diff --git a/app/code/Magento/Braintree/Observer/DataAssignObserver.php b/app/code/Magento/Braintree/Observer/DataAssignObserver.php index 512ea25c103b6..fb528e3554d23 100644 --- a/app/code/Magento/Braintree/Observer/DataAssignObserver.php +++ b/app/code/Magento/Braintree/Observer/DataAssignObserver.php @@ -7,6 +7,7 @@ use Magento\Framework\Event\Observer; use Magento\Payment\Observer\AbstractDataAssignObserver; +use Magento\Quote\Api\Data\PaymentInterface; /** * Class DataAssignObserver @@ -31,13 +32,19 @@ class DataAssignObserver extends AbstractDataAssignObserver public function execute(Observer $observer) { $data = $this->readDataArgument($observer); + + $additionalData = $data->getData(PaymentInterface::KEY_ADDITIONAL_DATA); + if (!is_array($additionalData)) { + return; + } + $paymentInfo = $this->readPaymentModelArgument($observer); foreach ($this->additionalInformationList as $additionalInformationKey) { - if ($data->getDataByKey($additionalInformationKey) !== null) { + if (isset($additionalData[$additionalInformationKey])) { $paymentInfo->setAdditionalInformation( $additionalInformationKey, - $data->getDataByKey($additionalInformationKey) + $additionalData[$additionalInformationKey] ); } } diff --git a/app/code/Magento/Braintree/Test/Unit/Observer/DataAssignObserverTest.php b/app/code/Magento/Braintree/Test/Unit/Observer/DataAssignObserverTest.php index 92e6820f44778..c14227d73d7bb 100644 --- a/app/code/Magento/Braintree/Test/Unit/Observer/DataAssignObserverTest.php +++ b/app/code/Magento/Braintree/Test/Unit/Observer/DataAssignObserverTest.php @@ -10,6 +10,7 @@ use Magento\Payment\Model\InfoInterface; use Magento\Payment\Observer\AbstractDataAssignObserver; use Magento\Braintree\Observer\DataAssignObserver; +use Magento\Quote\Api\Data\PaymentInterface; /** * Class DataAssignObserverTest @@ -30,8 +31,10 @@ public function testExecute() $paymentInfoModel = $this->getMock(InfoInterface::class); $dataObject = new DataObject( [ - 'payment_method_nonce' => self::PAYMENT_METHOD_NONCE, - 'device_data' => self::DEVICE_DATA, + PaymentInterface::KEY_ADDITIONAL_DATA => [ + 'payment_method_nonce' => self::PAYMENT_METHOD_NONCE, + 'device_data' => self::DEVICE_DATA + ] ] ); $observerContainer->expects(static::atLeastOnce()) diff --git a/app/code/Magento/Catalog/Block/Adminhtml/Category/Tab/Product.php b/app/code/Magento/Catalog/Block/Adminhtml/Category/Tab/Product.php index 41aad9086869a..976dd4c922263 100644 --- a/app/code/Magento/Catalog/Block/Adminhtml/Category/Tab/Product.php +++ b/app/code/Magento/Catalog/Block/Adminhtml/Category/Tab/Product.php @@ -104,8 +104,6 @@ protected function _prepareCollection() 'sku' )->addAttributeToSelect( 'price' - )->addStoreFilter( - $this->getRequest()->getParam('store') )->joinField( 'position', 'catalog_category_product', @@ -114,6 +112,10 @@ protected function _prepareCollection() 'category_id=' . (int)$this->getRequest()->getParam('id', 0), 'left' ); + $storeId = (int)$this->getRequest()->getParam('store', 0); + if ($storeId > 0) { + $collection->addStoreFilter($storeId); + } $this->setCollection($collection); if ($this->getCategory()->getProductsReadonly()) { diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Category/Move.php b/app/code/Magento/Catalog/Controller/Adminhtml/Category/Move.php index 6cfb6e3ba277c..ead95c544814a 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Category/Move.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Category/Move.php @@ -67,12 +67,12 @@ public function execute() throw new \Exception(__('Category is not available for requested store.')); } $category->move($parentNodeId, $prevNodeId); - } catch (\Magento\Framework\Exception\LocalizedException $e) { - $error = true; - $this->messageManager->addError(__('There was a category move error.')); } catch (\Magento\Framework\Exception\AlreadyExistsException $e) { $error = true; $this->messageManager->addError(__('There was a category move error. %1', $e->getMessage())); + } catch (\Magento\Framework\Exception\LocalizedException $e) { + $error = true; + $this->messageManager->addError($e->getMessage()); } catch (\Exception $e) { $error = true; $this->messageManager->addError(__('There was a category move error.')); diff --git a/app/code/Magento/Catalog/Model/Product/Copier.php b/app/code/Magento/Catalog/Model/Product/Copier.php index fb40cc75cdb35..129d8c0850db8 100644 --- a/app/code/Magento/Catalog/Model/Product/Copier.php +++ b/app/code/Magento/Catalog/Model/Product/Copier.php @@ -47,8 +47,10 @@ public function copy(\Magento\Catalog\Model\Product $product) $product->getWebsiteIds(); $product->getCategoryIds(); + /** @var \Magento\Catalog\Model\Product $duplicate */ $duplicate = $this->productFactory->create(); $duplicate->setData($product->getData()); + $duplicate->setOptions([]); $duplicate->setIsDuplicate(true); $duplicate->setOriginalId($product->getEntityId()); $duplicate->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_DISABLED); diff --git a/app/code/Magento/Catalog/Model/Product/Option/Type/File/Validator.php b/app/code/Magento/Catalog/Model/Product/Option/Type/File/Validator.php index d4b417edc32df..3b2f5ab73120f 100644 --- a/app/code/Magento/Catalog/Model/Product/Option/Type/File/Validator.php +++ b/app/code/Magento/Catalog/Model/Product/Option/Type/File/Validator.php @@ -38,7 +38,7 @@ public function __construct( \Magento\Framework\File\Size $fileSize ) { $this->scopeConfig = $scopeConfig; - $this->rootDirectory = $filesystem->getDirectoryRead(DirectoryList::ROOT); + $this->rootDirectory = $filesystem->getDirectoryRead(DirectoryList::MEDIA); $this->fileSize = $fileSize; } diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product.php b/app/code/Magento/Catalog/Model/ResourceModel/Product.php index 9c402ea6ec5cc..c0d81c53e623f 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product.php @@ -522,9 +522,6 @@ public function duplicate($oldId, $newId) )->where( $this->getLinkField() . ' = ?', $oldId - )->where( - 'store_id >= ?', - 0 ); $connection->query( @@ -532,7 +529,7 @@ public function duplicate($oldId, $newId) $select, $tableName, ['attribute_id', 'store_id', $this->getLinkField(), 'value'], - \Magento\Framework\DB\Adapter\AdapterInterface::INSERT_ON_DUPLICATE + \Magento\Framework\DB\Adapter\AdapterInterface::INSERT_IGNORE ) ); } @@ -541,7 +538,6 @@ public function duplicate($oldId, $newId) $statusAttribute = $this->getAttribute('status'); $statusAttributeId = $statusAttribute->getAttributeId(); $statusAttributeTable = $statusAttribute->getBackend()->getTable(); - $updateCond[] = 'store_id >= 0'; $updateCond[] = $connection->quoteInto($this->getLinkField() . ' = ?', $newId); $updateCond[] = $connection->quoteInto('attribute_id = ?', $statusAttributeId); $connection->update( diff --git a/app/code/Magento/Catalog/Model/Webapi/Product/Option/Type/File/Processor.php b/app/code/Magento/Catalog/Model/Webapi/Product/Option/Type/File/Processor.php index d4a424a1b4338..96e8b492b4e31 100644 --- a/app/code/Magento/Catalog/Model/Webapi/Product/Option/Type/File/Processor.php +++ b/app/code/Magento/Catalog/Model/Webapi/Product/Option/Type/File/Processor.php @@ -7,7 +7,6 @@ use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\Api\Data\ImageContentInterface; -use Magento\Catalog\Model\Product\Option\Type\File\ValidateFactory; use Magento\Framework\Api\ImageProcessor; use Magento\Framework\Filesystem; @@ -20,7 +19,7 @@ class Processor protected $imageProcessor; /** @var string */ - protected $destinationFolder = '/custom_options/quote'; + protected $destinationFolder = 'custom_options/quote'; /** * @param Filesystem $filesystem @@ -40,9 +39,8 @@ public function __construct( */ protected function saveFile(ImageContentInterface $imageContent) { - $uri = $this->filesystem->getUri(DirectoryList::MEDIA); $filePath = $this->imageProcessor->processImageContent($this->destinationFolder, $imageContent); - return $uri . $this->destinationFolder . $filePath; + return $this->destinationFolder . $filePath; } /** @@ -54,8 +52,8 @@ public function processFileContent(ImageContentInterface $imageContent) { $filePath = $this->saveFile($imageContent); - $fileAbsolutePath = $this->filesystem->getDirectoryRead(DirectoryList::ROOT)->getAbsolutePath($filePath); - $fileHash = md5($this->filesystem->getDirectoryRead(DirectoryList::ROOT)->readFile($filePath)); + $fileAbsolutePath = $this->filesystem->getDirectoryRead(DirectoryList::MEDIA)->getAbsolutePath($filePath); + $fileHash = md5($this->filesystem->getDirectoryRead(DirectoryList::MEDIA)->readFile($filePath)); $imageSize = getimagesize($fileAbsolutePath); $result = [ 'type' => $imageContent->getType(), diff --git a/app/code/Magento/Catalog/Model/Webapi/Product/Option/Type/File/Validator.php b/app/code/Magento/Catalog/Model/Webapi/Product/Option/Type/File/Validator.php deleted file mode 100644 index b95a14c963b2e..0000000000000 --- a/app/code/Magento/Catalog/Model/Webapi/Product/Option/Type/File/Validator.php +++ /dev/null @@ -1,52 +0,0 @@ -fileFullPath = null; - $this->fileRelativePath = null; - $this->initFilePath($optionValue); - - if ($this->fileFullPath === null) { - return false; - } - - $validatorChain = $this->validateFactory->create(); - try { - $validatorChain = $this->buildImageValidator($validatorChain, $option, $this->fileFullPath); - } catch (\Magento\Framework\Exception\InputException $notImage) { - return false; - } - - $result = false; - if ($validatorChain->isValid($this->fileFullPath) - && $this->rootDirectory->isReadable($this->fileRelativePath) - ) { - $result = true; - } elseif ($validatorChain->getErrors()) { - $errors = $this->getValidatorErrors($validatorChain->getErrors(), $optionValue, $option); - throw new \Magento\Framework\Exception\LocalizedException(__(implode("\n", $errors))); - } else { - throw new \Magento\Framework\Exception\LocalizedException( - __('Please specify product\'s required option(s).') - ); - } - return $result; - } -} diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/CopierTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/CopierTest.php index 09149788022db..3ce525c20c649 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Product/CopierTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/CopierTest.php @@ -79,6 +79,7 @@ public function testCopy() [ '__wakeup', 'setData', + 'setOptions', 'setIsDuplicate', 'setOriginalId', 'setStatus', @@ -97,6 +98,7 @@ public function testCopy() ); $this->productFactoryMock->expects($this->once())->method('create')->will($this->returnValue($duplicateMock)); + $duplicateMock->expects($this->once())->method('setOptions')->with([]); $duplicateMock->expects($this->once())->method('setIsDuplicate')->with(true); $duplicateMock->expects($this->once())->method('setOriginalId')->with(1); $duplicateMock->expects( diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/Gallery/GalleryManagementTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/Gallery/GalleryManagementTest.php index bb1041824ab7c..0e4d357164481 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Product/Gallery/GalleryManagementTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/Gallery/GalleryManagementTest.php @@ -97,7 +97,7 @@ public function testCreateWithCannotSaveException() $productSku = 'mediaProduct'; $entryContentMock = $this->getMockBuilder('\Magento\Framework\Api\Data\ImageContentInterface') ->disableOriginalConstructor() - ->getMock();; + ->getMock(); $this->mediaGalleryEntryMock->expects($this->any())->method('getContent')->willReturn($entryContentMock); $this->productRepositoryMock->expects($this->once()) ->method('get') diff --git a/app/code/Magento/Catalog/Test/Unit/Webapi/Product/Option/Type/File/ValidatorTest.php b/app/code/Magento/Catalog/Test/Unit/Webapi/Product/Option/Type/File/ValidatorTest.php deleted file mode 100644 index 898a658e69729..0000000000000 --- a/app/code/Magento/Catalog/Test/Unit/Webapi/Product/Option/Type/File/ValidatorTest.php +++ /dev/null @@ -1,223 +0,0 @@ -scopeConfig = $this->getMockForAbstractClass( - 'Magento\Framework\App\Config\ScopeConfigInterface', - [], - '', - false - ); - $this->filesystem = $this->getMock( - 'Magento\Framework\Filesystem', - [], - [], - '', - false - ); - $this->fileSize = $this->getMock( - 'Magento\Framework\File\Size', - [], - [], - '', - false - ); - $this->coreFileStorageDatabase = $this->getMock( - 'Magento\MediaStorage\Helper\File\Storage\Database', - [], - [], - '', - false - ); - $this->validateFactory = $this->getMock( - 'Magento\Catalog\Model\Product\Option\Type\File\ValidateFactory', - [], - [], - '', - false - ); - $this->option = $this->getMock( - 'Magento\Catalog\Model\Product\Option', - [], - [], - '', - false - ); - $this->directoryRead = $this->getMockForAbstractClass( - 'Magento\Framework\Filesystem\Directory\ReadInterface', - [], - '', - false - ); - $this->zendValidator = $this->getMock( - 'Zend_Validate', - [], - [], - '', - false - ); - - $this->filesystem->expects($this->once()) - ->method('getDirectoryRead') - ->with('base') - ->willReturn($this->directoryRead); - - $this->validator = new Validator( - $this->scopeConfig, - $this->filesystem, - $this->fileSize, - $this->coreFileStorageDatabase, - $this->validateFactory - ); - } - - public function testValidateWithoutOptionValue() - { - $this->assertFalse($this->validator->validate('', $this->option)); - } - - public function testValidateWithInvalidOptionValue() - { - $this->assertFalse($this->validator->validate([], $this->option)); - } - - protected function prepare() - { - $relativePath = '/custom_options/quote/file'; - $absolutePath = '/absolute/path' . $relativePath; - - $this->directoryRead->expects($this->once()) - ->method('isFile') - ->with('/custom_options/quote/file') - ->willReturn(true); - $this->directoryRead->expects($this->once()) - ->method('getAbsolutePath') - ->with('/custom_options/quote/file') - ->willReturn($absolutePath); - $this->validateFactory->expects($this->once()) - ->method('create') - ->willReturn($this->zendValidator); - $this->option->expects($this->once()) - ->method('getImageSizeX') - ->willReturn(0); - $this->option->expects($this->once()) - ->method('getImageSizeY') - ->willReturn(0); - $this->option->expects($this->once()) - ->method('getFileExtension') - ->willReturn(''); - $this->scopeConfig->expects($this->once()) - ->method('getValue') - ->with('catalog/custom_options/forbidden_extensions', \Magento\Store\Model\ScopeInterface::SCOPE_STORE) - ->willReturn(''); - $this->fileSize->expects($this->once()) - ->method('getMaxFileSize') - ->willReturn(9999999); - $this->zendValidator->expects($this->any()) - ->method('addValidator'); - $this->zendValidator->expects($this->once()) - ->method('isValid') - ->with($absolutePath) - ->willReturn(true); - } - - public function testValidate() - { - $relativePath = '/custom_options/quote/file'; - $optionValues = [ - 'quote_path' => '/custom_options/quote/file' - ]; - $this->prepare(); - - $this->directoryRead->expects($this->once()) - ->method('isReadable') - ->with($relativePath) - ->willReturn(true); - $this->assertTrue($this->validator->validate($optionValues, $this->option)); - } - - /** - * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage The file 'File Title' for 'Option Title' has an invalid extension. - */ - public function testValidateWithInvalidFile() - { - $relativePath = '/custom_options/quote/file'; - $optionValues = [ - 'quote_path' => '/custom_options/quote/file', - 'title' => 'File Title' - ]; - $this->prepare(); - - $this->directoryRead->expects($this->once()) - ->method('isReadable') - ->with($relativePath) - ->willReturn(false); - $this->option->expects($this->once()) - ->method('getTitle') - ->willReturn('Option Title'); - $this->zendValidator->expects($this->at(2)) - ->method('getErrors') - ->willReturn(true); - $this->zendValidator->expects($this->at(3)) - ->method('getErrors') - ->willReturn([\Zend_Validate_File_ExcludeExtension::FALSE_EXTENSION]); - $this->validator->validate($optionValues, $this->option); - } - - /** - * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage Please specify product's required option(s). - */ - public function testValidateWithUnreadableFile() - { - $relativePath = '/custom_options/quote/file'; - $optionValues = [ - 'quote_path' => '/custom_options/quote/file', - 'title' => 'File Title' - ]; - $this->prepare(); - - $this->directoryRead->expects($this->once()) - ->method('isReadable') - ->with($relativePath) - ->willReturn(false); - $this->validator->validate($optionValues, $this->option); - } -} diff --git a/app/code/Magento/Catalog/etc/webapi_rest/di.xml b/app/code/Magento/Catalog/etc/webapi_rest/di.xml index 2dbff8b2afe3b..8606cd8de1136 100644 --- a/app/code/Magento/Catalog/etc/webapi_rest/di.xml +++ b/app/code/Magento/Catalog/etc/webapi_rest/di.xml @@ -8,7 +8,6 @@ - diff --git a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/category/tree.phtml b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/category/tree.phtml index 980ab6ac45805..135864e957a26 100644 --- a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/category/tree.phtml +++ b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/category/tree.phtml @@ -493,6 +493,9 @@ } else { $(obj.tree.container.dom).trigger('categoryMove.tree'); } + $('.page-main-actions').next('.messages').remove(); + $('.page-main-actions').next('#messages').remove(); + $('.page-main-actions').after(data.messages); }).fail(function (jqXHR, textStatus) { if (window.console) { console.log(textStatus); diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/view/opengraph/general.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/view/opengraph/general.phtml index 238649265821f..39170817ec78e 100644 --- a/app/code/Magento/Catalog/view/frontend/templates/product/view/opengraph/general.phtml +++ b/app/code/Magento/Catalog/view/frontend/templates/product/view/opengraph/general.phtml @@ -10,10 +10,10 @@ ?> - - - - + + + + getProduct()->getFinalPrice()):?> getChildHtml('meta.currency'); ?> diff --git a/app/code/Magento/CatalogSearch/Model/ResourceModel/Advanced/Collection.php b/app/code/Magento/CatalogSearch/Model/ResourceModel/Advanced/Collection.php index 7b7bb4eea0019..50c38bb335987 100644 --- a/app/code/Magento/CatalogSearch/Model/ResourceModel/Advanced/Collection.php +++ b/app/code/Magento/CatalogSearch/Model/ResourceModel/Advanced/Collection.php @@ -8,7 +8,11 @@ use Magento\Catalog\Model\Product; use Magento\Framework\Api\FilterBuilder; use Magento\Framework\Api\Search\SearchCriteriaBuilder; +use Magento\Framework\Api\Search\SearchResultFactory; +use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Search\Adapter\Mysql\TemporaryStorage; +use Magento\Framework\Search\Request\EmptyRequestDataException; +use Magento\Framework\Search\Request\NonExistingRequestNameException; /** * Collection Advanced @@ -39,6 +43,11 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection */ private $searchCriteriaBuilder; + /** + * @var SearchResultFactory + */ + private $searchResultFactory; + /** * @var FilterBuilder */ @@ -69,6 +78,7 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection * @param \Magento\Search\Model\SearchEngine $searchEngine * @param \Magento\Framework\Search\Adapter\Mysql\TemporaryStorageFactory $temporaryStorageFactory * @param \Zend_Db_Adapter_Abstract $connection + * @param SearchResultFactory $searchResultFactory * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -94,11 +104,16 @@ public function __construct( \Magento\CatalogSearch\Model\Advanced\Request\Builder $requestBuilder, \Magento\Search\Model\SearchEngine $searchEngine, \Magento\Framework\Search\Adapter\Mysql\TemporaryStorageFactory $temporaryStorageFactory, - $connection = null + $connection = null, + SearchResultFactory $searchResultFactory = null ) { $this->requestBuilder = $requestBuilder; $this->searchEngine = $searchEngine; $this->temporaryStorageFactory = $temporaryStorageFactory; + if ($searchResultFactory === null) { + $this->searchResultFactory = \Magento\Framework\App\ObjectManager::getInstance() + ->get('Magento\Framework\Api\Search\SearchResultFactory'); + } parent::__construct( $entityFactory, $logger, @@ -152,8 +167,15 @@ protected function _renderFiltersBefore() } $searchCriteria = $this->getSearchCriteriaBuilder()->create(); $searchCriteria->setRequestName('advanced_search_container'); - $searchResult = $this->getSearch()->search($searchCriteria); - + try { + $searchResult = $this->getSearch()->search($searchCriteria); + } catch (EmptyRequestDataException $e) { + /** @var \Magento\Framework\Api\Search\SearchResultInterface $searchResult */ + $searchResult = $this->searchResultFactory->create()->setItems([]); + } catch (NonExistingRequestNameException $e) { + $this->_logger->error($e->getMessage()); + throw new LocalizedException(__('Sorry, something went wrong. You can find out more in the error log.')); + } $temporaryStorage = $this->temporaryStorageFactory->create(); $table = $temporaryStorage->storeApiDocuments($searchResult->getItems()); diff --git a/app/code/Magento/CatalogSearch/Model/ResourceModel/Fulltext/Collection.php b/app/code/Magento/CatalogSearch/Model/ResourceModel/Fulltext/Collection.php index ba0729d0d82f1..1d3749f4a95a9 100644 --- a/app/code/Magento/CatalogSearch/Model/ResourceModel/Fulltext/Collection.php +++ b/app/code/Magento/CatalogSearch/Model/ResourceModel/Fulltext/Collection.php @@ -9,6 +9,10 @@ use Magento\Framework\Exception\StateException; use Magento\Framework\Search\Adapter\Mysql\TemporaryStorage; use Magento\Framework\Search\Response\QueryResponse; +use Magento\Framework\Search\Request\EmptyRequestDataException; +use Magento\Framework\Search\Request\NonExistingRequestNameException; +use Magento\Framework\Api\Search\SearchResultFactory; +use Magento\Framework\Exception\LocalizedException; use Magento\Framework\App\ObjectManager; /** @@ -78,6 +82,11 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection */ private $searchResult; + /** + * @var SearchResultFactory + */ + private $searchResultFactory; + /** * @var \Magento\Framework\Api\FilterBuilder */ @@ -109,6 +118,7 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection * @param \Magento\Framework\Search\Adapter\Mysql\TemporaryStorageFactory $temporaryStorageFactory * @param \Magento\Framework\DB\Adapter\AdapterInterface $connection * @param string $searchRequestName + * @param SearchResultFactory $searchResultFactory * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -136,9 +146,14 @@ public function __construct( \Magento\Search\Model\SearchEngine $searchEngine, \Magento\Framework\Search\Adapter\Mysql\TemporaryStorageFactory $temporaryStorageFactory, \Magento\Framework\DB\Adapter\AdapterInterface $connection = null, - $searchRequestName = 'catalog_view_container' + $searchRequestName = 'catalog_view_container', + SearchResultFactory $searchResultFactory = null ) { $this->queryFactory = $catalogSearchData; + if ($searchResultFactory === null) { + $this->searchResultFactory = \Magento\Framework\App\ObjectManager::getInstance() + ->get('Magento\Framework\Api\Search\SearchResultFactory'); + } parent::__construct( $entityFactory, $logger, @@ -307,7 +322,15 @@ protected function _renderFiltersBefore() $searchCriteria = $this->searchCriteriaBuilder->create(); $searchCriteria->setRequestName($this->searchRequestName); - $this->searchResult = $this->search->search($searchCriteria); + try { + $this->searchResult = $this->getSearch()->search($searchCriteria); + } catch (EmptyRequestDataException $e) { + /** @var \Magento\Framework\Api\Search\SearchResultInterface $searchResult */ + $this->searchResult = $this->searchResultFactory->create()->setItems([]); + } catch (NonExistingRequestNameException $e) { + $this->_logger->error($e->getMessage()); + throw new LocalizedException(__('Sorry, something went wrong. You can find out more in the error log.')); + } $temporaryStorage = $this->temporaryStorageFactory->create(); $table = $temporaryStorage->storeApiDocuments($this->searchResult->getItems()); diff --git a/app/code/Magento/Checkout/Model/Cart.php b/app/code/Magento/Checkout/Model/Cart.php index 80cdf61499197..4ce23c9c7f709 100644 --- a/app/code/Magento/Checkout/Model/Cart.php +++ b/app/code/Magento/Checkout/Model/Cart.php @@ -257,7 +257,11 @@ public function addOrderItem($orderItem, $qtyFlag = null) if ($orderItem->getParentItem() === null) { $storeId = $this->_storeManager->getStore()->getId(); try { - $product = $this->productRepository->getById($orderItem->getProductId(), false, $storeId); + /** + * We need to reload product in this place, because products + * with the same id may have different sets of order attributes. + */ + $product = $this->productRepository->getById($orderItem->getProductId(), false, $storeId, true); } catch (NoSuchEntityException $e) { return $this; } diff --git a/app/code/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/Tab/Variations/Config/Matrix.php b/app/code/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/Tab/Variations/Config/Matrix.php index 62a0dd60e4941..cc46ce6ca3a93 100644 --- a/app/code/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/Tab/Variations/Config/Matrix.php +++ b/app/code/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/Tab/Variations/Config/Matrix.php @@ -321,6 +321,7 @@ protected function prepareVariations() if ($variations) { $usedProductAttributes = $this->getUsedAttributes(); $productByUsedAttributes = $this->getAssociatedProducts(); + $configurableAttributes = $this->getAttributes(); foreach ($variations as $variation) { $attributeValues = []; foreach ($usedProductAttributes as $attribute) { @@ -337,7 +338,7 @@ protected function prepareVariations() 'code' => $attribute->getAttributeCode(), 'label' => $attribute->getStoreLabel(), 'id' => $attribute->getAttributeId(), - 'position' => $attribute->getPosition(), + 'position' => $configurableAttributes[$attribute->getAttributeId()]['position'], 'chosen' => [], ]; foreach ($attribute->getOptions() as $option) { diff --git a/app/code/Magento/ConfigurableProduct/Model/ConfigurableAttributeData.php b/app/code/Magento/ConfigurableProduct/Model/ConfigurableAttributeData.php index 6c8eae58981a8..be39893145626 100644 --- a/app/code/Magento/ConfigurableProduct/Model/ConfigurableAttributeData.php +++ b/app/code/Magento/ConfigurableProduct/Model/ConfigurableAttributeData.php @@ -35,6 +35,7 @@ public function getAttributesData(Product $product, array $options = []) 'code' => $productAttribute->getAttributeCode(), 'label' => $productAttribute->getStoreLabel($product->getStoreId()), 'options' => $attributeOptionsData, + 'position' => $attribute->getPosition(), ]; $defaultValues[$attributeId] = $this->getAttributeConfigValue($attributeId, $product); } diff --git a/app/code/Magento/ConfigurableProduct/Test/Unit/Model/ConfigurableAttributeDataTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Model/ConfigurableAttributeDataTest.php index 8b4fa0646a3b0..e0d4eaaae913a 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Unit/Model/ConfigurableAttributeDataTest.php +++ b/app/code/Magento/ConfigurableProduct/Test/Unit/Model/ConfigurableAttributeDataTest.php @@ -67,12 +67,14 @@ public function testPrepareJsonAttributes() ['value_index' => 'option_id_1', 'label' => 'label_1'], ['value_index' => 'option_id_2', 'label' => 'label_2'], ]; + $position = 2; $expected = [ 'attributes' => [ $attributeId => [ 'id' => $attributeId, 'code' => 'test_attribute', 'label' => 'Test', + 'position' => $position, 'options' => [ 0 => [ 'id' => 'option_id_1', @@ -108,11 +110,15 @@ public function testPrepareJsonAttributes() $attributeMock = $this->getMockBuilder('Magento\ConfigurableProduct\Model\Product\Type\Configurable\Attribute') ->disableOriginalConstructor() - ->setMethods(['getProductAttribute', '__wakeup', 'getLabel', 'getOptions', 'getAttributeId']) + ->setMethods(['getProductAttribute', '__wakeup', 'getLabel', 'getOptions', 'getAttributeId', 'getPosition']) ->getMock(); $attributeMock->expects($this->once()) ->method('getProductAttribute') ->willReturn($productAttributeMock); + $attributeMock->expects($this->once()) + ->method('getPosition') + ->willReturn($position); + $this->product->expects($this->once())->method('getStoreId')->willReturn($storeId); $productAttributeMock->expects($this->once()) ->method('getStoreLabel') diff --git a/app/code/Magento/ConfigurableProduct/Ui/DataProvider/Product/Form/Modifier/Data/AssociatedProducts.php b/app/code/Magento/ConfigurableProduct/Ui/DataProvider/Product/Form/Modifier/Data/AssociatedProducts.php index 9d142a6693251..da7a0d7a3d9da 100644 --- a/app/code/Magento/ConfigurableProduct/Ui/DataProvider/Product/Form/Modifier/Data/AssociatedProducts.php +++ b/app/code/Magento/ConfigurableProduct/Ui/DataProvider/Product/Form/Modifier/Data/AssociatedProducts.php @@ -231,6 +231,7 @@ protected function prepareVariations() $usedProductAttributes = $this->getUsedAttributes(); $productByUsedAttributes = $this->getAssociatedProducts(); $currency = $this->localeCurrency->getCurrency($this->locator->getBaseCurrencyCode()); + $configurableAttributes = $this->getAttributes(); foreach ($variations as $variation) { $attributeValues = []; foreach ($usedProductAttributes as $attribute) { @@ -247,7 +248,7 @@ protected function prepareVariations() 'code' => $attribute->getAttributeCode(), 'label' => $attribute->getStoreLabel(), 'id' => $attribute->getAttributeId(), - 'position' => $attribute->getPosition(), + 'position' => $configurableAttributes[$attribute->getAttributeId()]['position'], 'chosen' => [], ]; foreach ($attribute->getOptions() as $option) { diff --git a/app/code/Magento/Indexer/Model/Source/ServiceSource.php b/app/code/Magento/Indexer/Model/Source/ServiceSource.php index 580db888b4a5f..eac789e7c0cf4 100644 --- a/app/code/Magento/Indexer/Model/Source/ServiceSource.php +++ b/app/code/Magento/Indexer/Model/Source/ServiceSource.php @@ -69,7 +69,7 @@ private function getRequestedFields(SearchResults $list, array $fields) foreach ($list->getItems() as $key => $item) { foreach (array_keys($fields) as $fieldName) { if (!isset($item[$fieldName])) { - throw new NotFoundException(__("Field {$fieldName} not found")); + throw new NotFoundException(__("Field '%1' not found", $fieldName)); } $requestedData[$key][$fieldName] = $item[$fieldName]; diff --git a/app/code/Magento/OfflinePayments/Model/Purchaseorder.php b/app/code/Magento/OfflinePayments/Model/Purchaseorder.php index b209af925a9db..52eee8df4ba78 100644 --- a/app/code/Magento/OfflinePayments/Model/Purchaseorder.php +++ b/app/code/Magento/OfflinePayments/Model/Purchaseorder.php @@ -47,10 +47,6 @@ class Purchaseorder extends \Magento\Payment\Model\Method\AbstractMethod */ public function assignData(\Magento\Framework\DataObject $data) { - if (!$data instanceof \Magento\Framework\DataObject) { - $data = new \Magento\Framework\DataObject($data); - } - $this->getInfoInstance()->setPoNumber($data->getPoNumber()); return $this; } diff --git a/app/code/Magento/Payment/Model/Info.php b/app/code/Magento/Payment/Model/Info.php index c98f2c98f3983..6f61ccdd02cad 100644 --- a/app/code/Magento/Payment/Model/Info.php +++ b/app/code/Magento/Payment/Model/Info.php @@ -220,9 +220,6 @@ protected function _initAdditionalInformation() { $additionalInfo = $this->_getData('additional_information'); if (empty($this->_additionalInformation) && $additionalInfo) { - if (!is_array($additionalInfo)) { - $additionalInfo = unserialize($additionalInfo); - } $this->_additionalInformation = $additionalInfo; } } diff --git a/app/code/Magento/Payment/Model/Method/AbstractMethod.php b/app/code/Magento/Payment/Model/Method/AbstractMethod.php index 57128e37dde9b..24b543ca02d62 100644 --- a/app/code/Magento/Payment/Model/Method/AbstractMethod.php +++ b/app/code/Magento/Payment/Model/Method/AbstractMethod.php @@ -21,6 +21,7 @@ * @SuppressWarnings(PHPMD.ExcessivePublicCount) * @SuppressWarnings(PHPMD.TooManyFields) * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @deprecated */ abstract class AbstractMethod extends \Magento\Framework\Model\AbstractExtensibleModel implements MethodInterface, @@ -769,12 +770,6 @@ public function getConfigData($field, $storeId = null) */ public function assignData(\Magento\Framework\DataObject $data) { - if (is_array($data)) { - $this->getInfoInstance()->addData($data); - } elseif ($data instanceof \Magento\Framework\DataObject) { - $this->getInfoInstance()->addData($data->getData()); - } - $this->_eventManager->dispatch( 'payment_method_assign_data_' . $this->getCode(), [ diff --git a/app/code/Magento/Payment/Test/Unit/Model/InfoTest.php b/app/code/Magento/Payment/Test/Unit/Model/InfoTest.php index 22ebf692706b3..72a6e3eda5507 100644 --- a/app/code/Magento/Payment/Test/Unit/Model/InfoTest.php +++ b/app/code/Magento/Payment/Test/Unit/Model/InfoTest.php @@ -90,7 +90,6 @@ public function ccKeysDataProvider() ]; } - public function testGetMethodInstanceWithRealMethod() { $method = 'real_method'; @@ -108,7 +107,6 @@ public function testGetMethodInstanceWithRealMethod() $this->info->getMethodInstance(); } - public function testGetMethodInstanceWithUnrealMethod() { $method = 'unreal_method'; @@ -131,7 +129,6 @@ public function testGetMethodInstanceWithUnrealMethod() $this->info->getMethodInstance(); } - /** * @expectedException \Magento\Framework\Exception\LocalizedException * @expectedExceptionMessage The payment method you requested is not available. @@ -141,8 +138,7 @@ public function testGetMethodInstanceWithNoMethod() $this->info->setData('method', false); $this->info->getMethodInstance(); } - - + public function testGetMethodInstanceRequestedMethod() { $code = 'real_method'; @@ -251,9 +247,9 @@ public function testHasAdditionalInformation() public function testInitAdditionalInformationWithUnserialize() { - $data = serialize(['key1' => 'data1', 'key2' => 'data2']); + $data = ['key1' => 'data1', 'key2' => 'data2']; $this->info->setData('additional_information', $data); - $this->assertEquals(unserialize($data), $this->info->getAdditionalInformation()); + $this->assertEquals($data, $this->info->getAdditionalInformation()); } } diff --git a/app/code/Magento/Payment/Test/Unit/Model/Method/AbstractMethodTest.php b/app/code/Magento/Payment/Test/Unit/Model/Method/AbstractMethodTest.php index 1504aff5308f8..22c35df17e897 100644 --- a/app/code/Magento/Payment/Test/Unit/Model/Method/AbstractMethodTest.php +++ b/app/code/Magento/Payment/Test/Unit/Model/Method/AbstractMethodTest.php @@ -5,6 +5,9 @@ */ namespace Magento\Payment\Test\Unit\Model\Method; +use Magento\Framework\DataObject; +use Magento\Payment\Model\InfoInterface; +use Magento\Payment\Observer\AbstractDataAssignObserver; use Magento\Store\Model\ScopeInterface; use Magento\Payment\Test\Unit\Model\Method\AbstractMethod\Stub; @@ -65,7 +68,7 @@ protected function setUp() $helper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->payment = $helper->getObject( - 'Magento\Payment\Test\Unit\Model\Method\AbstractMethod\Stub', + Stub::class, [ 'scopeConfig' => $this->scopeConfigMock, 'context' => $contextMock, @@ -114,6 +117,37 @@ public function testIsAvailable($result) $this->assertEquals($result, $this->payment->isAvailable($this->quoteMock)); } + public function testAssignData() + { + $data = new DataObject(); + $paymentInfo = $this->getMock(InfoInterface::class); + + $this->payment->setInfoInstance($paymentInfo); + + $eventData = [ + AbstractDataAssignObserver::METHOD_CODE => $this, + AbstractDataAssignObserver::MODEL_CODE => $paymentInfo, + AbstractDataAssignObserver::DATA_CODE => $data + ]; + + $this->eventManagerMock->expects(static::exactly(2)) + ->method('dispatch') + ->willReturnMap( + [ + [ + 'payment_method_assign_data_' . Stub::STUB_CODE, + $eventData + ], + [ + 'payment_method_assign_data', + $eventData + ] + ] + ); + + $this->payment->assignData($data); + } + /** * @return array */ diff --git a/app/code/Magento/Paypal/Model/Express.php b/app/code/Magento/Paypal/Model/Express.php index a10a2654bf529..80c9ef0625d96 100644 --- a/app/code/Magento/Paypal/Model/Express.php +++ b/app/code/Magento/Paypal/Model/Express.php @@ -8,6 +8,7 @@ use Magento\Paypal\Model\Api\Nvp; use Magento\Paypal\Model\Api\ProcessableException as ApiProcessableException; use Magento\Paypal\Model\Express\Checkout as ExpressCheckout; +use Magento\Quote\Api\Data\PaymentInterface; use Magento\Sales\Api\Data\OrderPaymentInterface; use Magento\Sales\Model\Order\Payment; use Magento\Sales\Model\Order\Payment\Transaction; @@ -667,14 +668,24 @@ public function getApi() */ public function assignData(\Magento\Framework\DataObject $data) { - $result = parent::assignData($data); - $key = ExpressCheckout::PAYMENT_INFO_TRANSPORT_BILLING_AGREEMENT; - if (is_array($data)) { - $this->getInfoInstance()->setAdditionalInformation($key, isset($data[$key]) ? $data[$key] : null); - } elseif ($data instanceof \Magento\Framework\DataObject) { - $this->getInfoInstance()->setAdditionalInformation($key, $data->getData($key)); + parent::assignData($data); + + $additionalData = $data->getData(PaymentInterface::KEY_ADDITIONAL_DATA); + + if ( + !is_array($additionalData) + || !isset($additionalData[ExpressCheckout::PAYMENT_INFO_TRANSPORT_BILLING_AGREEMENT]) + ) { + return $this; } - return $result; + + $this->getInfoInstance() + ->setAdditionalInformation( + ExpressCheckout::PAYMENT_INFO_TRANSPORT_BILLING_AGREEMENT, + $additionalData[ExpressCheckout::PAYMENT_INFO_TRANSPORT_BILLING_AGREEMENT] + ); + + return $this; } /** diff --git a/app/code/Magento/Paypal/Model/Payment/Method/Billing/AbstractAgreement.php b/app/code/Magento/Paypal/Model/Payment/Method/Billing/AbstractAgreement.php index f6f6154012a77..42894ddeec49d 100644 --- a/app/code/Magento/Paypal/Model/Payment/Method/Billing/AbstractAgreement.php +++ b/app/code/Magento/Paypal/Model/Payment/Method/Billing/AbstractAgreement.php @@ -5,6 +5,9 @@ */ namespace Magento\Paypal\Model\Payment\Method\Billing; +use Magento\Paypal\Model\Billing\Agreement; +use Magento\Quote\Api\Data\PaymentInterface; + /** * Billing Agreement Payment Method Abstract model * @@ -110,34 +113,35 @@ public function isAvailable(\Magento\Quote\Api\Data\CartInterface $quote = null) */ public function assignData(\Magento\Framework\DataObject $data) { - $result = parent::assignData($data); - - $key = self::TRANSPORT_BILLING_AGREEMENT_ID; - $id = false; - if (is_array($data) && isset($data[$key])) { - $id = $data[$key]; - } elseif ($data instanceof \Magento\Framework\DataObject && $data->getData($key)) { - $id = $data->getData($key); + parent::assignData($data); + + $additionalData = $data->getData(PaymentInterface::KEY_ADDITIONAL_DATA); + + if (!is_array($additionalData) || !isset($additionalData[self::TRANSPORT_BILLING_AGREEMENT_ID])) { + return $this; } - if ($id) { - $info = $this->getInfoInstance(); - $ba = $this->_agreementFactory->create()->load($id); - if ($ba->getId() && $ba->getCustomerId() == $info->getQuote()->getCustomerId()) { - $info->setAdditionalInformation( - $key, - $id - )->setAdditionalInformation( - self::PAYMENT_INFO_REFERENCE_ID, - $ba->getReferenceId() - ); - } + + $id = $additionalData[self::TRANSPORT_BILLING_AGREEMENT_ID]; + if (!$id || !is_numeric($id)) { + return $this; } - return $result; + + $info = $this->getInfoInstance(); + /** @var Agreement $ba */ + $ba = $this->_agreementFactory->create(); + $ba->load($id); + + if ($ba->getId() && $ba->getCustomerId() == $info->getQuote()->getCustomerId()) { + $info->setAdditionalInformation(self::TRANSPORT_BILLING_AGREEMENT_ID, $id); + $info->setAdditionalInformation(self::PAYMENT_INFO_REFERENCE_ID, $ba->getReferenceId()); + } + + return $this; } /** * @param object $quote - * @return void + * @return bool */ abstract protected function _isAvailable($quote); } diff --git a/app/code/Magento/Paypal/Observer/PayflowProAddCcData.php b/app/code/Magento/Paypal/Observer/PayflowProAddCcData.php index 857322608e0d3..92980e46ed8d7 100644 --- a/app/code/Magento/Paypal/Observer/PayflowProAddCcData.php +++ b/app/code/Magento/Paypal/Observer/PayflowProAddCcData.php @@ -8,6 +8,7 @@ use Magento\Framework\Event\Observer; use Magento\Payment\Observer\AbstractDataAssignObserver; use Magento\Paypal\Model\Payflow\Transparent; +use Magento\Quote\Api\Data\PaymentInterface; class PayflowProAddCcData extends AbstractDataAssignObserver { @@ -29,7 +30,13 @@ public function execute(\Magento\Framework\Event\Observer $observer) { $dataObject = $this->readDataArgument($observer); - $ccData = array_intersect_key($dataObject->getData(), array_flip($this->ccKeys)); + $additionalData = $dataObject->getData(PaymentInterface::KEY_ADDITIONAL_DATA); + + if (!is_array($additionalData)) { + return; + } + + $ccData = array_intersect_key($additionalData, array_flip($this->ccKeys)); if (count($ccData) !== count($this->ccKeys)) { return; } @@ -39,6 +46,11 @@ public function execute(\Magento\Framework\Event\Observer $observer) Transparent::CC_DETAILS, $this->sortCcData($ccData) ); + + // CC data should be stored explicitly + foreach ($ccData as $ccKey => $ccValue) { + $paymentModel->setData($ccKey, $ccValue); + } } /** diff --git a/app/code/Magento/Paypal/Test/Unit/Model/ExpressTest.php b/app/code/Magento/Paypal/Test/Unit/Model/ExpressTest.php index 75f4c14d8517e..6abf963cf7b26 100644 --- a/app/code/Magento/Paypal/Test/Unit/Model/ExpressTest.php +++ b/app/code/Magento/Paypal/Test/Unit/Model/ExpressTest.php @@ -5,7 +5,13 @@ */ namespace Magento\Paypal\Test\Unit\Model; +use Magento\Framework\DataObject; +use Magento\Framework\Event\ManagerInterface; +use Magento\Payment\Model\InfoInterface; +use Magento\Payment\Observer\AbstractDataAssignObserver; use Magento\Paypal\Model\Api\ProcessableException as ApiProcessableException; +use Magento\Paypal\Model\Express; +use Magento\Quote\Api\Data\PaymentInterface; class ExpressTest extends \PHPUnit_Framework_TestCase { @@ -55,6 +61,11 @@ class ExpressTest extends \PHPUnit_Framework_TestCase */ protected $transactionBuilder; + /** + * @var ManagerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $eventManagerMock; + protected function setUp() { $this->_checkoutSession = $this->getMock( @@ -79,24 +90,28 @@ protected function setUp() false ); $this->_pro = $this->getMock( - 'Magento\Paypal\Model\ProFactory', - ['create', 'setMethod', 'getApi', 'importPaymentInfo', 'resetApi'], + 'Magento\Paypal\Model\Pro', + ['setMethod', 'getApi', 'importPaymentInfo', 'resetApi'], [], '', false ); - $this->_pro->expects($this->any())->method('create')->will($this->returnSelf()); + $this->eventManagerMock = $this->getMockBuilder(ManagerInterface::class) + ->setMethods(['dispatch']) + ->getMockForAbstractClass(); + + $this->_pro->expects($this->any())->method('getApi')->will($this->returnValue($this->_nvp)); $this->_helper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); } public function testSetApiProcessableErrors() { $this->_nvp->expects($this->once())->method('setProcessableErrors')->with($this->errorCodes); - $this->_pro->expects($this->any())->method('getApi')->will($this->returnValue($this->_nvp)); + $this->_model = $this->_helper->getObject( 'Magento\Paypal\Model\Express', [ - 'proFactory' => $this->_pro, + 'data' => [$this->_pro], 'checkoutSession' => $this->_checkoutSession, 'transactionBuilder' => $this->transactionBuilder ] @@ -110,7 +125,7 @@ public function testOrder() $this->_nvp->expects($this->any())->method('setCurrencyCode')->will($this->returnSelf()); $this->_nvp->expects($this->any())->method('setTransactionId')->will($this->returnSelf()); $this->_nvp->expects($this->any())->method('callDoAuthorization')->will($this->returnSelf()); - $this->_pro->expects($this->any())->method('getApi')->will($this->returnValue($this->_nvp)); + $this->_checkoutSession->expects($this->once())->method('getPaypalTransactionData')->will( $this->returnValue([]) ); @@ -148,11 +163,75 @@ public function testOrder() $this->_model = $this->_helper->getObject( 'Magento\Paypal\Model\Express', [ - 'proFactory' => $this->_pro, + 'data' => [$this->_pro], 'checkoutSession' => $this->_checkoutSession, 'transactionBuilder' => $this->transactionBuilder ] ); $this->assertEquals($this->_model, $this->_model->order($paymentModel, 12.3)); } + + public function testAssignData() + { + $transportValue = 'something'; + + $data = new DataObject( + [ + PaymentInterface::KEY_ADDITIONAL_DATA => [ + Express\Checkout::PAYMENT_INFO_TRANSPORT_BILLING_AGREEMENT => $transportValue + ] + ] + ); + + $this->_model = $this->_helper->getObject( + 'Magento\Paypal\Model\Express', + [ + 'data' => [$this->_pro], + 'checkoutSession' => $this->_checkoutSession, + 'transactionBuilder' => $this->transactionBuilder, + 'eventDispatcher' => $this->eventManagerMock, + ] + ); + + $paymentInfo = $this->getMock(InfoInterface::class); + $this->_model->setInfoInstance($paymentInfo); + + $this->parentAssignDataExpectation($data); + + $paymentInfo->expects(static::once()) + ->method('setAdditionalInformation') + ->with( + Express\Checkout::PAYMENT_INFO_TRANSPORT_BILLING_AGREEMENT, + $transportValue + ); + + $this->_model->assignData($data); + } + + /** + * @param DataObject $data + */ + private function parentAssignDataExpectation(DataObject $data) + { + $eventData = [ + AbstractDataAssignObserver::METHOD_CODE => $this, + AbstractDataAssignObserver::MODEL_CODE => $this->_model->getInfoInstance(), + AbstractDataAssignObserver::DATA_CODE => $data + ]; + + $this->eventManagerMock->expects(static::exactly(2)) + ->method('dispatch') + ->willReturnMap( + [ + [ + 'payment_method_assign_data_' . $this->_model->getCode(), + $eventData + ], + [ + 'payment_method_assign_data', + $eventData + ] + ] + ); + } } diff --git a/app/code/Magento/Paypal/Test/Unit/Model/Payment/Method/Billing/AbstractAgreementStub.php b/app/code/Magento/Paypal/Test/Unit/Model/Payment/Method/Billing/AbstractAgreementStub.php new file mode 100644 index 0000000000000..c0eba7bb1807f --- /dev/null +++ b/app/code/Magento/Paypal/Test/Unit/Model/Payment/Method/Billing/AbstractAgreementStub.php @@ -0,0 +1,30 @@ +eventManagerMock = $this->getMockBuilder(ManagerInterface::class) + ->setMethods(['dispatch']) + ->getMockForAbstractClass(); + + $this->agreementFactory = $this->getMockBuilder('Magento\Paypal\Model\Billing\AgreementFactory') + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + + $this->payment = $helper->getObject( + AbstractAgreementStub::class, + [ + 'eventDispatcher' => $this->eventManagerMock, + 'agreementFactory' => $this->agreementFactory + ] + ); + } + + public function testAssignData() + { + $baId = '1678235'; + $customerId = 67; + $referenceId = '1234124'; + + $data = new DataObject( + [ + PaymentInterface::KEY_ADDITIONAL_DATA => [ + AbstractAgreement::TRANSPORT_BILLING_AGREEMENT_ID => $baId + ] + ] + ); + $paymentInfo = $this->getMockBuilder(Payment::class) + ->disableOriginalConstructor() + ->getMock(); + $quote = $this->getMockBuilder(Quote::class) + ->disableOriginalConstructor() + ->setMethods(['__wakeup', 'getCustomerId']) + ->getMock(); + + $this->payment->setInfoInstance($paymentInfo); + $this->parentAssignDataExpectation($data); + + $agreementModel = $this->getMockBuilder(Agreement::class) + ->disableOriginalConstructor() + ->setMethods(['__wakeup', 'load', 'getCustomerId', 'getId', 'getReferenceId']) + ->getMock(); + + $this->agreementFactory->expects(static::once()) + ->method('create') + ->willReturn($agreementModel); + + $paymentInfo->expects(static::once()) + ->method('getQuote') + ->willReturn($quote); + + $agreementModel->expects(static::once()) + ->method('load') + ->with($baId); + $agreementModel->expects(static::once()) + ->method('getId') + ->willReturn($baId); + $agreementModel->expects(static::atLeastOnce()) + ->method('getCustomerId') + ->willReturn($customerId); + $agreementModel->expects(static::atLeastOnce()) + ->method('getReferenceId') + ->willReturn($referenceId); + + $quote->expects(static::once()) + ->method('getCustomerId') + ->willReturn($customerId); + + $paymentInfo->expects(static::exactly(2)) + ->method('setAdditionalInformation') + ->willReturnMap( + [ + AbstractAgreement::TRANSPORT_BILLING_AGREEMENT_ID, $baId, + AbstractAgreement::PAYMENT_INFO_REFERENCE_ID, $referenceId + ] + ); + + $this->payment->assignData($data); + } + + /** + * @param DataObject $data + * @throws \Magento\Framework\Exception\LocalizedException + */ + private function parentAssignDataExpectation(DataObject $data) + { + $eventData = [ + AbstractDataAssignObserver::METHOD_CODE => $this, + AbstractDataAssignObserver::MODEL_CODE => $this->payment->getInfoInstance(), + AbstractDataAssignObserver::DATA_CODE => $data + ]; + + $this->eventManagerMock->expects(static::exactly(2)) + ->method('dispatch') + ->willReturnMap( + [ + [ + 'payment_method_assign_data_' . AbstractAgreementStub::STUB_CODE, + $eventData + ], + [ + 'payment_method_assign_data', + $eventData + ] + ] + ); + } +} diff --git a/app/code/Magento/Quote/Model/PaymentMethodManagement.php b/app/code/Magento/Quote/Model/PaymentMethodManagement.php index 63d3fc166467e..6bff056cd034a 100644 --- a/app/code/Magento/Quote/Model/PaymentMethodManagement.php +++ b/app/code/Magento/Quote/Model/PaymentMethodManagement.php @@ -61,10 +61,6 @@ public function set($cartId, \Magento\Quote\Api\Data\PaymentInterface $method) $payment = $quote->getPayment(); $data = $method->getData(); - if (isset($data['additional_data'])) { - $data = array_merge($data, (array)$data['additional_data']); - unset($data['additional_data']); - } $payment->importData($data); if ($quote->isVirtual()) { diff --git a/app/code/Magento/Quote/Model/Quote/Payment.php b/app/code/Magento/Quote/Model/Quote/Payment.php index 0efdf0620e66a..cdd295114c3d5 100644 --- a/app/code/Magento/Quote/Model/Quote/Payment.php +++ b/app/code/Magento/Quote/Model/Quote/Payment.php @@ -5,6 +5,8 @@ */ namespace Magento\Quote\Model\Quote; +use Magento\Quote\Api\Data\PaymentInterface; + /** * Quote payment information * @@ -34,7 +36,7 @@ * @author Magento Core Team * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class Payment extends \Magento\Payment\Model\Info implements \Magento\Quote\Api\Data\PaymentInterface +class Payment extends \Magento\Payment\Model\Info implements PaymentInterface { /** * @var string @@ -167,6 +169,7 @@ public function importData(array $data) } $method->assignData($data); + /* * validating the payment data */ diff --git a/app/code/Magento/Quote/Model/QuoteManagement.php b/app/code/Magento/Quote/Model/QuoteManagement.php index 23c3db6f558a0..2325ccaad612a 100644 --- a/app/code/Magento/Quote/Model/QuoteManagement.php +++ b/app/code/Magento/Quote/Model/QuoteManagement.php @@ -334,10 +334,6 @@ public function placeOrder($cartId, PaymentInterface $paymentMethod = null) $quote->getPayment()->setQuote($quote); $data = $paymentMethod->getData(); - if (isset($data['additional_data'])) { - $data = array_merge($data, (array)$data['additional_data']); - unset($data['additional_data']); - } $quote->getPayment()->importData($data); } diff --git a/app/code/Magento/Quote/Test/Unit/Model/PaymentMethodManagementTest.php b/app/code/Magento/Quote/Test/Unit/Model/PaymentMethodManagementTest.php index d4bea1326812f..60d7618413676 100644 --- a/app/code/Magento/Quote/Test/Unit/Model/PaymentMethodManagementTest.php +++ b/app/code/Magento/Quote/Test/Unit/Model/PaymentMethodManagementTest.php @@ -16,6 +16,7 @@ class PaymentMethodManagementTest extends \PHPUnit_Framework_TestCase * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager */ protected $objectManager; + /** * @var \PHPUnit_Framework_MockObject_MockObject */ @@ -111,7 +112,7 @@ public function testSetVirtualProduct() $cartId = 100; $paymentId = 200; $methodDataWithAdditionalData = ['method' => 'data', 'additional_data' => ['additional' => 'value']]; - $methodData = ['method' => 'data', 'additional' => 'value']; + $methodData = $methodDataWithAdditionalData; $paymentMethod = 'checkmo'; $quoteMock = $this->getMock( diff --git a/app/code/Magento/Quote/Test/Unit/Model/QuoteTest.php b/app/code/Magento/Quote/Test/Unit/Model/QuoteTest.php index 9254ea0ea6362..7da2feffe464e 100644 --- a/app/code/Magento/Quote/Test/Unit/Model/QuoteTest.php +++ b/app/code/Magento/Quote/Test/Unit/Model/QuoteTest.php @@ -1105,7 +1105,7 @@ public function testBeforeSaveIsVirtualQuote(array $productTypes, $expected) ); $items = []; foreach ($productTypes as $type) { - $productMock = $this->getMock('\Magento\Catalog\Model\Product', [], [], '', false);; + $productMock = $this->getMock('\Magento\Catalog\Model\Product', [], [], '', false); $productMock->expects($this->any())->method('getIsVirtual')->willReturn($type); $itemMock = $this->getMock( diff --git a/app/code/Magento/Reports/Model/ResourceModel/Quote/Collection.php b/app/code/Magento/Reports/Model/ResourceModel/Quote/Collection.php index fbba8ce47e537..151f8478c0bb4 100644 --- a/app/code/Magento/Reports/Model/ResourceModel/Quote/Collection.php +++ b/app/code/Magento/Reports/Model/ResourceModel/Quote/Collection.php @@ -156,7 +156,7 @@ public function resolveCustomerNames() $select->from( ['customer' => $this->customerResource->getTable('customer_entity')], - ['email'] + ['entity_id', 'email'] ); $select->columns( ['customer_name' => $customerName] @@ -171,8 +171,11 @@ public function resolveCustomerNames() $customersData = $this->customerResource->getConnection()->fetchAll($select); foreach ($this->getItems() as $item) { - $item->setData(array_merge($item->getData(), current($customersData))); - next($customersData); + foreach ($customersData as $customerItemData) { + if ($item['customer_id'] == $customerItemData['entity_id']) { + $item->setData(array_merge($item->getData(), $customerItemData)); + } + } } } } diff --git a/app/code/Magento/Reports/Test/Unit/Model/ResourceModel/Quote/CollectionTest.php b/app/code/Magento/Reports/Test/Unit/Model/ResourceModel/Quote/CollectionTest.php index 0a03a05bbb346..fa4f67f09f2d5 100644 --- a/app/code/Magento/Reports/Test/Unit/Model/ResourceModel/Quote/CollectionTest.php +++ b/app/code/Magento/Reports/Test/Unit/Model/ResourceModel/Quote/CollectionTest.php @@ -110,15 +110,14 @@ public function testResolveCustomerNames() $customerName = "CONCAT_WS('firstname', 'lastname')"; $customerTableName = 'customer_entity'; $customerId = ['customer_id' => ['test_id']]; - $customersData = [['item_1']]; - $itemData = ['test']; + $customersData = [['entity_id' => 'test_id', 'name' => 'item_1']]; $this->selectMock->expects($this->any()) ->method('getConnection') ->willReturn($this->connectionMock); $this->selectMock->expects($this->once()) ->method('from') - ->with(['customer' => $customerTableName], ['email']) + ->with(['customer' => $customerTableName], ['entity_id', 'email']) ->willReturnSelf(); $this->selectMock->expects($this->once()) ->method('columns') @@ -158,9 +157,6 @@ public function testResolveCustomerNames() $itemMock = $this->getMockBuilder('Magento\Framework\Model\AbstractModel') ->disableOriginalConstructor() ->getMock(); - $itemMock->expects($this->once()) - ->method('getData') - ->willReturn($itemData); $this->entityFactoryMock->expects($this->any()) ->method('create') diff --git a/app/code/Magento/Reports/view/adminhtml/layout/reports_report_grid.xml b/app/code/Magento/Reports/view/adminhtml/layout/reports_report_grid.xml index 6f04004a39951..b190ce77e22ad 100644 --- a/app/code/Magento/Reports/view/adminhtml/layout/reports_report_grid.xml +++ b/app/code/Magento/Reports/view/adminhtml/layout/reports_report_grid.xml @@ -11,9 +11,6 @@ 0 - - null - 1 1 1 diff --git a/app/code/Magento/Sales/Model/Order/Payment/Info.php b/app/code/Magento/Sales/Model/Order/Payment/Info.php index 45289510a9695..4e5dfee783aa2 100644 --- a/app/code/Magento/Sales/Model/Order/Payment/Info.php +++ b/app/code/Magento/Sales/Model/Order/Payment/Info.php @@ -226,9 +226,6 @@ protected function initAdditionalInformation() { $additionalInfo = $this->getData('additional_information'); if (empty($this->additionalInformation) && $additionalInfo) { - if (!is_array($additionalInfo)) { - $additionalInfo = unserialize($additionalInfo); - } $this->additionalInformation = $additionalInfo; } } diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Payment/InfoTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Payment/InfoTest.php index f47806866aef6..3516aef705982 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/Payment/InfoTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Payment/InfoTest.php @@ -89,8 +89,7 @@ public function ccKeysDataProvider() ['cc_cid', 'cc_cid_enc'] ]; } - - + public function testGetMethodInstanceWithRealMethod() { $method = 'real_method'; @@ -108,7 +107,6 @@ public function testGetMethodInstanceWithRealMethod() $this->info->getMethodInstance(); } - public function testGetMethodInstanceWithUnrealMethod() { $method = 'unreal_method'; @@ -131,7 +129,6 @@ public function testGetMethodInstanceWithUnrealMethod() $this->info->getMethodInstance(); } - /** * @expectedException \Magento\Framework\Exception\LocalizedException * @expectedExceptionMessage The payment method you requested is not available. @@ -253,9 +250,9 @@ public function testHasAdditionalInformation() public function testInitAdditionalInformationWithUnserialize() { - $data = serialize(['key1' => 'data1', 'key2' => 'data2']); + $data = ['key1' => 'data1', 'key2' => 'data2']; $this->info->setData('additional_information', $data); - $this->assertEquals(unserialize($data), $this->info->getAdditionalInformation()); + $this->assertEquals($data, $this->info->getAdditionalInformation()); } } diff --git a/app/code/Magento/Search/etc/adminhtml/system.xml b/app/code/Magento/Search/etc/adminhtml/system.xml index fef331798c3a1..a919f02adbfb5 100644 --- a/app/code/Magento/Search/etc/adminhtml/system.xml +++ b/app/code/Magento/Search/etc/adminhtml/system.xml @@ -13,11 +13,6 @@ Magento\Search\Model\Adminhtml\System\Config\Source\Engine - - - mysql - - diff --git a/app/code/Magento/Swatches/view/frontend/templates/product/layered/renderer.phtml b/app/code/Magento/Swatches/view/frontend/templates/product/layered/renderer.phtml index 2b3c9f148360f..19b4002efb2a7 100644 --- a/app/code/Magento/Swatches/view/frontend/templates/product/layered/renderer.phtml +++ b/app/code/Magento/Swatches/view/frontend/templates/product/layered/renderer.phtml @@ -10,7 +10,7 @@ ?> getSwatchData(); ?>
+ attribute-code="" attribute-id="">
$label): ?> diff --git a/app/code/Magento/Swatches/view/frontend/web/js/swatch-renderer.js b/app/code/Magento/Swatches/view/frontend/web/js/swatch-renderer.js index 169da58a35ccb..326cbd7e43c5d 100644 --- a/app/code/Magento/Swatches/view/frontend/web/js/swatch-renderer.js +++ b/app/code/Magento/Swatches/view/frontend/web/js/swatch-renderer.js @@ -205,12 +205,22 @@ define([ */ _init: function () { if (this.options.jsonConfig !== '' && this.options.jsonSwatchConfig !== '') { + this._sortAttributes(); this._RenderControls(); } else { console.log('SwatchRenderer: No input data received'); } }, + /** + * @private + */ + _sortAttributes: function () { + this.options.jsonConfig.attributes = _.sortBy(this.options.jsonConfig.attributes, function (attribute) { + return attribute.position; + }); + }, + /** * @private */ diff --git a/app/code/Magento/Vault/Observer/PaymentTokenAssigner.php b/app/code/Magento/Vault/Observer/PaymentTokenAssigner.php index 760c655d3cb66..64f7f5b27226f 100644 --- a/app/code/Magento/Vault/Observer/PaymentTokenAssigner.php +++ b/app/code/Magento/Vault/Observer/PaymentTokenAssigner.php @@ -7,6 +7,7 @@ use Magento\Framework\Event\Observer; use Magento\Payment\Observer\AbstractDataAssignObserver; +use Magento\Quote\Api\Data\PaymentInterface; use Magento\Quote\Model\Quote\Payment; use Magento\Vault\Api\Data\PaymentTokenInterface; use Magento\Vault\Api\PaymentTokenManagementInterface; @@ -37,7 +38,13 @@ public function execute(Observer $observer) { $dataObject = $this->readDataArgument($observer); - $tokenPublicHash = $dataObject->getData(PaymentTokenInterface::PUBLIC_HASH); + $additionalData = $dataObject->getData(PaymentInterface::KEY_ADDITIONAL_DATA); + + if (!is_array($additionalData) || !isset($additionalData[PaymentTokenInterface::PUBLIC_HASH])) { + return; + } + + $tokenPublicHash = $additionalData[PaymentTokenInterface::PUBLIC_HASH]; if ($tokenPublicHash === null) { return; diff --git a/app/code/Magento/Vault/Observer/VaultEnableAssigner.php b/app/code/Magento/Vault/Observer/VaultEnableAssigner.php index 2c98b5a2af83b..db112cf453912 100644 --- a/app/code/Magento/Vault/Observer/VaultEnableAssigner.php +++ b/app/code/Magento/Vault/Observer/VaultEnableAssigner.php @@ -7,6 +7,7 @@ use Magento\Framework\Event\Observer; use Magento\Payment\Observer\AbstractDataAssignObserver; +use Magento\Quote\Api\Data\PaymentInterface; use Magento\Vault\Model\Ui\VaultConfigProvider; class VaultEnableAssigner extends AbstractDataAssignObserver @@ -19,11 +20,17 @@ public function execute(\Magento\Framework\Event\Observer $observer) { $data = $this->readDataArgument($observer); - if (isset($data[VaultConfigProvider::IS_ACTIVE_CODE])) { + $additionalData = $data->getData(PaymentInterface::KEY_ADDITIONAL_DATA); + + if (!is_array($additionalData)) { + return; + } + + if (isset($additionalData[VaultConfigProvider::IS_ACTIVE_CODE])) { $payment = $this->readPaymentModelArgument($observer); $payment->setAdditionalInformation( VaultConfigProvider::IS_ACTIVE_CODE, - filter_var($data[VaultConfigProvider::IS_ACTIVE_CODE], FILTER_VALIDATE_BOOLEAN) + filter_var($additionalData[VaultConfigProvider::IS_ACTIVE_CODE], FILTER_VALIDATE_BOOLEAN) ); } } diff --git a/app/code/Magento/Vault/Test/Unit/Observer/PaymentTokenAssignerTest.php b/app/code/Magento/Vault/Test/Unit/Observer/PaymentTokenAssignerTest.php index 655f0abac2501..40fa32fc7988d 100644 --- a/app/code/Magento/Vault/Test/Unit/Observer/PaymentTokenAssignerTest.php +++ b/app/code/Magento/Vault/Test/Unit/Observer/PaymentTokenAssignerTest.php @@ -12,6 +12,7 @@ use Magento\Payment\Model\InfoInterface; use Magento\Payment\Observer\AbstractDataAssignObserver; use Magento\Quote\Api\Data\CartInterface; +use Magento\Quote\Api\Data\PaymentInterface; use Magento\Quote\Model\Quote\Payment; use Magento\Vault\Api\Data\PaymentTokenInterface; use Magento\Vault\Api\PaymentTokenManagementInterface; @@ -58,7 +59,9 @@ public function testExecuteNotOrderPaymentModel() { $dataObject = new DataObject( [ - PaymentTokenInterface::PUBLIC_HASH => 'public_hash_value' + PaymentInterface::KEY_ADDITIONAL_DATA => [ + PaymentTokenInterface::PUBLIC_HASH => 'public_hash_value' + ] ] ); $paymentModel = $this->getMock(InfoInterface::class); @@ -79,7 +82,9 @@ public function testExecuteNoCustomerId() { $dataObject = new DataObject( [ - PaymentTokenInterface::PUBLIC_HASH => 'public_hash_value' + PaymentInterface::KEY_ADDITIONAL_DATA => [ + PaymentTokenInterface::PUBLIC_HASH => 'public_hash_value' + ] ] ); @@ -117,7 +122,9 @@ public function testExecuteNoPaymentToken() $publicHash = 'public_hash_value'; $dataObject = new DataObject( [ - PaymentTokenInterface::PUBLIC_HASH => $publicHash + PaymentInterface::KEY_ADDITIONAL_DATA => [ + PaymentTokenInterface::PUBLIC_HASH => $publicHash + ] ] ); @@ -161,7 +168,9 @@ public function testExecuteSaveMetadata() $publicHash = 'public_hash_value'; $dataObject = new DataObject( [ - PaymentTokenInterface::PUBLIC_HASH => $publicHash + PaymentInterface::KEY_ADDITIONAL_DATA => [ + PaymentTokenInterface::PUBLIC_HASH => $publicHash + ] ] ); diff --git a/app/code/Magento/Vault/Test/Unit/Observer/VaultEnableAssignerTest.php b/app/code/Magento/Vault/Test/Unit/Observer/VaultEnableAssignerTest.php index 0c96592f7301f..2d59188c232ee 100644 --- a/app/code/Magento/Vault/Test/Unit/Observer/VaultEnableAssignerTest.php +++ b/app/code/Magento/Vault/Test/Unit/Observer/VaultEnableAssignerTest.php @@ -10,6 +10,7 @@ use Magento\Framework\Event\Observer; use Magento\Payment\Model\InfoInterface; use Magento\Payment\Observer\AbstractDataAssignObserver; +use Magento\Quote\Api\Data\PaymentInterface; use Magento\Vault\Model\Ui\VaultConfigProvider; use Magento\Vault\Observer\VaultEnableAssigner; @@ -39,7 +40,9 @@ public function testExecute($activeCode, $expectedBool) { $dataObject = new DataObject( [ - VaultConfigProvider::IS_ACTIVE_CODE => $activeCode + PaymentInterface::KEY_ADDITIONAL_DATA => [ + VaultConfigProvider::IS_ACTIVE_CODE => $activeCode + ] ] ); $paymentModel = $this->getMock(InfoInterface::class); diff --git a/dev/tests/functional/lib/Magento/Mtf/Client/Element/SuggestElement.php b/dev/tests/functional/lib/Magento/Mtf/Client/Element/SuggestElement.php index d912a689cb31e..71d4a84b11612 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Client/Element/SuggestElement.php +++ b/dev/tests/functional/lib/Magento/Mtf/Client/Element/SuggestElement.php @@ -75,19 +75,9 @@ public function setValue($value) if ($value == '') { return; } - foreach (str_split($value) as $symbol) { - $this->keys([$symbol]); - $searchedItem = $this->find(sprintf($this->resultItem, $value), Locator::SELECTOR_XPATH); - if ($searchedItem->isVisible()) { - try { - $searchedItem->click(); - break; - } catch (\Exception $e) { - // In parallel run on windows change the focus is lost on element - // that causes disappearing of category suggest list. - } - } - } + $this->keys([$value]); + $searchedItem = $this->find(sprintf($this->resultItem, $value), Locator::SELECTOR_XPATH); + $searchedItem->click(); $closeButton = $this->find($this->closeButton); if ($closeButton->isVisible()) { $closeButton->click(); @@ -102,7 +92,9 @@ public function setValue($value) */ public function keys(array $keys) { - $this->find($this->advancedSelect)->click(); + if (!$this->find($this->selectInput)->isVisible()) { + $this->find($this->advancedSelect)->click(); + } $input = $this->find($this->selectInput); $input->click(); $input->keys($keys); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Option/Type/File/ValidatorInfoTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Option/Type/File/ValidatorInfoTest.php index b94b21f02b1d6..aa5a3ec5ded0b 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Option/Type/File/ValidatorInfoTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Option/Type/File/ValidatorInfoTest.php @@ -16,7 +16,7 @@ class ValidatorInfoTest extends \PHPUnit_Framework_TestCase protected $model; /** - * @var \Magento\Framework\ObjectManager + * @var \Magento\Framework\ObjectManagerInterface */ protected $objectManager; @@ -164,11 +164,13 @@ protected function getProductOption(array $options = []) */ protected function getOptionValue() { - $file = 'var/tmp/magento_small_image.jpg'; + /** @var \Magento\Catalog\Model\Product\Media\Config $config */ + $config = $this->objectManager->get('Magento\Catalog\Model\Product\Media\Config'); + $file = $config->getBaseTmpMediaPath() . '/magento_small_image.jpg'; - /** @var \Magento\Framework\App\Filesystem $filesystem */ + /** @var \Magento\Framework\Filesystem $filesystem */ $filesystem = $this->objectManager->get('Magento\Framework\Filesystem'); - $tmpDirectory = $filesystem->getDirectoryWrite(\Magento\Framework\App\Filesystem\DirectoryList::ROOT); + $tmpDirectory = $filesystem->getDirectoryRead(\Magento\Framework\App\Filesystem\DirectoryList::MEDIA); $filePath = $tmpDirectory->getAbsolutePath($file); return [ diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Webapi/Product/Option/Type/File/ProcessorTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Webapi/Product/Option/Type/File/ProcessorTest.php new file mode 100644 index 0000000000000..e209ef74e7084 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Webapi/Product/Option/Type/File/ProcessorTest.php @@ -0,0 +1,100 @@ +objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + } + + /** + * @dataProvider pathConfigDataProvider + */ + public function testProcessFileContent($pathConfig) + { + $model = $this->getModel($pathConfig); + /** @var \Magento\Framework\Api\Data\ImageContentInterface $imageContent */ + $imageContent = $this->objectManager->create( + '\Magento\Framework\Api\Data\ImageContentInterface' + ); + $imageContent->setName('my_file'); + $imageContent->setType('image/png'); + $imageContent->setBase64EncodedData($this->getImageContent()); + $result = $model->processFileContent($imageContent); + + $this->assertArrayHasKey('fullpath', $result); + $this->assertTrue(file_exists($result['fullpath'])); + + /** @var $filesystem \Magento\Framework\Filesystem */ + $filesystem = $this->objectManager->get('Magento\Framework\Filesystem'); + $this->assertArrayHasKey('quote_path', $result); + $filePath = $filesystem->getDirectoryRead(DirectoryList::MEDIA)->getAbsolutePath($result['quote_path']); + $this->assertTrue(file_exists($filePath)); + + $this->assertArrayHasKey('order_path', $result); + $filePath = $filesystem->getDirectoryRead(DirectoryList::MEDIA)->getAbsolutePath($result['order_path']); + $this->assertTrue(file_exists($filePath)); + } + + public function pathConfigDataProvider() + { + return [ + // default config + [[]], + // config from pub/index.php + [ + [ + DirectoryList::PUB => [DirectoryList::URL_PATH => ''], + DirectoryList::MEDIA => [DirectoryList::URL_PATH => 'media'], + DirectoryList::STATIC_VIEW => [DirectoryList::URL_PATH => 'static'], + DirectoryList::UPLOAD => [DirectoryList::URL_PATH => 'media/upload'], + ] + ], + ]; + } + + /** + * @return \Magento\Catalog\Model\Webapi\Product\Option\Type\File\Processor + */ + private function getModel($pathConfig) + { + $rootPath = \Magento\TestFramework\Helper\Bootstrap::getInstance()->getAppTempDir(); + $dirList = $this->objectManager->create( + '\Magento\Framework\App\Filesystem\DirectoryList', + ['root' => $rootPath, 'config' => $pathConfig] + ); + $fileSystem = $this->objectManager->create( + '\Magento\Framework\Filesystem', + ['directoryList' => $dirList] + ); + $model = $this->objectManager->create( + '\Magento\Catalog\Model\Webapi\Product\Option\Type\File\Processor', + ['filesystem' => $fileSystem] + ); + return $model; + } + + /** + * Black rectangle 10x10px + * + * @return string + */ + private function getImageContent() + { + return 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKEAIAAABSwISpAAAACXBIWXMAAABIAAAASABGyWs+AAAACXZwQWcAAAA' . + 'KAAAACgBOpnblAAAAD0lEQVQoz2NgGAWjgJYAAAJiAAEQ3MCgAAAAJXRFWHRjcmVhdGUtZGF0ZQAyMDA5LTA3LTA4VDE5Oj' . + 'E1OjMyKzAyOjAwm1PZQQAAACV0RVh0bW9kaWZ5LWRhdGUAMjAwOS0wNy0wOFQxOToxNTozMiswMjowMMTir3UAAAAASUVORK5CYII='; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/validate_image_info.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/validate_image_info.php index b36bf61959d84..05e84c29d7710 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/validate_image_info.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/validate_image_info.php @@ -7,12 +7,15 @@ $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); /** @var \Magento\Framework\Filesystem $filesystem */ -$filesystem = $objectManager->create('Magento\Framework\Filesystem'); +$filesystem = $objectManager->get('Magento\Framework\Filesystem'); + +/** @var Magento\Catalog\Model\Product\Media\Config $config */ +$config = $objectManager->get('Magento\Catalog\Model\Product\Media\Config'); /** @var $tmpDirectory \Magento\Framework\Filesystem\Directory\WriteInterface */ -$tmpDirectory = $filesystem->getDirectoryWrite(\Magento\Framework\App\Filesystem\DirectoryList::ROOT); -$tmpDirectory->create('var/tmp'); +$tmpDirectory = $filesystem->getDirectoryWrite(\Magento\Framework\App\Filesystem\DirectoryList::MEDIA); +$tmpDirectory->create($config->getBaseTmpMediaPath()); -$targetTmpFilePath = $tmpDirectory->getAbsolutePath('var/tmp/magento_small_image.jpg'); +$targetTmpFilePath = $tmpDirectory->getAbsolutePath($config->getBaseTmpMediaPath() . '/magento_small_image.jpg'); copy(__DIR__ . '/magento_small_image.jpg', $targetTmpFilePath); // Copying the image to target dir is not necessary because during product save, it will be moved there from tmp dir diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/validate_image_info_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/validate_image_info_rollback.php index f3402abdc8a46..f92635616235c 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/validate_image_info_rollback.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/validate_image_info_rollback.php @@ -9,11 +9,13 @@ /** @var \Magento\Framework\Filesystem $filesystem */ $filesystem = $objectManager->create('Magento\Framework\Filesystem'); +/** @var Magento\Catalog\Model\Product\Media\Config $config */ +$config = $objectManager->get('Magento\Catalog\Model\Product\Media\Config'); + /** @var $tmpDirectory \Magento\Framework\Filesystem\Directory\WriteInterface */ -$tmpDirectory = $filesystem->getDirectoryWrite(\Magento\Framework\App\Filesystem\DirectoryList::TMP); -$tmpDirectory->create($tmpDirectory->getAbsolutePath()); +$tmpDirectory = $filesystem->getDirectoryRead(\Magento\Framework\App\Filesystem\DirectoryList::MEDIA); -$targetTmpFilePath = $tmpDirectory->getAbsolutePath('magento_small_image.jpg'); +$targetTmpFilePath = $tmpDirectory->getAbsolutePath($config->getBaseTmpMediaPath() . '/magento_small_image.jpg'); if (file_exists($targetTmpFilePath)) { unlink($targetTmpFilePath); } diff --git a/dev/tests/integration/testsuite/Magento/CatalogSearch/Model/ResourceModel/Advanced/CollectionTest.php b/dev/tests/integration/testsuite/Magento/CatalogSearch/Model/ResourceModel/Advanced/CollectionTest.php new file mode 100644 index 0000000000000..a1954bc86dca6 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/CatalogSearch/Model/ResourceModel/Advanced/CollectionTest.php @@ -0,0 +1,47 @@ +advancedCollection = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() + ->create('\Magento\CatalogSearch\Model\ResourceModel\Advanced\Collection'); + } + + /** + * @dataProvider filtersDataProvider + * @magentoDataFixture Magento/Framework/Search/_files/products.php + */ + public function testLoadWithFilterNoFilters($filters, $expectedCount) + { + // addFieldsToFilter will load filters, + // then loadWithFilter will trigger _renderFiltersBefore code in Advanced/Collection + $this->advancedCollection->addFieldsToFilter([$filters])->loadWithFilter(); + $items = $this->advancedCollection->getItems(); + $this->assertCount($expectedCount, $items); + } + + public function filtersDataProvider() + { + return [ + [['name' => ['like' => 'shorts'], 'description' => ['like' => 'green']], 1], + [['name' => 'white', 'description' => ' '], 1], + [['name' => ' ', 'description' => 'green'], 2], + [['name' => ' ', 'description' => ' '], 0], + ]; + } +} diff --git a/dev/tests/integration/testsuite/Magento/CatalogSearch/Model/ResourceModel/Fulltext/CollectionTest.php b/dev/tests/integration/testsuite/Magento/CatalogSearch/Model/ResourceModel/Fulltext/CollectionTest.php new file mode 100644 index 0000000000000..902c8a7d8093f --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/CatalogSearch/Model/ResourceModel/Fulltext/CollectionTest.php @@ -0,0 +1,45 @@ +create( + '\Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection', + ['searchRequestName' => $request] + ); + foreach ($filters as $field => $value) { + $fulltextCollection->addFieldToFilter($field, $value); + } + $fulltextCollection->loadWithFilter(); + $items = $fulltextCollection->getItems(); + $this->assertCount($expectedCount, $items); + } + + public function filtersDataProviderSearch() + { + return [ + ['quick_search_container', ['search_term' => ' shorts'], 2], + ['quick_search_container', ['search_term' => ' '], 0], + ['catalog_view_container', ['category_ids' => 2], 5], + ['catalog_view_container', ['category_ids' => 100001], 0], + ['catalog_view_container', ['category_ids' => []], 0], + ['catalog_view_container', [], 0], + ]; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Framework/Search/Adapter/Mysql/AdapterTest.php b/dev/tests/integration/testsuite/Magento/Framework/Search/Adapter/Mysql/AdapterTest.php index e3a524b204386..c3cbc57c7fe6f 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Search/Adapter/Mysql/AdapterTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/Search/Adapter/Mysql/AdapterTest.php @@ -5,12 +5,21 @@ */ namespace Magento\Framework\Search\Adapter\Mysql; +use Magento\CatalogSearch\Model\ResourceModel\EngineInterface; +use Magento\Search\Model\EngineResolver; use Magento\TestFramework\Helper\Bootstrap; +/** + * Class AdapterTest + * + * @magentoDbIsolation disabled + * @magentoAppIsolation enabled + * @magentoDataFixture Magento/Framework/Search/_files/products.php + */ class AdapterTest extends \PHPUnit_Framework_TestCase { /** - * @var \Magento\Framework\Search\Adapter\Mysql\Adapter + * @var \Magento\Framework\Search\AdapterInterface */ private $adapter; @@ -22,7 +31,17 @@ class AdapterTest extends \PHPUnit_Framework_TestCase /** * @var \Magento\Framework\ObjectManagerInterface */ - private $objectManager; + protected $objectManager; + + /** + * @var string + */ + protected $requestConfig = __DIR__ . '/../../_files/requests.xml'; + + /** + * @var string + */ + protected $searchEngine = EngineResolver::CATALOG_SEARCH_MYSQL_ENGINE; protected function setUp() { @@ -32,7 +51,7 @@ protected function setUp() $converter = $this->objectManager->create('Magento\Framework\Search\Request\Config\Converter'); $document = new \DOMDocument(); - $document->load(__DIR__ . '/../../_files/requests.xml'); + $document->load($this->requestConfig); $requestConfig = $converter->convert($document); /** @var \Magento\Framework\Search\Request\Config $config */ @@ -44,26 +63,25 @@ protected function setUp() ['config' => $config] ); - $this->adapter = $this->objectManager->create('Magento\Framework\Search\Adapter\Mysql\Adapter'); + $this->adapter = $this->createAdapter(); } /** - * Sample test - * - * @magentoDbIsolation disabled - * @magentoAppIsolation enabled - * @magentoConfigFixture current_store catalog/search/engine mysql - * @magentoConfigFixture current_store catalog/search/search_type 2 - * @magentoDataFixture Magento/Framework/Search/_files/products.php + * Make sure that correct engine is set */ - public function testMatchQuery() + protected function assertPreConditions() { - $this->requestBuilder->bind('fulltext_search_query', 'socks'); - $this->requestBuilder->setRequestName('one_match'); - - $queryResponse = $this->executeQuery(); + $currentEngine = $this->objectManager->get('Magento\Framework\App\Config\MutableScopeConfigInterface') + ->getValue(EngineInterface::CONFIG_ENGINE_PATH, \Magento\Store\Model\ScopeInterface::SCOPE_STORE); + $this->assertEquals($this->searchEngine, $currentEngine); + } - $this->assertEquals(1, $queryResponse->count()); + /** + * @return \Magento\Framework\Search\AdapterInterface + */ + protected function createAdapter() + { + return $this->objectManager->create('Magento\Framework\Search\Adapter\Mysql\Adapter'); } /** @@ -71,7 +89,7 @@ public function testMatchQuery() */ private function executeQuery() { - /** @var \Magento\Framework\Search\Response\QueryResponse $queryRequest */ + /** @var \Magento\Framework\Search\RequestInterface $queryRequest */ $queryRequest = $this->requestBuilder->create(); $queryResponse = $this->adapter->query($queryRequest); @@ -80,13 +98,36 @@ private function executeQuery() } /** - * Sample test - * - * @magentoDbIsolation disabled - * @magentoAppIsolation enabled + * @param \Magento\Framework\Search\Response\QueryResponse $queryResponse + * @param array $expectedIds + */ + private function assertProductIds($queryResponse, $expectedIds) + { + $actualIds = []; + foreach ($queryResponse as $document) { + /** @var \Magento\Framework\Search\Document $document */ + $actualIds[] = $document->getId(); + } + sort($actualIds); + sort($expectedIds); + $this->assertEquals($expectedIds, $actualIds); + } + + /** + * @magentoConfigFixture current_store catalog/search/engine mysql + */ + public function testMatchQuery() + { + $this->requestBuilder->bind('fulltext_search_query', 'socks'); + $this->requestBuilder->setRequestName('one_match'); + + $queryResponse = $this->executeQuery(); + + $this->assertEquals(1, $queryResponse->count()); + } + + /** * @magentoConfigFixture current_store catalog/search/engine mysql - * @magentoConfigFixture current_store catalog/search/search_type 2 - * @magentoDataFixture Magento/Framework/Search/_files/products.php */ public function testAggregationsQuery() { @@ -103,13 +144,7 @@ public function testAggregationsQuery() } /** - * Sample test - * - * @magentoDbIsolation disabled - * @magentoAppIsolation enabled * @magentoConfigFixture current_store catalog/search/engine mysql - * @magentoConfigFixture current_store catalog/search/search_type 2 - * @magentoDataFixture Magento/Framework/Search/_files/products.php */ public function testMatchQueryFilters() { @@ -126,11 +161,7 @@ public function testMatchQueryFilters() /** * Range filter test with all fields filled * - * @magentoDbIsolation disabled - * @magentoAppIsolation enabled * @magentoConfigFixture current_store catalog/search/engine mysql - * @magentoConfigFixture current_store catalog/search/search_type 2 - * @magentoDataFixture Magento/Framework/Search/_files/products.php */ public function testRangeFilterWithAllFields() { @@ -145,11 +176,7 @@ public function testRangeFilterWithAllFields() /** * Range filter test with all fields filled * - * @magentoDbIsolation disabled - * @magentoAppIsolation enabled * @magentoConfigFixture current_store catalog/search/engine mysql - * @magentoConfigFixture current_store catalog/search/search_type 2 - * @magentoDataFixture Magento/Framework/Search/_files/products.php */ public function testRangeFilterWithoutFromField() { @@ -163,11 +190,7 @@ public function testRangeFilterWithoutFromField() /** * Range filter test with all fields filled * - * @magentoDbIsolation disabled - * @magentoAppIsolation enabled * @magentoConfigFixture current_store catalog/search/engine mysql - * @magentoConfigFixture current_store catalog/search/search_type 2 - * @magentoDataFixture Magento/Framework/Search/_files/products.php */ public function testRangeFilterWithoutToField() { @@ -181,11 +204,7 @@ public function testRangeFilterWithoutToField() /** * Term filter test * - * @magentoDbIsolation disabled - * @magentoAppIsolation enabled * @magentoConfigFixture current_store catalog/search/engine mysql - * @magentoConfigFixture current_store catalog/search/search_type 2 - * @magentoDataFixture Magento/Framework/Search/_files/products.php */ public function testTermFilter() { @@ -200,11 +219,7 @@ public function testTermFilter() /** * Term filter test * - * @magentoDbIsolation disabled - * @magentoAppIsolation enabled * @magentoConfigFixture current_store catalog/search/engine mysql - * @magentoConfigFixture current_store catalog/search/search_type 2 - * @magentoDataFixture Magento/Framework/Search/_files/products.php */ public function testTermFilterArray() { @@ -218,29 +233,39 @@ public function testTermFilterArray() /** * Term filter test * - * @magentoDbIsolation disabled - * @magentoAppIsolation enabled * @magentoConfigFixture current_store catalog/search/engine mysql - * @magentoConfigFixture current_store catalog/search/search_type 2 - * @magentoDataFixture Magento/Framework/Search/_files/products.php */ public function testWildcardFilter() { + $expectedIds = [1, 3, 5]; $this->requestBuilder->bind('wildcard_filter', 're'); $this->requestBuilder->setRequestName('one_wildcard'); $queryResponse = $this->executeQuery(); $this->assertEquals(3, $queryResponse->count()); + $this->assertProductIds($queryResponse, $expectedIds); + } + + /** + * Request limits test + * + * @magentoConfigFixture current_store catalog/search/engine mysql + */ + public function testSearchLimit() + { + $this->requestBuilder->bind('wildcard_filter', 're'); + $this->requestBuilder->setFrom(1); + $this->requestBuilder->setSize(2); + $this->requestBuilder->setRequestName('one_wildcard'); + + $queryResponse = $this->executeQuery(); + $this->assertEquals(2, $queryResponse->count()); } /** * Bool filter test * - * @magentoDbIsolation disabled - * @magentoAppIsolation enabled * @magentoConfigFixture current_store catalog/search/engine mysql - * @magentoConfigFixture current_store catalog/search/search_type 2 - * @magentoDataFixture Magento/Framework/Search/_files/products.php */ public function testBoolFilter() { @@ -257,23 +282,13 @@ public function testBoolFilter() $queryResponse = $this->executeQuery(); $this->assertEquals(count($expectedIds), $queryResponse->count()); - $actualIds = []; - foreach ($queryResponse as $document) { - /** @var \Magento\Framework\Search\Document $document */ - $actualIds[] = $document->getId(); - } - sort($actualIds); - $this->assertEquals($expectedIds, $actualIds); + $this->assertProductIds($queryResponse, $expectedIds); } /** * Test bool filter with nested negative bool filter * - * @magentoDbIsolation disabled - * @magentoAppIsolation enabled * @magentoConfigFixture current_store catalog/search/engine mysql - * @magentoConfigFixture current_store catalog/search/search_type 2 - * @magentoDataFixture Magento/Framework/Search/_files/products.php */ public function testBoolFilterWithNestedNegativeBoolFilter() { @@ -285,50 +300,31 @@ public function testBoolFilterWithNestedNegativeBoolFilter() $queryResponse = $this->executeQuery(); $this->assertEquals(count($expectedIds), $queryResponse->count()); - $actualIds = []; - foreach ($queryResponse as $document) { - /** @var \Magento\Framework\Search\Document $document */ - $actualIds[] = $document->getId(); - } - $this->assertEquals($expectedIds, $actualIds); + $this->assertProductIds($queryResponse, $expectedIds); } /** * Test range inside nested negative bool filter * - * @magentoDbIsolation disabled - * @magentoAppIsolation enabled * @magentoConfigFixture current_store catalog/search/engine mysql - * @magentoConfigFixture current_store catalog/search/search_type 2 - * @magentoDataFixture Magento/Framework/Search/_files/products.php */ public function testBoolFilterWithNestedRangeInNegativeBoolFilter() { - $expectedIds = [1, 2, 4, 5]; + $expectedIds = [1, 5]; $this->requestBuilder->bind('nested_must_range_filter_from', 14); $this->requestBuilder->bind('nested_must_range_filter_to', 18); $this->requestBuilder->setRequestName('bool_filter_with_range_in_nested_negative_filter'); $queryResponse = $this->executeQuery(); $this->assertEquals(count($expectedIds), $queryResponse->count()); - $actualIds = []; - foreach ($queryResponse as $document) { - /** @var \Magento\Framework\Search\Document $document */ - $actualIds[] = $document->getId(); - } - sort($actualIds); - $this->assertEquals($expectedIds, $actualIds); + $this->assertProductIds($queryResponse, $expectedIds); } /** * Sample Advanced search request test * - * @dataProvider advancedSearchDataProvider - * @magentoDbIsolation disabled - * @magentoAppIsolation enabled * @magentoConfigFixture current_store catalog/search/engine mysql - * @magentoConfigFixture current_store catalog/search/search_type 2 - * @magentoDataFixture Magento/Framework/Search/_files/products.php + * @dataProvider advancedSearchDataProvider */ public function testSimpleAdvancedSearch( $nameQuery, @@ -355,16 +351,15 @@ public function advancedSearchDataProvider() ['white', 'shorts', ['from' => '16', 'to' => '18'], 0], ['white', 'shorts',['from' => '12', 'to' => '18'], 1], ['black', 'tshirts', ['from' => '12', 'to' => '20'], 0], - ['peoples', 'green', ['from' => '12', 'to' => '22'], 2], + ['shorts', 'green', ['from' => '12', 'to' => '22'], 1], + //Search with empty fields/values + ['white', ' ', ['from' => '12', 'to' => '22'], 1], + [' ', 'green', ['from' => '12', 'to' => '22'], 2] ]; } /** - * @magentoDbIsolation disabled - * @magentoAppIsolation enabled * @magentoConfigFixture current_store catalog/search/engine mysql - * @magentoConfigFixture current_store catalog/search/search_type 2 - * @magentoDataFixture Magento/Framework/Search/_files/filterable_attribute.php */ public function testCustomFilterableAttribute() { diff --git a/dev/tests/integration/testsuite/Magento/Framework/Search/_files/requests.xml b/dev/tests/integration/testsuite/Magento/Framework/Search/_files/requests.xml index 0356d6881d4fc..76e044afcba49 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Search/_files/requests.xml +++ b/dev/tests/integration/testsuite/Magento/Framework/Search/_files/requests.xml @@ -19,7 +19,7 @@ - 10 + 0 10 @@ -53,7 +53,7 @@ - 10 + 0 10 @@ -68,7 +68,7 @@ - 10 + 0 10 @@ -112,7 +112,7 @@ - 10 + 0 10 @@ -131,7 +131,7 @@ from="$range_filter_from$" to="$range_filter_to$"/> - 10 + 0 10 @@ -149,7 +149,7 @@ field="price" to="$range_filter_to$"/> - 10 + 0 10 @@ -167,7 +167,7 @@ field="price" from="$range_filter_from$"/> - 10 + 0 10 @@ -182,7 +182,7 @@ - 10 + 0 10 @@ -234,7 +234,7 @@ field="price" value="$not_term_filter2$"/> - 10 + 0 10 @@ -264,7 +264,7 @@ field="price" value="$nested_not_term_filter$"/> - 10 + 0 10 @@ -289,7 +289,7 @@ from="$nested_must_range_filter_from$" to="$nested_must_range_filter_to$"/> - 10 + 0 10 @@ -305,7 +305,7 @@ - + @@ -318,7 +318,7 @@ - 10 + 0 10 diff --git a/dev/tests/integration/testsuite/Magento/Paypal/Model/Payment/Method/Billing/AbstractAgreementTest.php b/dev/tests/integration/testsuite/Magento/Paypal/Model/Payment/Method/Billing/AbstractAgreementTest.php index 25405d261abdb..e05b3f6cdefe5 100644 --- a/dev/tests/integration/testsuite/Magento/Paypal/Model/Payment/Method/Billing/AbstractAgreementTest.php +++ b/dev/tests/integration/testsuite/Magento/Paypal/Model/Payment/Method/Billing/AbstractAgreementTest.php @@ -6,6 +6,8 @@ namespace Magento\Paypal\Model\Payment\Method\Billing; +use Magento\Quote\Api\Data\PaymentInterface; + class AbstractAgreementTest extends \PHPUnit_Framework_TestCase { /** @var \Magento\Paypal\Model\Method\Agreement */ @@ -60,7 +62,9 @@ public function testAssignData() )->getFirstItem(); $data = new \Magento\Framework\DataObject( [ - AbstractAgreement::TRANSPORT_BILLING_AGREEMENT_ID => $billingAgreement->getId() + PaymentInterface::KEY_ADDITIONAL_DATA => [ + AbstractAgreement::TRANSPORT_BILLING_AGREEMENT_ID => $billingAgreement->getId() + ] ] ); $this->_model->assignData($data); diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/_files/blacklist/exception_hierarchy.txt b/dev/tests/static/testsuite/Magento/Test/Integrity/_files/blacklist/exception_hierarchy.txt index a1d583b341c31..18e66b8144dc0 100644 --- a/dev/tests/static/testsuite/Magento/Test/Integrity/_files/blacklist/exception_hierarchy.txt +++ b/dev/tests/static/testsuite/Magento/Test/Integrity/_files/blacklist/exception_hierarchy.txt @@ -1,3 +1,5 @@ \Magento\Framework\Exception\LocalizedException \Magento\Framework\View\Asset\File\NotFoundException \Magento\Framework\Config\Dom\ValidationException +\Magento\Framework\Search\Request\EmptyRequestDataException +\Magento\Framework\Search\Request\NonExistingRequestNameException diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_classes.php b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_classes.php index bdcadc125b2ca..d6456a44a8d18 100755 --- a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_classes.php +++ b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_classes.php @@ -4221,4 +4221,6 @@ ['Magento\Braintree\Test\Unit\Observer\DeleteBraintreeCustomerTest'], ['Magento\Braintree\Test\Unit\Observer\ProcessBraintreeAddressTest'], ['Magento\Braintree\Test\Unit\Observer\ProcessBraintreePaymentTest'], + ['Magento\Catalog\Model\Webapi\Product\Option\Type\File\Validator'], + ['Magento\Catalog\Test\Unit\Webapi\Product\Option\Type\File\ValidatorTest'], ]; diff --git a/lib/internal/Magento/Framework/Model/ResourceModel/AbstractResource.php b/lib/internal/Magento/Framework/Model/ResourceModel/AbstractResource.php index 451ec868bef31..4e38d13aa72f6 100644 --- a/lib/internal/Magento/Framework/Model/ResourceModel/AbstractResource.php +++ b/lib/internal/Magento/Framework/Model/ResourceModel/AbstractResource.php @@ -3,11 +3,9 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ - -// @codingStandardsIgnoreFile - namespace Magento\Framework\Model\ResourceModel; +use Magento\Framework\DataObject; use Magento\Framework\Model\CallbackPool; /** @@ -33,7 +31,6 @@ public function __construct() */ abstract protected function _construct(); - /** * Get connection * @@ -108,26 +105,19 @@ public function rollBack() /** * Serialize specified field in an object * - * @param \Magento\Framework\DataObject $object + * @param DataObject $object * @param string $field * @param mixed $defaultValue * @param bool $unsetEmpty * @return $this */ - protected function _serializeField(\Magento\Framework\DataObject $object, $field, $defaultValue = null, $unsetEmpty = false) + protected function _serializeField(DataObject $object, $field, $defaultValue = null, $unsetEmpty = false) { $value = $object->getData($field); - if (empty($value)) { - if ($unsetEmpty) { - $object->unsetData($field); - } else { - if (is_object($defaultValue) || is_array($defaultValue)) { - $defaultValue = serialize($defaultValue); - } - $object->setData($field, $defaultValue); - } - } elseif (is_array($value) || is_object($value)) { - $object->setData($field, serialize($value)); + if (empty($value) && $unsetEmpty) { + $object->unsetData($field); + } else { + $object->setData($field, serialize($value ?: $defaultValue)); } return $this; @@ -141,24 +131,30 @@ protected function _serializeField(\Magento\Framework\DataObject $object, $field * @param mixed $defaultValue * @return void */ - protected function _unserializeField(\Magento\Framework\DataObject $object, $field, $defaultValue = null) + protected function _unserializeField(DataObject $object, $field, $defaultValue = null) { $value = $object->getData($field); + + if ($value) { + $unserializedValue = @unserialize($value); + $value = $unserializedValue !== false || $value === 'b:0;' ? $unserializedValue : $value; + } + if (empty($value)) { $object->setData($field, $defaultValue); - } elseif (!is_array($value) && !is_object($value)) { - $object->setData($field, unserialize($value)); + } else { + $object->setData($field, $value); } } /** * Prepare data for passed table * - * @param \Magento\Framework\DataObject $object + * @param DataObject $object * @param string $table * @return array */ - protected function _prepareDataForTable(\Magento\Framework\DataObject $object, $table) + protected function _prepareDataForTable(DataObject $object, $table) { $data = []; $fields = $this->getConnection()->describeTable($table); diff --git a/lib/internal/Magento/Framework/Model/Test/Unit/ResourceModel/AbstractResourceStub.php b/lib/internal/Magento/Framework/Model/Test/Unit/ResourceModel/AbstractResourceStub.php new file mode 100644 index 0000000000000..13370114aa7ae --- /dev/null +++ b/lib/internal/Magento/Framework/Model/Test/Unit/ResourceModel/AbstractResourceStub.php @@ -0,0 +1,54 @@ +_serializeField($dataObject, $field, $defaultValue, $unsetEmpty); + + static::assertEquals($expectation, $dataObject->getDataByKey($field)); + } + + /** + * @return array + */ + public function serializableFieldsDataProvider() + { + $dataObject = new DataObject( + [ + 'object' => new \stdClass(), + 'array' => ['a', 'b', 'c'], + 'string' => 'i am string', + 'int' => 969, + 'serialized_object' => 'O:8:"stdClass":0:{}', + 'empty_value' => '', + 'empty_value_with_default' => '' + ] + ); + + return [ + [[$dataObject, 'object', null, false], serialize($dataObject->getDataByKey('object'))], + [[$dataObject, 'array', null, false], serialize($dataObject->getDataByKey('array'))], + [[$dataObject, 'string', null, false], serialize($dataObject->getDataByKey('string'))], + [[$dataObject, 'int', null, false], serialize($dataObject->getDataByKey('int'))], + [ + [$dataObject, 'serialized_object', null, false], + serialize($dataObject->getDataByKey('serialized_object')) + ], + [[$dataObject, 'empty_value', null, true], null], + [[$dataObject, 'empty_value_with_default', new \stdClass(), false], 'O:8:"stdClass":0:{}'], + ]; + } + + /** + * @param array $arguments + * @param mixed $expectation + * @dataProvider unserializableFieldsDataProvider + */ + public function testUnserializeFields(array $arguments, $expectation) + { + /** @var DataObject $dataObject */ + list($dataObject, $field, $defaultValue) = $arguments; + + $abstractResource = new AbstractResourceStub(); + + $abstractResource->_unserializeField($dataObject, $field, $defaultValue); + + static::assertEquals($expectation, $dataObject->getDataByKey($field)); + } + + /** + * @return array + */ + public function unserializableFieldsDataProvider() + { + $dataObject = new DataObject( + [ + 'object' => serialize(new \stdClass()), + 'array' => serialize(['a', 'b', 'c']), + 'string' => serialize('i am string'), + 'int' => serialize(969), + 'serialized_object' => serialize('O:8:"stdClass":0:{}'), + 'empty_value_with_default' => serialize(''), + 'not_serialized_string' => 'i am string', + 'serialized_boolean_false' => serialize(false) + ] + ); + + $defaultValue = new \stdClass(); + + return [ + [[$dataObject, 'object', null], unserialize($dataObject->getDataByKey('object'))], + [[$dataObject, 'array', null], unserialize($dataObject->getDataByKey('array'))], + [[$dataObject, 'string', null], unserialize($dataObject->getDataByKey('string'))], + [[$dataObject, 'int', null], unserialize($dataObject->getDataByKey('int'))], + [[$dataObject, 'serialized_object', null], unserialize($dataObject->getDataByKey('serialized_object'))], + [[$dataObject, 'empty_value_with_default', $defaultValue], $defaultValue], + [[$dataObject, 'not_serialized_string', null], 'i am string'], + [[$dataObject, 'serialized_boolean_false', null], false] + ]; + } +} diff --git a/lib/internal/Magento/Framework/Search/Adapter/Mysql/Filter/Builder/Range.php b/lib/internal/Magento/Framework/Search/Adapter/Mysql/Filter/Builder/Range.php index f90cd032f9c15..d613afa8c7f2d 100644 --- a/lib/internal/Magento/Framework/Search/Adapter/Mysql/Filter/Builder/Range.php +++ b/lib/internal/Magento/Framework/Search/Adapter/Mysql/Filter/Builder/Range.php @@ -13,6 +13,8 @@ class Range implements FilterInterface { const CONDITION_PART_GREATER_THAN = '>='; const CONDITION_PART_LOWER_THAN = '<='; + const CONDITION_NEGATION_PART_GREATER_THAN = '>'; + const CONDITION_NEGATION_PART_LOWER_THAN = '<'; /** * @var ConditionManager @@ -54,7 +56,7 @@ private function getLeftConditionPart(RequestFilterInterface $filter, $isNegatio { return $this->getPart( $filter->getField(), - ($isNegation ? self::CONDITION_PART_LOWER_THAN : self::CONDITION_PART_GREATER_THAN), + ($isNegation ? self::CONDITION_NEGATION_PART_LOWER_THAN : self::CONDITION_PART_GREATER_THAN), $filter->getFrom() ); } @@ -68,7 +70,7 @@ private function getRightConditionPart(RequestFilterInterface $filter, $isNegati { return $this->getPart( $filter->getField(), - ($isNegation ? self::CONDITION_PART_GREATER_THAN : self::CONDITION_PART_LOWER_THAN), + ($isNegation ? self::CONDITION_NEGATION_PART_GREATER_THAN : self::CONDITION_PART_LOWER_THAN), $filter->getTo() ); } diff --git a/lib/internal/Magento/Framework/Search/Request/Binder.php b/lib/internal/Magento/Framework/Search/Request/Binder.php index b87011b36bbbd..3a3fc2be8ed8f 100644 --- a/lib/internal/Magento/Framework/Search/Request/Binder.php +++ b/lib/internal/Magento/Framework/Search/Request/Binder.php @@ -70,6 +70,10 @@ private function processDimensions($data, $bindData) */ private function processData($data, $bindData) { + array_walk_recursive($bindData, function (&$item) { + $item = trim($item); + }); + $bindData = array_filter($bindData); foreach ($data as $key => $value) { if (is_array($value)) { $data[$key] = $this->processData($value, $bindData); diff --git a/lib/internal/Magento/Framework/Search/Request/Builder.php b/lib/internal/Magento/Framework/Search/Request/Builder.php index cee13fbfe445a..8020545c6f6e8 100644 --- a/lib/internal/Magento/Framework/Search/Request/Builder.php +++ b/lib/internal/Magento/Framework/Search/Request/Builder.php @@ -7,6 +7,7 @@ namespace Magento\Framework\Search\Request; use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\Phrase; use Magento\Framework\Search\RequestInterface; class Builder @@ -33,6 +34,7 @@ class Builder 'dimensions' => [], 'placeholder' => [], ]; + /** * @var Cleaner */ @@ -130,7 +132,7 @@ public function create() /** @var array $data */ $data = $this->config->get($requestName); if ($data === null) { - throw new \InvalidArgumentException("Request name '{$requestName}' doesn't exist."); + throw new NonExistingRequestNameException(new Phrase("Request name '%1' doesn't exist.", [$requestName])); } $data = $this->binder->bind($data, $this->data); diff --git a/lib/internal/Magento/Framework/Search/Request/Cleaner.php b/lib/internal/Magento/Framework/Search/Request/Cleaner.php index 77f4b9d6c0fb0..7d2ad5173fd6b 100644 --- a/lib/internal/Magento/Framework/Search/Request/Cleaner.php +++ b/lib/internal/Magento/Framework/Search/Request/Cleaner.php @@ -56,6 +56,10 @@ public function clean(array $requestData) $requestData = $this->requestData; $this->clear(); + if (empty($requestData['queries']) && empty($requestData['filters'])) { + throw new EmptyRequestDataException(new Phrase('Request query and filter is not set')); + } + return $requestData; } diff --git a/lib/internal/Magento/Framework/Search/Request/EmptyRequestDataException.php b/lib/internal/Magento/Framework/Search/Request/EmptyRequestDataException.php new file mode 100644 index 0000000000000..72ea1ea354bca --- /dev/null +++ b/lib/internal/Magento/Framework/Search/Request/EmptyRequestDataException.php @@ -0,0 +1,11 @@ + '0', 'to' => '10', 'isNegation' => true, - 'expectedResult' => 'testField <= \'0\' OR testField >= \'10\'', + 'expectedResult' => 'testField < \'0\' OR testField > \'10\'', ], 'rangeWithoutFromValue' => [ 'field' => 'testField', @@ -130,7 +130,7 @@ public function buildQueryDataProvider() 'from' => null, 'to' => 50, 'isNegation' => true, - 'expectedResult' => 'testField >= \'50\'', + 'expectedResult' => 'testField > \'50\'', ], 'rangeWithoutToValue' => [ 'field' => 'testField', @@ -144,7 +144,7 @@ public function buildQueryDataProvider() 'from' => 50, 'to' => null, 'isNegation' => true, - 'expectedResult' => 'testField <= \'50\'', + 'expectedResult' => 'testField < \'50\'', ], 'rangeWithEmptyValues' => [ 'field' => 'testField', diff --git a/lib/internal/Magento/Framework/Search/Test/Unit/Request/BinderTest.php b/lib/internal/Magento/Framework/Search/Test/Unit/Request/BinderTest.php index f9e649aa03430..599ecd1d3e2d6 100644 --- a/lib/internal/Magento/Framework/Search/Test/Unit/Request/BinderTest.php +++ b/lib/internal/Magento/Framework/Search/Test/Unit/Request/BinderTest.php @@ -31,7 +31,11 @@ public function testBind() { $requestData = [ 'dimensions' => ['scope' => ['value' => '$sss$']], - 'queries' => ['query' => ['value' => '$query$']], + 'queries' => [ + 'query' => ['value' => '$query$'], + 'empty_query' => ['value' => '$empty_query$'], + 'space_query' => ['value' => '$space_query$'] + ], 'filters' => ['filter' => ['from' => '$from$', 'to' => '$to$', 'value' => '$filter$']], 'aggregations' => ['price' => ['method' => '$method$']], 'from' => 0, @@ -41,6 +45,8 @@ public function testBind() 'dimensions' => ['scope' => 'default'], 'placeholder' => [ '$query$' => 'match_query', + '$empty_query$' => ' ', + '$space_query$' => ' value', '$from$' => 'filter_from', '$to$' => 'filter_to', '$filter$' => 'filter_value', @@ -51,7 +57,11 @@ public function testBind() ]; $expectedResult = [ 'dimensions' => ['scope' => ['value' => 'default']], - 'queries' => ['query' => ['value' => 'match_query', 'is_bind' => true]], + 'queries' => [ + 'query' => ['value' => 'match_query', 'is_bind' => true], + 'empty_query' => ['value' => '$empty_query$'], + 'space_query' => ['value' => 'value', 'is_bind' => true] + ], 'filters' => [ 'filter' => [ 'from' => 'filter_from', @@ -67,6 +77,6 @@ public function testBind() $result = $this->binder->bind($requestData, $bindData); - $this->assertEquals($result, $expectedResult); + $this->assertEquals($expectedResult, $result); } } diff --git a/lib/internal/Magento/Framework/Search/Test/Unit/Request/BuilderTest.php b/lib/internal/Magento/Framework/Search/Test/Unit/Request/BuilderTest.php index 043736aa036b7..a7fddb55f58f8 100644 --- a/lib/internal/Magento/Framework/Search/Test/Unit/Request/BuilderTest.php +++ b/lib/internal/Magento/Framework/Search/Test/Unit/Request/BuilderTest.php @@ -94,7 +94,7 @@ public function testCreateInvalidArgumentExceptionNotDefined() } /** - * @expectedException \InvalidArgumentException + * @expectedException \Magento\Framework\Search\Request\NonExistingRequestNameException * @expectedExceptionMessage Request name 'rn' doesn't exist. */ public function testCreateInvalidArgumentException() diff --git a/lib/internal/Magento/Framework/Search/Test/Unit/Request/CleanerTest.php b/lib/internal/Magento/Framework/Search/Test/Unit/Request/CleanerTest.php index 117613ef1e79e..2d3368345b910 100644 --- a/lib/internal/Magento/Framework/Search/Test/Unit/Request/CleanerTest.php +++ b/lib/internal/Magento/Framework/Search/Test/Unit/Request/CleanerTest.php @@ -335,4 +335,64 @@ public function testCleanQueryNotExists() $this->cleaner->clean($requestData); } + + /** + * @expectedException \Magento\Framework\Search\Request\EmptyRequestDataException + * @expectedExceptionMessage Request query and filter is not set + */ + public function testCleanEmptyQueryAndFilter() + { + $this->status->expects($this->once()) + ->method('isEnabled') + ->will($this->returnValue(true)); + $requestData = [ + 'query' => 'bool_query', + 'queries' => [ + 'bool_query' => [ + 'queryReference' => [ + ['ref' => 'bool_query_rm'], + ['ref' => 'filtered_query_to_filter2'], + ], + 'type' => 'boolQuery', + ], + 'bool_query_rm' => [ + 'queryReference' => [ + ['ref' => 'match_query_rm'], + ['ref' => 'filtered_query_to_query'], + ['ref' => 'filtered_query_to_filter'], + ], + 'type' => 'boolQuery', + ], + 'match_query_rm' => ['value' => '$some$', 'type' => 'matchQuery'], + 'match_query_rm2' => ['value' => '$some2$', 'type' => 'matchQuery'], + 'filtered_query_to_query' => [ + 'queryReference' => [['ref' => 'match_query_rm2']], + 'type' => 'filteredQuery', + ], + 'filtered_query_to_filter' => [ + 'filterReference' => [['ref' => 'bool_filter']], + 'type' => 'filteredQuery', + ], + 'filtered_query_to_filter2' => [ + 'filterReference' => [['ref' => 'bool_filter2']], + 'type' => 'filteredQuery', + ], + ], + 'filters' => [ + 'bool_filter' => [ + 'filterReference' => [['ref' => 'term_filter'], ['ref' => 'range_filter']], + 'type' => 'boolFilter', + ], + 'term_filter' => ['value' => '$val$', 'type' => 'termFilter'], + 'range_filter' => ['from' => '$from$', 'to' => '$to$', 'type' => 'rangeFilter'], + 'bool_filter2' => [ + 'filterReference' => [['ref' => 'term_filter2']], + 'type' => 'boolFilter', + ], + 'term_filter2' => ['value' => '$val$', 'type' => 'termFilter'], + ], + ]; + + $this->cleaner->clean($requestData); + } } diff --git a/lib/internal/Magento/Framework/View/Page/Config.php b/lib/internal/Magento/Framework/View/Page/Config.php index 1ff41f5becfff..e862c764d74c4 100644 --- a/lib/internal/Magento/Framework/View/Page/Config.php +++ b/lib/internal/Magento/Framework/View/Page/Config.php @@ -216,7 +216,7 @@ public function getTitle() public function setMetadata($name, $content) { $this->build(); - $this->metadata[$name] = $content; + $this->metadata[$name] = htmlentities($content); } /** diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Page/ConfigTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Page/ConfigTest.php index 90079974edd0d..2e73629c03888 100644 --- a/lib/internal/Magento/Framework/View/Test/Unit/Page/ConfigTest.php +++ b/lib/internal/Magento/Framework/View/Test/Unit/Page/ConfigTest.php @@ -133,8 +133,10 @@ public function testMetadata() 'keywords' => null, 'robots' => null, 'name' => 'test_value', + 'html_encoded' => '<title><span class="test">Test</span></title>', ]; $this->model->setMetadata('name', 'test_value'); + $this->model->setMetadata('html_encoded', '<span class="test">Test</span>'); $this->assertEquals($expectedMetadata, $this->model->getMetadata()); }