From bf891993a2a7cdd9c953761eda850051a1872a4a Mon Sep 17 00:00:00 2001 From: Maksym Aposov Date: Fri, 15 Apr 2016 14:34:12 +0300 Subject: [PATCH 01/43] MAGETWO-51538: Exception when perform advanced search by space in any field --- .../ResourceModel/Advanced/Collection.php | 28 ++- .../ResourceModel/Fulltext/Collection.php | 28 ++- .../Magento/Search/etc/adminhtml/system.xml | 5 - .../ResourceModel/Advanced/CollectionTest.php | 47 +++++ .../ResourceModel/Fulltext/CollectionTest.php | 45 +++++ .../Search/Adapter/Mysql/AdapterTest.php | 188 +++++++++--------- .../Framework/Search/_files/requests.xml | 26 +-- .../Adapter/Mysql/Filter/Builder/Range.php | 6 +- .../Framework/Search/Request/Binder.php | 2 + .../Framework/Search/Request/Builder.php | 2 +- .../Framework/Search/Request/Cleaner.php | 4 + .../Request/EmptyRequestDataException.php | 11 + .../NonExistingRequestNameException.php | 11 + .../Mysql/Filter/Builder/RangeTest.php | 6 +- .../Search/Test/Unit/Request/BinderTest.php | 16 +- .../Search/Test/Unit/Request/BuilderTest.php | 2 +- .../Search/Test/Unit/Request/CleanerTest.php | 60 ++++++ 17 files changed, 357 insertions(+), 130 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/CatalogSearch/Model/ResourceModel/Advanced/CollectionTest.php create mode 100644 dev/tests/integration/testsuite/Magento/CatalogSearch/Model/ResourceModel/Fulltext/CollectionTest.php create mode 100644 lib/internal/Magento/Framework/Search/Request/EmptyRequestDataException.php create mode 100644 lib/internal/Magento/Framework/Search/Request/NonExistingRequestNameException.php 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..a6a88596e54ee 100644 --- a/app/code/Magento/CatalogSearch/Model/ResourceModel/Fulltext/Collection.php +++ b/app/code/Magento/CatalogSearch/Model/ResourceModel/Fulltext/Collection.php @@ -9,8 +9,13 @@ 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; + /** * Fulltext Collection * @SuppressWarnings(PHPMD.CouplingBetweenObjects) @@ -78,6 +83,11 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection */ private $searchResult; + /** + * @var SearchResultFactory + */ + private $searchResultFactory; + /** * @var \Magento\Framework\Api\FilterBuilder */ @@ -109,6 +119,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 +147,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 +323,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/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/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..d85fc55c041c4 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,35 @@ 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); + $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 +143,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 +160,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 +175,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 +189,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 +203,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 +218,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 +232,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 +281,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 +299,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 +350,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/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..aa3c31350f5aa 100644 --- a/lib/internal/Magento/Framework/Search/Request/Binder.php +++ b/lib/internal/Magento/Framework/Search/Request/Binder.php @@ -70,6 +70,8 @@ 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..91787a1aa1b1e 100644 --- a/lib/internal/Magento/Framework/Search/Request/Builder.php +++ b/lib/internal/Magento/Framework/Search/Request/Builder.php @@ -130,7 +130,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(__("Request name '{$requestName}' doesn't exist.")); } $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..0d1e393a3ac70 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(__('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..0419886a18db6 --- /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); + } } From 6a2c7a4d87152d034122b59fd61097a46d8762dd Mon Sep 17 00:00:00 2001 From: Maksym Aposov Date: Fri, 15 Apr 2016 16:43:19 +0300 Subject: [PATCH 02/43] MAGETWO-51538: Exception when perform advanced search by space in any field --- .../CatalogSearch/Model/ResourceModel/Fulltext/Collection.php | 1 - .../Test/Integrity/_files/blacklist/exception_hierarchy.txt | 2 ++ lib/internal/Magento/Framework/Search/Request/Binder.php | 4 +++- lib/internal/Magento/Framework/Search/Request/Builder.php | 4 +++- lib/internal/Magento/Framework/Search/Request/Cleaner.php | 2 +- .../Framework/Search/Request/EmptyRequestDataException.php | 2 +- .../Search/Request/NonExistingRequestNameException.php | 2 +- 7 files changed, 11 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/CatalogSearch/Model/ResourceModel/Fulltext/Collection.php b/app/code/Magento/CatalogSearch/Model/ResourceModel/Fulltext/Collection.php index a6a88596e54ee..1d3749f4a95a9 100644 --- a/app/code/Magento/CatalogSearch/Model/ResourceModel/Fulltext/Collection.php +++ b/app/code/Magento/CatalogSearch/Model/ResourceModel/Fulltext/Collection.php @@ -15,7 +15,6 @@ use Magento\Framework\Exception\LocalizedException; use Magento\Framework\App\ObjectManager; - /** * Fulltext Collection * @SuppressWarnings(PHPMD.CouplingBetweenObjects) 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/lib/internal/Magento/Framework/Search/Request/Binder.php b/lib/internal/Magento/Framework/Search/Request/Binder.php index aa3c31350f5aa..3a3fc2be8ed8f 100644 --- a/lib/internal/Magento/Framework/Search/Request/Binder.php +++ b/lib/internal/Magento/Framework/Search/Request/Binder.php @@ -70,7 +70,9 @@ private function processDimensions($data, $bindData) */ private function processData($data, $bindData) { - array_walk_recursive($bindData, function (&$item) { $item = trim($item);}); + array_walk_recursive($bindData, function (&$item) { + $item = trim($item); + }); $bindData = array_filter($bindData); foreach ($data as $key => $value) { if (is_array($value)) { diff --git a/lib/internal/Magento/Framework/Search/Request/Builder.php b/lib/internal/Magento/Framework/Search/Request/Builder.php index 91787a1aa1b1e..c94aa967b3a9b 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 NonExistingRequestNameException(__("Request name '{$requestName}' doesn't exist.")); + throw new NonExistingRequestNameException(new Phrase("Request name '{$requestName}' doesn't exist.")); } $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 0d1e393a3ac70..7d2ad5173fd6b 100644 --- a/lib/internal/Magento/Framework/Search/Request/Cleaner.php +++ b/lib/internal/Magento/Framework/Search/Request/Cleaner.php @@ -57,7 +57,7 @@ public function clean(array $requestData) $this->clear(); if (empty($requestData['queries']) && empty($requestData['filters'])) { - throw new EmptyRequestDataException(__('Request query and filter is not set')); + 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 index 0419886a18db6..72ea1ea354bca 100644 --- a/lib/internal/Magento/Framework/Search/Request/EmptyRequestDataException.php +++ b/lib/internal/Magento/Framework/Search/Request/EmptyRequestDataException.php @@ -8,4 +8,4 @@ class EmptyRequestDataException extends \InvalidArgumentException { -} \ No newline at end of file +} diff --git a/lib/internal/Magento/Framework/Search/Request/NonExistingRequestNameException.php b/lib/internal/Magento/Framework/Search/Request/NonExistingRequestNameException.php index d317ec16142e7..0746c80da09f9 100644 --- a/lib/internal/Magento/Framework/Search/Request/NonExistingRequestNameException.php +++ b/lib/internal/Magento/Framework/Search/Request/NonExistingRequestNameException.php @@ -8,4 +8,4 @@ class NonExistingRequestNameException extends \InvalidArgumentException { -} \ No newline at end of file +} From 9daba8c0431076b9b61fba9b2bcb5daed18d4b34 Mon Sep 17 00:00:00 2001 From: Stanislav Lopukhov Date: Sat, 16 Apr 2016 12:12:22 +0300 Subject: [PATCH 03/43] MAGETWO-51942: Does not work error message in category moving --- .../Magento/Catalog/Controller/Adminhtml/Category/Move.php | 6 +++--- .../view/adminhtml/templates/catalog/category/tree.phtml | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) 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/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); From 29e3010a065fe533f7364f69f890d791a2b57707 Mon Sep 17 00:00:00 2001 From: Illia Grybkov Date: Sun, 17 Apr 2016 19:01:46 +0300 Subject: [PATCH 04/43] MAGETWO-50923: Product save&duplicate creates create double portion of custom options in both products --- app/code/Magento/Catalog/Model/Product/Copier.php | 2 ++ app/code/Magento/Catalog/Test/Unit/Model/Product/CopierTest.php | 2 ++ 2 files changed, 4 insertions(+) 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/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( From 17d58de940f34b90eaf737fb9588b1b0ae95d6ee Mon Sep 17 00:00:00 2001 From: Maksym Aposov Date: Mon, 18 Apr 2016 13:57:10 +0300 Subject: [PATCH 05/43] MAGETWO-51538: Exception when perform advanced search by space in any field --- app/code/Magento/Indexer/Model/Source/ServiceSource.php | 2 +- .../Magento/Framework/Search/Adapter/Mysql/AdapterTest.php | 1 + lib/internal/Magento/Framework/Search/Request/Builder.php | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) 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/dev/tests/integration/testsuite/Magento/Framework/Search/Adapter/Mysql/AdapterTest.php b/dev/tests/integration/testsuite/Magento/Framework/Search/Adapter/Mysql/AdapterTest.php index d85fc55c041c4..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 @@ -109,6 +109,7 @@ private function assertProductIds($queryResponse, $expectedIds) $actualIds[] = $document->getId(); } sort($actualIds); + sort($expectedIds); $this->assertEquals($expectedIds, $actualIds); } diff --git a/lib/internal/Magento/Framework/Search/Request/Builder.php b/lib/internal/Magento/Framework/Search/Request/Builder.php index c94aa967b3a9b..8020545c6f6e8 100644 --- a/lib/internal/Magento/Framework/Search/Request/Builder.php +++ b/lib/internal/Magento/Framework/Search/Request/Builder.php @@ -132,7 +132,7 @@ public function create() /** @var array $data */ $data = $this->config->get($requestName); if ($data === null) { - throw new NonExistingRequestNameException(new Phrase("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); From 41a37aa63cc9a5680038a035be8dd76f1acaff5d Mon Sep 17 00:00:00 2001 From: Roman Ganin Date: Wed, 20 Apr 2016 11:04:08 +0300 Subject: [PATCH 06/43] MAGETWO-52023: Cannot create store view after product duplicate --- app/code/Magento/Catalog/Model/ResourceModel/Product.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product.php b/app/code/Magento/Catalog/Model/ResourceModel/Product.php index 9c402ea6ec5cc..e0752d0f510a3 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product.php @@ -532,7 +532,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 ) ); } From 5e83d6137608fe58747abe367f91e492561e4c60 Mon Sep 17 00:00:00 2001 From: Roman Ganin Date: Wed, 20 Apr 2016 11:21:58 +0300 Subject: [PATCH 07/43] MAGETWO-52023: Cannot create store view after product duplicate --- app/code/Magento/Catalog/Model/ResourceModel/Product.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product.php b/app/code/Magento/Catalog/Model/ResourceModel/Product.php index e0752d0f510a3..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( @@ -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( From 64bb2d274a5e166bba7eaddd545c73eca1edfca5 Mon Sep 17 00:00:00 2001 From: Valeriy Nayda Date: Wed, 20 Apr 2016 12:14:54 +0300 Subject: [PATCH 08/43] MAGETWO-50409: Changing order of configurable attributes is ignored on frontend --- .../Adminhtml/Product/Edit/Tab/Variations/Config/Matrix.php | 3 ++- .../Product/Form/Modifier/Data/AssociatedProducts.php | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) 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/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) { From ba9f4b8efba1c14c2d64e618228f1da91259395b Mon Sep 17 00:00:00 2001 From: "Yushkin, Dmytro" Date: Wed, 20 Apr 2016 16:10:37 +0300 Subject: [PATCH 09/43] MAGETWO-50198: [GITHUB] Options for Configurable product are merged in one product if Reorder #3654 --- app/code/Magento/Checkout/Model/Cart.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Checkout/Model/Cart.php b/app/code/Magento/Checkout/Model/Cart.php index 80cdf61499197..bc61352984659 100644 --- a/app/code/Magento/Checkout/Model/Cart.php +++ b/app/code/Magento/Checkout/Model/Cart.php @@ -257,7 +257,7 @@ public function addOrderItem($orderItem, $qtyFlag = null) if ($orderItem->getParentItem() === null) { $storeId = $this->_storeManager->getStore()->getId(); try { - $product = $this->productRepository->getById($orderItem->getProductId(), false, $storeId); + $product = $this->productRepository->getById($orderItem->getProductId(), false, $storeId, true); } catch (NoSuchEntityException $e) { return $this; } From e4225bd7a308c2440574a9f45d29d3bf33fe6d05 Mon Sep 17 00:00:00 2001 From: Dmytro Kvashnin Date: Wed, 20 Apr 2016 16:42:40 +0300 Subject: [PATCH 10/43] MAGETWO-52116: Remove additional_data merge to the root of Payment Info data object - Changed the way additional_data is passed to payment - Changed additional_data usage in PayPal Express and PayflowPro/Billing Agreements/PurchaseOrder/Braintree - Removed excessive set of Payment DTO into Payment Model --- .../Braintree/Observer/DataAssignObserver.php | 11 ++++- .../OfflinePayments/Model/Purchaseorder.php | 4 -- app/code/Magento/Payment/Model/Info.php | 3 -- .../Payment/Model/Method/AbstractMethod.php | 7 +--- app/code/Magento/Paypal/Model/Express.php | 17 +++++--- .../Method/Billing/AbstractAgreement.php | 40 ++++++++++--------- .../Paypal/Observer/PayflowProAddCcData.php | 14 ++++++- .../Quote/Model/PaymentMethodManagement.php | 4 -- .../Magento/Quote/Model/Quote/Payment.php | 5 ++- .../Magento/Quote/Model/QuoteManagement.php | 4 -- .../Sales/Model/Order/Payment/Info.php | 3 -- .../Vault/Observer/PaymentTokenAssigner.php | 9 ++++- .../Vault/Observer/VaultEnableAssigner.php | 11 ++++- 13 files changed, 79 insertions(+), 53 deletions(-) diff --git a/app/code/Magento/Braintree/Observer/DataAssignObserver.php b/app/code/Magento/Braintree/Observer/DataAssignObserver.php index 512ea25c103b6..42ceecad1ed6a 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,21 @@ 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) { $paymentInfo->setAdditionalInformation( $additionalInformationKey, - $data->getDataByKey($additionalInformationKey) + isset($additionalData[$additionalInformationKey]) + ? $additionalData[$additionalInformationKey] + : null ); } } 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/Paypal/Model/Express.php b/app/code/Magento/Paypal/Model/Express.php index a10a2654bf529..59f8928bee92f 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; @@ -668,12 +669,18 @@ 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)); + + $additionalData = $data->getData(PaymentInterface::KEY_ADDITIONAL_DATA); + + if (!is_array($additionalData) || !isset($additionalData[ExpressCheckout::PAYMENT_INFO_TRANSPORT_BILLING_AGREEMENT])) { + return $result; } + + $this->getInfoInstance() + ->setAdditionalInformation( + ExpressCheckout::PAYMENT_INFO_TRANSPORT_BILLING_AGREEMENT, + $additionalData[ExpressCheckout::PAYMENT_INFO_TRANSPORT_BILLING_AGREEMENT] + ); return $result; } 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..3c6d50c36d7be 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 * @@ -112,26 +115,27 @@ 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); + $additionalData = $data->getData(PaymentInterface::KEY_ADDITIONAL_DATA); + + if (!is_array($additionalData) || !isset($additionalData[self::TRANSPORT_BILLING_AGREEMENT_ID])) { + return $result; } - 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 $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 $result; } diff --git a/app/code/Magento/Paypal/Observer/PayflowProAddCcData.php b/app/code/Magento/Paypal/Observer/PayflowProAddCcData.php index 857322608e0d3..8a61438ff438b 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($ccData, $ccValue); + } } /** 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..9bf1158bdf797 100644 --- a/app/code/Magento/Quote/Model/Quote/Payment.php +++ b/app/code/Magento/Quote/Model/Quote/Payment.php @@ -4,6 +4,7 @@ * See COPYING.txt for license details. */ namespace Magento\Quote\Model\Quote; +use Magento\Quote\Api\Data\PaymentInterface; /** * Quote payment information @@ -34,7 +35,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 +168,8 @@ public function importData(array $data) } $method->assignData($data); + $data->unsetData(PaymentInterface::KEY_ADDITIONAL_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/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/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..f0a12d6dc4478 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) || !isset($additionalData[VaultConfigProvider::IS_ACTIVE_CODE])) { + 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) ); } } From f2186fe850b84c6dbefa64a46938caa02e620dca Mon Sep 17 00:00:00 2001 From: Dmytro Kvashnin Date: Wed, 20 Apr 2016 18:44:20 +0300 Subject: [PATCH 11/43] MAGETWO-52116: Remove additional_data merge to the root of Payment Info data object --- app/code/Magento/Braintree/Observer/DataAssignObserver.php | 6 ++---- app/code/Magento/Paypal/Observer/PayflowProAddCcData.php | 2 +- app/code/Magento/Vault/Observer/VaultEnableAssigner.php | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Braintree/Observer/DataAssignObserver.php b/app/code/Magento/Braintree/Observer/DataAssignObserver.php index 42ceecad1ed6a..fb528e3554d23 100644 --- a/app/code/Magento/Braintree/Observer/DataAssignObserver.php +++ b/app/code/Magento/Braintree/Observer/DataAssignObserver.php @@ -41,12 +41,10 @@ public function execute(Observer $observer) $paymentInfo = $this->readPaymentModelArgument($observer); foreach ($this->additionalInformationList as $additionalInformationKey) { - if ($data->getDataByKey($additionalInformationKey) !== null) { + if (isset($additionalData[$additionalInformationKey])) { $paymentInfo->setAdditionalInformation( $additionalInformationKey, - isset($additionalData[$additionalInformationKey]) - ? $additionalData[$additionalInformationKey] - : null + $additionalData[$additionalInformationKey] ); } } diff --git a/app/code/Magento/Paypal/Observer/PayflowProAddCcData.php b/app/code/Magento/Paypal/Observer/PayflowProAddCcData.php index 8a61438ff438b..92980e46ed8d7 100644 --- a/app/code/Magento/Paypal/Observer/PayflowProAddCcData.php +++ b/app/code/Magento/Paypal/Observer/PayflowProAddCcData.php @@ -49,7 +49,7 @@ public function execute(\Magento\Framework\Event\Observer $observer) // CC data should be stored explicitly foreach ($ccData as $ccKey => $ccValue) { - $paymentModel->setData($ccData, $ccValue); + $paymentModel->setData($ccKey, $ccValue); } } diff --git a/app/code/Magento/Vault/Observer/VaultEnableAssigner.php b/app/code/Magento/Vault/Observer/VaultEnableAssigner.php index f0a12d6dc4478..db112cf453912 100644 --- a/app/code/Magento/Vault/Observer/VaultEnableAssigner.php +++ b/app/code/Magento/Vault/Observer/VaultEnableAssigner.php @@ -22,7 +22,7 @@ public function execute(\Magento\Framework\Event\Observer $observer) $additionalData = $data->getData(PaymentInterface::KEY_ADDITIONAL_DATA); - if (!is_array($additionalData) || !isset($additionalData[VaultConfigProvider::IS_ACTIVE_CODE])) { + if (!is_array($additionalData)) { return; } From 1700f7c58d6464349ca1a236823e30d4ef0ef01e Mon Sep 17 00:00:00 2001 From: Roman Ganin Date: Thu, 21 Apr 2016 13:50:59 +0300 Subject: [PATCH 12/43] MAGETWO-48511: [GitHub] HTML tags inside the Meta Description on Edit Product Admin page brake the Storefront PDP layout #1514 #2613 #3090 #3244 #3255 #3813 #4031 #4073 --- lib/internal/Magento/Framework/View/Page/Config.php | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/View/Page/Config.php b/lib/internal/Magento/Framework/View/Page/Config.php index 1ff41f5becfff..93467aa8469fe 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] = $this->prepareMetaTagContent($content); } /** @@ -338,6 +338,17 @@ public function setKeywords($keywords) $this->setMetadata('keywords', $keywords); } + /** + * Prepare content for meta tag attribute + * + * @param $content + * @return string + */ + protected function prepareMetaTagContent($content) + { + return htmlentities($content); + } + /** * Retrieve content for keywords tag * From 6028b3449700f6dbaa4eb0e9ab7b3d41666ac327 Mon Sep 17 00:00:00 2001 From: Dmytro Kvashnin Date: Thu, 21 Apr 2016 15:04:05 +0300 Subject: [PATCH 13/43] MAGETWO-52116: Remove additional_data merge to the root of Payment Info data object - Added Unit tests - Reverted change in Quote Payment as redundand --- .../Unit/Observer/DataAssignObserverTest.php | 7 +++++-- .../Payment/Test/Unit/Model/InfoTest.php | 4 ++-- app/code/Magento/Quote/Model/Quote/Payment.php | 1 - .../Unit/Model/PaymentMethodManagementTest.php | 2 +- .../Test/Unit/Model/Order/Payment/InfoTest.php | 4 ++-- .../Unit/Observer/PaymentTokenAssignerTest.php | 17 +++++++++++++---- .../Unit/Observer/VaultEnableAssignerTest.php | 5 ++++- 7 files changed, 27 insertions(+), 13 deletions(-) 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/Payment/Test/Unit/Model/InfoTest.php b/app/code/Magento/Payment/Test/Unit/Model/InfoTest.php index 22ebf692706b3..6d09243cb3b56 100644 --- a/app/code/Magento/Payment/Test/Unit/Model/InfoTest.php +++ b/app/code/Magento/Payment/Test/Unit/Model/InfoTest.php @@ -251,9 +251,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/Quote/Model/Quote/Payment.php b/app/code/Magento/Quote/Model/Quote/Payment.php index 9bf1158bdf797..2efd10b010f47 100644 --- a/app/code/Magento/Quote/Model/Quote/Payment.php +++ b/app/code/Magento/Quote/Model/Quote/Payment.php @@ -168,7 +168,6 @@ public function importData(array $data) } $method->assignData($data); - $data->unsetData(PaymentInterface::KEY_ADDITIONAL_DATA); /* * validating the payment 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..56e3e79257ae5 100644 --- a/app/code/Magento/Quote/Test/Unit/Model/PaymentMethodManagementTest.php +++ b/app/code/Magento/Quote/Test/Unit/Model/PaymentMethodManagementTest.php @@ -111,7 +111,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/Sales/Test/Unit/Model/Order/Payment/InfoTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Payment/InfoTest.php index f47806866aef6..5758037b3115b 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 @@ -253,9 +253,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/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); From 1549ea78481734d311178933901c4cafe02c42b4 Mon Sep 17 00:00:00 2001 From: Dmytro Kvashnin Date: Thu, 21 Apr 2016 15:27:16 +0300 Subject: [PATCH 14/43] MAGETWO-52116: Remove additional_data merge to the root of Payment Info data object - Code style fixes --- app/code/Magento/Payment/Test/Unit/Model/InfoTest.php | 6 +----- app/code/Magento/Paypal/Model/Express.php | 5 ++++- .../Quote/Test/Unit/Model/PaymentMethodManagementTest.php | 1 + .../Sales/Test/Unit/Model/Order/Payment/InfoTest.php | 5 +---- 4 files changed, 7 insertions(+), 10 deletions(-) diff --git a/app/code/Magento/Payment/Test/Unit/Model/InfoTest.php b/app/code/Magento/Payment/Test/Unit/Model/InfoTest.php index 6d09243cb3b56..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'; diff --git a/app/code/Magento/Paypal/Model/Express.php b/app/code/Magento/Paypal/Model/Express.php index 59f8928bee92f..445264b5c78ba 100644 --- a/app/code/Magento/Paypal/Model/Express.php +++ b/app/code/Magento/Paypal/Model/Express.php @@ -672,7 +672,10 @@ public function assignData(\Magento\Framework\DataObject $data) $additionalData = $data->getData(PaymentInterface::KEY_ADDITIONAL_DATA); - if (!is_array($additionalData) || !isset($additionalData[ExpressCheckout::PAYMENT_INFO_TRANSPORT_BILLING_AGREEMENT])) { + if ( + !is_array($additionalData) + || !isset($additionalData[ExpressCheckout::PAYMENT_INFO_TRANSPORT_BILLING_AGREEMENT]) + ) { return $result; } diff --git a/app/code/Magento/Quote/Test/Unit/Model/PaymentMethodManagementTest.php b/app/code/Magento/Quote/Test/Unit/Model/PaymentMethodManagementTest.php index 56e3e79257ae5..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 */ 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 5758037b3115b..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. From a3558b6e6df19bf77001ab7c29c7ec3e6343d679 Mon Sep 17 00:00:00 2001 From: Dmytro Kvashnin Date: Thu, 21 Apr 2016 18:25:26 +0300 Subject: [PATCH 15/43] MAGETWO-52116: Remove additional_data merge to the root of Payment Info data object - Added tests --- .../Unit/Model/Method/AbstractMethodTest.php | 36 ++++- app/code/Magento/Paypal/Model/Express.php | 7 +- .../Method/Billing/AbstractAgreement.php | 12 +- .../Paypal/Test/Unit/Model/ExpressTest.php | 93 ++++++++++- .../Method/Billing/AbstractAgreementStub.php | 30 ++++ .../Method/Billing/AbstractAgreementTest.php | 150 ++++++++++++++++++ .../Magento/Quote/Model/Quote/Payment.php | 1 + 7 files changed, 312 insertions(+), 17 deletions(-) create mode 100644 app/code/Magento/Paypal/Test/Unit/Model/Payment/Method/Billing/AbstractAgreementStub.php create mode 100644 app/code/Magento/Paypal/Test/Unit/Model/Payment/Method/Billing/AbstractAgreementTest.php 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 445264b5c78ba..80c9ef0625d96 100644 --- a/app/code/Magento/Paypal/Model/Express.php +++ b/app/code/Magento/Paypal/Model/Express.php @@ -668,7 +668,7 @@ public function getApi() */ public function assignData(\Magento\Framework\DataObject $data) { - $result = parent::assignData($data); + parent::assignData($data); $additionalData = $data->getData(PaymentInterface::KEY_ADDITIONAL_DATA); @@ -676,7 +676,7 @@ public function assignData(\Magento\Framework\DataObject $data) !is_array($additionalData) || !isset($additionalData[ExpressCheckout::PAYMENT_INFO_TRANSPORT_BILLING_AGREEMENT]) ) { - return $result; + return $this; } $this->getInfoInstance() @@ -684,7 +684,8 @@ public function assignData(\Magento\Framework\DataObject $data) ExpressCheckout::PAYMENT_INFO_TRANSPORT_BILLING_AGREEMENT, $additionalData[ExpressCheckout::PAYMENT_INFO_TRANSPORT_BILLING_AGREEMENT] ); - return $result; + + 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 3c6d50c36d7be..42894ddeec49d 100644 --- a/app/code/Magento/Paypal/Model/Payment/Method/Billing/AbstractAgreement.php +++ b/app/code/Magento/Paypal/Model/Payment/Method/Billing/AbstractAgreement.php @@ -113,17 +113,17 @@ public function isAvailable(\Magento\Quote\Api\Data\CartInterface $quote = null) */ public function assignData(\Magento\Framework\DataObject $data) { - $result = parent::assignData($data); + parent::assignData($data); $additionalData = $data->getData(PaymentInterface::KEY_ADDITIONAL_DATA); if (!is_array($additionalData) || !isset($additionalData[self::TRANSPORT_BILLING_AGREEMENT_ID])) { - return $result; + return $this; } $id = $additionalData[self::TRANSPORT_BILLING_AGREEMENT_ID]; if (!$id || !is_numeric($id)) { - return $result; + return $this; } $info = $this->getInfoInstance(); @@ -131,17 +131,17 @@ public function assignData(\Magento\Framework\DataObject $data) $ba = $this->_agreementFactory->create(); $ba->load($id); - if ($ba->getId() && $ba->getCustomerId() === $info->getQuote()->getCustomerId()) { + 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 $result; + return $this; } /** * @param object $quote - * @return void + * @return bool */ abstract protected function _isAvailable($quote); } 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..5f6a4fbcadc74 --- /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/Quote/Payment.php b/app/code/Magento/Quote/Model/Quote/Payment.php index 2efd10b010f47..cdd295114c3d5 100644 --- a/app/code/Magento/Quote/Model/Quote/Payment.php +++ b/app/code/Magento/Quote/Model/Quote/Payment.php @@ -4,6 +4,7 @@ * See COPYING.txt for license details. */ namespace Magento\Quote\Model\Quote; + use Magento\Quote\Api\Data\PaymentInterface; /** From 4d94694f53d46a6dd37643feb0ff28d04d8a6bb3 Mon Sep 17 00:00:00 2001 From: Dmytro Kvashnin Date: Thu, 21 Apr 2016 18:36:56 +0300 Subject: [PATCH 16/43] MAGETWO-52116: Remove additional_data merge to the root of Payment Info data object --- .../Unit/Model/Payment/Method/Billing/AbstractAgreementStub.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 index 5f6a4fbcadc74..c0eba7bb1807f 100644 --- 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 @@ -27,4 +27,4 @@ protected function _isAvailable($quote) { return false; } -} \ No newline at end of file +} From 0041c43b27db0e027dc02423a0d513c9ded2a40b Mon Sep 17 00:00:00 2001 From: Roman Ganin Date: Thu, 21 Apr 2016 19:21:52 +0300 Subject: [PATCH 17/43] MAGETWO-48511: [GitHub] HTML tags inside the Meta Description on Edit Product Admin page brake the Storefront PDP layout #1514 #2613 #3090 #3244 #3255 #3813 #4031 #4073 - CR changes --- lib/internal/Magento/Framework/View/Page/Config.php | 13 +------------ .../Framework/View/Test/Unit/Page/ConfigTest.php | 2 ++ 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/lib/internal/Magento/Framework/View/Page/Config.php b/lib/internal/Magento/Framework/View/Page/Config.php index 93467aa8469fe..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] = $this->prepareMetaTagContent($content); + $this->metadata[$name] = htmlentities($content); } /** @@ -338,17 +338,6 @@ public function setKeywords($keywords) $this->setMetadata('keywords', $keywords); } - /** - * Prepare content for meta tag attribute - * - * @param $content - * @return string - */ - protected function prepareMetaTagContent($content) - { - return htmlentities($content); - } - /** * Retrieve content for keywords tag * 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()); } From a39526b7478018c2b1d9ff7a1e5feffd682cf71d Mon Sep 17 00:00:00 2001 From: Stanislav Lopukhov Date: Fri, 22 Apr 2016 11:30:37 +0300 Subject: [PATCH 18/43] MAGETWO-51982: [CE] Products not displayed in category products if assigned to 2nd website only --- .../Magento/Catalog/Block/Adminhtml/Category/Tab/Product.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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..8ed0ad9e11cc2 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,9 @@ protected function _prepareCollection() 'category_id=' . (int)$this->getRequest()->getParam('id', 0), 'left' ); + if ($this->getRequest()->getParam('store', 0) > 0) { + $collection->addStoreFilter($this->getRequest()->getParam('store')); + } $this->setCollection($collection); if ($this->getCategory()->getProductsReadonly()) { From 79e2a31522b2543b48c3e821db54baa4482c2ae3 Mon Sep 17 00:00:00 2001 From: Stanislav Lopukhov Date: Fri, 22 Apr 2016 11:55:13 +0300 Subject: [PATCH 19/43] MAGETWO-51982: [CE] Products not displayed in category products if assigned to 2nd website only --- .../Magento/Catalog/Block/Adminhtml/Category/Tab/Product.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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 8ed0ad9e11cc2..976dd4c922263 100644 --- a/app/code/Magento/Catalog/Block/Adminhtml/Category/Tab/Product.php +++ b/app/code/Magento/Catalog/Block/Adminhtml/Category/Tab/Product.php @@ -112,8 +112,9 @@ protected function _prepareCollection() 'category_id=' . (int)$this->getRequest()->getParam('id', 0), 'left' ); - if ($this->getRequest()->getParam('store', 0) > 0) { - $collection->addStoreFilter($this->getRequest()->getParam('store')); + $storeId = (int)$this->getRequest()->getParam('store', 0); + if ($storeId > 0) { + $collection->addStoreFilter($storeId); } $this->setCollection($collection); From 0a632518cce7fd49dda631bac1a3cb061adae684 Mon Sep 17 00:00:00 2001 From: Dmytro Kvashnin Date: Fri, 22 Apr 2016 12:59:59 +0300 Subject: [PATCH 20/43] MAGETWO-52116: Remove additional_data merge to the root of Payment Info data object - Fixed integration test --- .../Model/Payment/Method/Billing/AbstractAgreementTest.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) 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); From ceb9e841fd112c76d5d0bb00c63991f4c536974a Mon Sep 17 00:00:00 2001 From: Dmytro Kvashnin Date: Fri, 22 Apr 2016 14:51:00 +0300 Subject: [PATCH 21/43] MAGETWO-52226: Remove conditional serialization of AbstractResource::serializableFields - Removed conditional serialization from AbstractResource --- .../Model/ResourceModel/AbstractResource.php | 22 ++-- .../ResourceModel/AbstractResourceStub.php | 53 +++++++++ .../ResourceModel/AbstractResourceTest.php | 101 ++++++++++++++++++ 3 files changed, 163 insertions(+), 13 deletions(-) create mode 100644 lib/internal/Magento/Framework/Model/Test/Unit/ResourceModel/AbstractResourceStub.php create mode 100644 lib/internal/Magento/Framework/Model/Test/Unit/ResourceModel/AbstractResourceTest.php diff --git a/lib/internal/Magento/Framework/Model/ResourceModel/AbstractResource.php b/lib/internal/Magento/Framework/Model/ResourceModel/AbstractResource.php index 451ec868bef31..e3a3a0914fac0 100644 --- a/lib/internal/Magento/Framework/Model/ResourceModel/AbstractResource.php +++ b/lib/internal/Magento/Framework/Model/ResourceModel/AbstractResource.php @@ -117,17 +117,10 @@ public function rollBack() protected function _serializeField(\Magento\Framework\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; @@ -144,10 +137,13 @@ protected function _serializeField(\Magento\Framework\DataObject $object, $field protected function _unserializeField(\Magento\Framework\DataObject $object, $field, $defaultValue = null) { $value = $object->getData($field); + + $value = $value ? unserialize($value) : $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); } } 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..a5d0c9c318c8a --- /dev/null +++ b/lib/internal/Magento/Framework/Model/Test/Unit/ResourceModel/AbstractResourceStub.php @@ -0,0 +1,53 @@ +_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('') + ] + ); + + $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], + ]; + } +} From a3e310ac4f97e03190e5e80701386fd491711f35 Mon Sep 17 00:00:00 2001 From: Dmytro Kvashnin Date: Fri, 22 Apr 2016 15:23:30 +0300 Subject: [PATCH 22/43] MAGETWO-52226: Remove conditional serialization of AbstractResource::serializableFields --- .../Model/ResourceModel/AbstractResource.php | 14 ++++++-------- .../Unit/ResourceModel/AbstractResourceStub.php | 9 +++++---- .../Unit/ResourceModel/AbstractResourceTest.php | 5 ++++- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/lib/internal/Magento/Framework/Model/ResourceModel/AbstractResource.php b/lib/internal/Magento/Framework/Model/ResourceModel/AbstractResource.php index e3a3a0914fac0..d0561266e7d2a 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; /** @@ -108,13 +106,13 @@ 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) && $unsetEmpty) { @@ -134,7 +132,7 @@ 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); @@ -150,11 +148,11 @@ protected function _unserializeField(\Magento\Framework\DataObject $object, $fie /** * 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 index a5d0c9c318c8a..13370114aa7ae 100644 --- a/lib/internal/Magento/Framework/Model/Test/Unit/ResourceModel/AbstractResourceStub.php +++ b/lib/internal/Magento/Framework/Model/Test/Unit/ResourceModel/AbstractResourceStub.php @@ -5,6 +5,7 @@ */ namespace Magento\Framework\Model\Test\Unit\ResourceModel; +use Magento\Framework\DataObject; use Magento\Framework\Model\ResourceModel\AbstractResource; class AbstractResourceStub extends AbstractResource @@ -30,23 +31,23 @@ protected function getConnection() } /** - * @param \Magento\Framework\DataObject $object + * @param DataObject $object * @param string $field * @param null $defaultValue * @param bool $unsetEmpty * @return $this */ - public function _serializeField(\Magento\Framework\DataObject $object, $field, $defaultValue = null, $unsetEmpty = false) + public function _serializeField(DataObject $object, $field, $defaultValue = null, $unsetEmpty = false) { return parent::_serializeField($object, $field, $defaultValue, $unsetEmpty); } /** - * @param \Magento\Framework\DataObject $object + * @param DataObject $object * @param string $field * @param null $defaultValue */ - public function _unserializeField(\Magento\Framework\DataObject $object, $field, $defaultValue = null) + public function _unserializeField(DataObject $object, $field, $defaultValue = null) { parent::_unserializeField($object, $field, $defaultValue); } diff --git a/lib/internal/Magento/Framework/Model/Test/Unit/ResourceModel/AbstractResourceTest.php b/lib/internal/Magento/Framework/Model/Test/Unit/ResourceModel/AbstractResourceTest.php index 7721ca78e62a3..c8c87006123e5 100644 --- a/lib/internal/Magento/Framework/Model/Test/Unit/ResourceModel/AbstractResourceTest.php +++ b/lib/internal/Magento/Framework/Model/Test/Unit/ResourceModel/AbstractResourceTest.php @@ -48,7 +48,10 @@ public function serializableFieldsDataProvider() [[$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, '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:{}'], ]; From e3a667ff95d050cce8022f4b58bb844ef6f0b516 Mon Sep 17 00:00:00 2001 From: Dmytro Kvashnin Date: Fri, 22 Apr 2016 15:41:02 +0300 Subject: [PATCH 23/43] MAGETWO-52226: Remove conditional serialization of AbstractResource::serializableFields --- .../Magento/Framework/Model/ResourceModel/AbstractResource.php | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Model/ResourceModel/AbstractResource.php b/lib/internal/Magento/Framework/Model/ResourceModel/AbstractResource.php index d0561266e7d2a..96839aba0f904 100644 --- a/lib/internal/Magento/Framework/Model/ResourceModel/AbstractResource.php +++ b/lib/internal/Magento/Framework/Model/ResourceModel/AbstractResource.php @@ -31,7 +31,6 @@ public function __construct() */ abstract protected function _construct(); - /** * Get connection * From 9a8886264353bae25609b55ff349ad2699c050d8 Mon Sep 17 00:00:00 2001 From: Dmytro Kvashnin Date: Fri, 22 Apr 2016 17:16:10 +0300 Subject: [PATCH 24/43] MAGETWO-52226: Remove conditional serialization of AbstractResource::serializableFields --- .../Framework/Model/ResourceModel/AbstractResource.php | 4 +++- .../Model/Test/Unit/ResourceModel/AbstractResourceTest.php | 6 +++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/internal/Magento/Framework/Model/ResourceModel/AbstractResource.php b/lib/internal/Magento/Framework/Model/ResourceModel/AbstractResource.php index 96839aba0f904..7ab5f4e1ad100 100644 --- a/lib/internal/Magento/Framework/Model/ResourceModel/AbstractResource.php +++ b/lib/internal/Magento/Framework/Model/ResourceModel/AbstractResource.php @@ -135,7 +135,9 @@ protected function _unserializeField(DataObject $object, $field, $defaultValue = { $value = $object->getData($field); - $value = $value ? unserialize($value) : $value; + if ($value) { + $value = @unserialize($value) !== false || $value === 'b:0;' ? unserialize($value) : $value; + } if (empty($value)) { $object->setData($field, $defaultValue); diff --git a/lib/internal/Magento/Framework/Model/Test/Unit/ResourceModel/AbstractResourceTest.php b/lib/internal/Magento/Framework/Model/Test/Unit/ResourceModel/AbstractResourceTest.php index c8c87006123e5..6508f3d8122d3 100644 --- a/lib/internal/Magento/Framework/Model/Test/Unit/ResourceModel/AbstractResourceTest.php +++ b/lib/internal/Magento/Framework/Model/Test/Unit/ResourceModel/AbstractResourceTest.php @@ -86,7 +86,9 @@ public function unserializableFieldsDataProvider() 'string' => serialize('i am string'), 'int' => serialize(969), 'serialized_object' => serialize('O:8:"stdClass":0:{}'), - 'empty_value_with_default' => serialize('') + 'empty_value_with_default' => serialize(''), + 'not_serialized_string' => 'i am string', + 'serialized_boolean_false' => serialize(false) ] ); @@ -99,6 +101,8 @@ public function unserializableFieldsDataProvider() [[$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] ]; } } From 4a229d10b9d7ced09dd3c5a7603da9be4f6b8eaa Mon Sep 17 00:00:00 2001 From: Dmytro Kvashnin Date: Fri, 22 Apr 2016 18:29:07 +0300 Subject: [PATCH 25/43] MAGETWO-52226: Remove conditional serialization of AbstractResource::serializableFields --- .../Framework/Model/ResourceModel/AbstractResource.php | 3 ++- .../Model/Test/Unit/ResourceModel/AbstractResourceTest.php | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/internal/Magento/Framework/Model/ResourceModel/AbstractResource.php b/lib/internal/Magento/Framework/Model/ResourceModel/AbstractResource.php index 7ab5f4e1ad100..4e38d13aa72f6 100644 --- a/lib/internal/Magento/Framework/Model/ResourceModel/AbstractResource.php +++ b/lib/internal/Magento/Framework/Model/ResourceModel/AbstractResource.php @@ -136,7 +136,8 @@ protected function _unserializeField(DataObject $object, $field, $defaultValue = $value = $object->getData($field); if ($value) { - $value = @unserialize($value) !== false || $value === 'b:0;' ? unserialize($value) : $value; + $unserializedValue = @unserialize($value); + $value = $unserializedValue !== false || $value === 'b:0;' ? $unserializedValue : $value; } if (empty($value)) { diff --git a/lib/internal/Magento/Framework/Model/Test/Unit/ResourceModel/AbstractResourceTest.php b/lib/internal/Magento/Framework/Model/Test/Unit/ResourceModel/AbstractResourceTest.php index 6508f3d8122d3..7fc749948b3b3 100644 --- a/lib/internal/Magento/Framework/Model/Test/Unit/ResourceModel/AbstractResourceTest.php +++ b/lib/internal/Magento/Framework/Model/Test/Unit/ResourceModel/AbstractResourceTest.php @@ -88,7 +88,8 @@ public function unserializableFieldsDataProvider() 'serialized_object' => serialize('O:8:"stdClass":0:{}'), 'empty_value_with_default' => serialize(''), 'not_serialized_string' => 'i am string', - 'serialized_boolean_false' => serialize(false) + 'serialized_boolean_false' => serialize(false), + 'olol' => 'a:1:{s:22:"additional_information";O:8:"stdClaes":0:{}}' ] ); @@ -102,7 +103,8 @@ public function unserializableFieldsDataProvider() [[$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] + [[$dataObject, 'serialized_boolean_false', null], false], + [[$dataObject, 'olol', null], false], ]; } } From 562971a2155c6c26f04cca2e4e4819848e6e5e17 Mon Sep 17 00:00:00 2001 From: Kateryna Muntianu Date: Fri, 22 Apr 2016 19:22:46 +0300 Subject: [PATCH 26/43] MAGETWO-52176: New Accounts Report incorrectly calculates accounts for multiple websites --- .../Reports/view/adminhtml/layout/reports_report_grid.xml | 3 --- 1 file changed, 3 deletions(-) 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 From 13a961f181ff7740a12b0a994ae585fa74a6a05e Mon Sep 17 00:00:00 2001 From: Roman Ganin Date: Sat, 23 Apr 2016 11:46:59 +0300 Subject: [PATCH 27/43] MAGETWO-48511: [GitHub] HTML tags inside the Meta Description on Edit Product Admin page brake the Storefront PDP layout #1514 #2613 #3090 #3244 #3255 #3813 #4031 #4073 - fixed opengraph tags template --- .../templates/product/view/opengraph/general.phtml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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..2310323452518 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'); ?> From fe1eb2f2b2ee7a4f8b937f5cf8b850e9c0ef0b2a Mon Sep 17 00:00:00 2001 From: Roman Ganin Date: Sat, 23 Apr 2016 12:47:47 +0300 Subject: [PATCH 28/43] MAGETWO-48511: [GitHub] HTML tags inside the Meta Description on Edit Product Admin page brake the Storefront PDP layout #1514 #2613 #3090 #3244 #3255 #3813 #4031 #4073 - fixed opengraph tags template --- .../templates/product/view/opengraph/general.phtml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 2310323452518..fd66871b28ab8 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'); ?> From 2ff73d2564631ac0ad6993c7768a7a7374830441 Mon Sep 17 00:00:00 2001 From: vzabaznov Date: Sat, 23 Apr 2016 16:02:00 +0300 Subject: [PATCH 29/43] MAGETWO-52250: Remove double semicolon --- .../Test/Unit/Model/Product/Gallery/GalleryManagementTest.php | 2 +- app/code/Magento/Quote/Test/Unit/Model/QuoteTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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/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( From de942b806f749c772a9d9a5413937571db898adf Mon Sep 17 00:00:00 2001 From: Roman Ganin Date: Sat, 23 Apr 2016 17:39:51 +0300 Subject: [PATCH 30/43] MAGETWO-48527: [GITHUB] Wrong customer id in Abandoned Carts grid #3162 --- .../Reports/Model/ResourceModel/Quote/Collection.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) 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)); + } + } } } } From 2fdd82ee340cfbdf7f9cec69fbea0299cecb1016 Mon Sep 17 00:00:00 2001 From: Maksym Aposov Date: Sun, 24 Apr 2016 09:56:15 +0300 Subject: [PATCH 31/43] MAGETWO-51116: There is no ability to add product with file custom option to shopping cart as guest user using API --- .../Product/Option/Type/File/Validator.php | 2 +- .../Product/Option/Type/File/Processor.php | 10 +- .../Product/Option/Type/File/Validator.php | 52 ---- .../Option/Type/File/ValidatorTest.php | 223 ------------------ .../Magento/Catalog/etc/webapi_rest/di.xml | 1 - .../Option/Type/File/ProcessorTest.php | 100 ++++++++ 6 files changed, 105 insertions(+), 283 deletions(-) delete mode 100644 app/code/Magento/Catalog/Model/Webapi/Product/Option/Type/File/Validator.php delete mode 100644 app/code/Magento/Catalog/Test/Unit/Webapi/Product/Option/Type/File/ValidatorTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/Model/Webapi/Product/Option/Type/File/ProcessorTest.php 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/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/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/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='; + } +} From f5d99fe0f7145c5b273688ef7c6d9684ef738971 Mon Sep 17 00:00:00 2001 From: Maksym Aposov Date: Sun, 24 Apr 2016 12:22:23 +0300 Subject: [PATCH 32/43] MAGETWO-51116: There is no ability to add product with file custom option to shopping cart as guest user using API --- .../Product/Option/Type/File/ValidatorInfoTest.php | 10 ++++++---- .../Magento/Catalog/_files/validate_image_info.php | 11 +++++++---- .../Catalog/_files/validate_image_info_rollback.php | 8 +++++--- 3 files changed, 18 insertions(+), 11 deletions(-) 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/_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); } From a6a900af22cff0b9af19dc667bf43746e90f3d27 Mon Sep 17 00:00:00 2001 From: Valeriy Nayda Date: Mon, 25 Apr 2016 11:40:19 +0300 Subject: [PATCH 33/43] MAGETWO-50409: Changing order of configurable attributes is ignored on frontend --- .../ConfigurableProduct/Model/ConfigurableAttributeData.php | 2 +- .../view/frontend/templates/product/layered/renderer.phtml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/ConfigurableProduct/Model/ConfigurableAttributeData.php b/app/code/Magento/ConfigurableProduct/Model/ConfigurableAttributeData.php index 6c8eae58981a8..03ca4e174f1da 100644 --- a/app/code/Magento/ConfigurableProduct/Model/ConfigurableAttributeData.php +++ b/app/code/Magento/ConfigurableProduct/Model/ConfigurableAttributeData.php @@ -30,7 +30,7 @@ public function getAttributesData(Product $product, array $options = []) if ($attributeOptionsData) { $productAttribute = $attribute->getProductAttribute(); $attributeId = $productAttribute->getId(); - $attributes[$attributeId] = [ + $attributes['swatch_' . $attributeId] = [ 'id' => $attributeId, 'code' => $productAttribute->getAttributeCode(), 'label' => $productAttribute->getStoreLabel($product->getStoreId()), 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..de57c7f47747c 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): ?> From bc7c2fdc6ec0af0186547935ef682f107f7e5b70 Mon Sep 17 00:00:00 2001 From: Valeriy Nayda Date: Mon, 25 Apr 2016 12:36:48 +0300 Subject: [PATCH 34/43] MAGETWO-50409: Changing order of configurable attributes is ignored on frontend --- .../ConfigurableProduct/Model/ConfigurableAttributeData.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/ConfigurableProduct/Model/ConfigurableAttributeData.php b/app/code/Magento/ConfigurableProduct/Model/ConfigurableAttributeData.php index 03ca4e174f1da..65195998274aa 100644 --- a/app/code/Magento/ConfigurableProduct/Model/ConfigurableAttributeData.php +++ b/app/code/Magento/ConfigurableProduct/Model/ConfigurableAttributeData.php @@ -30,7 +30,7 @@ public function getAttributesData(Product $product, array $options = []) if ($attributeOptionsData) { $productAttribute = $attribute->getProductAttribute(); $attributeId = $productAttribute->getId(); - $attributes['swatch_' . $attributeId] = [ + $attributes[] = [ 'id' => $attributeId, 'code' => $productAttribute->getAttributeCode(), 'label' => $productAttribute->getStoreLabel($product->getStoreId()), From 071ba86109da628eebbdecd85cae31c8f5a8e930 Mon Sep 17 00:00:00 2001 From: Valeriy Nayda Date: Mon, 25 Apr 2016 13:10:58 +0300 Subject: [PATCH 35/43] MAGETWO-50409: Changing order of configurable attributes is ignored on frontend --- .../Model/ConfigurableAttributeData.php | 3 ++- .../Test/Unit/Model/ConfigurableAttributeDataTest.php | 8 +++++++- .../Swatches/view/frontend/web/js/swatch-renderer.js | 10 ++++++++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/ConfigurableProduct/Model/ConfigurableAttributeData.php b/app/code/Magento/ConfigurableProduct/Model/ConfigurableAttributeData.php index 65195998274aa..be39893145626 100644 --- a/app/code/Magento/ConfigurableProduct/Model/ConfigurableAttributeData.php +++ b/app/code/Magento/ConfigurableProduct/Model/ConfigurableAttributeData.php @@ -30,11 +30,12 @@ public function getAttributesData(Product $product, array $options = []) if ($attributeOptionsData) { $productAttribute = $attribute->getProductAttribute(); $attributeId = $productAttribute->getId(); - $attributes[] = [ + $attributes[$attributeId] = [ 'id' => $attributeId, '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/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 */ From e245408161b7a6841b721eda9ff83275e53c6d3a Mon Sep 17 00:00:00 2001 From: Valeriy Nayda Date: Mon, 25 Apr 2016 13:16:30 +0300 Subject: [PATCH 36/43] MAGETWO-50409: Changing order of configurable attributes is ignored on frontend --- .../view/frontend/templates/product/layered/renderer.phtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 de57c7f47747c..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): ?> From 423ff9eb3bbbcc9aeaedf355f466d1caa4cd4072 Mon Sep 17 00:00:00 2001 From: Roman Ganin Date: Mon, 25 Apr 2016 13:59:58 +0300 Subject: [PATCH 37/43] MAGETWO-48527: [GITHUB] Wrong customer id in Abandoned Carts grid #3162 --- .../Test/Unit/Model/ResourceModel/Quote/CollectionTest.php | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) 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..3b0cbd5c8a6c0 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,7 +110,7 @@ public function testResolveCustomerNames() $customerName = "CONCAT_WS('firstname', 'lastname')"; $customerTableName = 'customer_entity'; $customerId = ['customer_id' => ['test_id']]; - $customersData = [['item_1']]; + $customersData = [['entity_id' => 'test_id', 'name' => 'item_1']]; $itemData = ['test']; $this->selectMock->expects($this->any()) @@ -118,7 +118,7 @@ public function testResolveCustomerNames() ->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 +158,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') From 54b1b73cf7ab3542aba4d10c27772519f5273d26 Mon Sep 17 00:00:00 2001 From: Kateryna Muntianu Date: Mon, 25 Apr 2016 14:13:13 +0300 Subject: [PATCH 38/43] MAGETWO-51458: [FT] Autotests cannot set category on product page when run on env with sample data --- .../Mtf/Client/Element/SuggestElement.php | 20 ++++++------------- 1 file changed, 6 insertions(+), 14 deletions(-) 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); From faf84f1cee5af11b6a86cb787bb52616e096a4a1 Mon Sep 17 00:00:00 2001 From: Roman Ganin Date: Mon, 25 Apr 2016 14:47:37 +0300 Subject: [PATCH 39/43] MAGETWO-48527: [GITHUB] Wrong customer id in Abandoned Carts grid #3162 --- .../Test/Unit/Model/ResourceModel/Quote/CollectionTest.php | 1 - 1 file changed, 1 deletion(-) 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 3b0cbd5c8a6c0..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 @@ -111,7 +111,6 @@ public function testResolveCustomerNames() $customerTableName = 'customer_entity'; $customerId = ['customer_id' => ['test_id']]; $customersData = [['entity_id' => 'test_id', 'name' => 'item_1']]; - $itemData = ['test']; $this->selectMock->expects($this->any()) ->method('getConnection') From 518acaf67e8e2dd1adb7f1c643fcf8f548762078 Mon Sep 17 00:00:00 2001 From: Roman Ganin Date: Mon, 25 Apr 2016 19:36:24 +0300 Subject: [PATCH 40/43] MAGETWO-48511: [GitHub] HTML tags inside the Meta Description on Edit Product Admin page brake the Storefront PDP layout #1514 #2613 #3090 #3244 #3255 #3813 #4031 #4073 --- .../frontend/templates/product/view/opengraph/general.phtml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 fd66871b28ab8..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 @@ -11,9 +11,9 @@ - + - + getProduct()->getFinalPrice()):?> getChildHtml('meta.currency'); ?> From 17389d151343ae9021dd74fe9994a274cf2139a4 Mon Sep 17 00:00:00 2001 From: Maksym Aposov Date: Tue, 26 Apr 2016 12:17:20 +0300 Subject: [PATCH 41/43] MAGETWO-51116: There is no ability to add product with file custom option to shopping cart as guest user using API --- .../testsuite/Magento/Test/Legacy/_files/obsolete_classes.php | 2 ++ 1 file changed, 2 insertions(+) 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'], ]; From 268992a998210b480ddbbed1709702515767fd72 Mon Sep 17 00:00:00 2001 From: "Yushkin, Dmytro" Date: Tue, 26 Apr 2016 13:45:50 +0300 Subject: [PATCH 42/43] MAGETWO-50198: [GITHUB] Options for Configurable product are merged in one product if Reorder #3654 - Added annotation --- app/code/Magento/Checkout/Model/Cart.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/code/Magento/Checkout/Model/Cart.php b/app/code/Magento/Checkout/Model/Cart.php index bc61352984659..4ce23c9c7f709 100644 --- a/app/code/Magento/Checkout/Model/Cart.php +++ b/app/code/Magento/Checkout/Model/Cart.php @@ -257,6 +257,10 @@ public function addOrderItem($orderItem, $qtyFlag = null) if ($orderItem->getParentItem() === null) { $storeId = $this->_storeManager->getStore()->getId(); try { + /** + * 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; From 6d139734b44d231b381162f9a6942326765a52e1 Mon Sep 17 00:00:00 2001 From: Dmytro Kvashnin Date: Tue, 26 Apr 2016 14:14:21 +0300 Subject: [PATCH 43/43] MAGETWO-52226: Remove conditional serialization of AbstractResource::serializableFields - reverted not supported test case --- .../Model/Test/Unit/ResourceModel/AbstractResourceTest.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/internal/Magento/Framework/Model/Test/Unit/ResourceModel/AbstractResourceTest.php b/lib/internal/Magento/Framework/Model/Test/Unit/ResourceModel/AbstractResourceTest.php index 7fc749948b3b3..6508f3d8122d3 100644 --- a/lib/internal/Magento/Framework/Model/Test/Unit/ResourceModel/AbstractResourceTest.php +++ b/lib/internal/Magento/Framework/Model/Test/Unit/ResourceModel/AbstractResourceTest.php @@ -88,8 +88,7 @@ public function unserializableFieldsDataProvider() 'serialized_object' => serialize('O:8:"stdClass":0:{}'), 'empty_value_with_default' => serialize(''), 'not_serialized_string' => 'i am string', - 'serialized_boolean_false' => serialize(false), - 'olol' => 'a:1:{s:22:"additional_information";O:8:"stdClaes":0:{}}' + 'serialized_boolean_false' => serialize(false) ] ); @@ -103,8 +102,7 @@ public function unserializableFieldsDataProvider() [[$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], - [[$dataObject, 'olol', null], false], + [[$dataObject, 'serialized_boolean_false', null], false] ]; } }