diff --git a/app/code/Magento/Backup/Model/ResourceModel/Db.php b/app/code/Magento/Backup/Model/ResourceModel/Db.php
index c38a7b3005e2..cf39406d54ae 100644
--- a/app/code/Magento/Backup/Model/ResourceModel/Db.php
+++ b/app/code/Magento/Backup/Model/ResourceModel/Db.php
@@ -301,7 +301,7 @@ public function rollBackTransaction()
*/
public function runCommand($command)
{
- $this->connection->query($command);
+ $this->connection->multiQuery($command);
return $this;
}
}
diff --git a/app/code/Magento/Bundle/Test/Mftf/Section/AdminProductFormBundleSection.xml b/app/code/Magento/Bundle/Test/Mftf/Section/AdminProductFormBundleSection.xml
index 8b78ac7b5fe6..295243f8a81d 100644
--- a/app/code/Magento/Bundle/Test/Mftf/Section/AdminProductFormBundleSection.xml
+++ b/app/code/Magento/Bundle/Test/Mftf/Section/AdminProductFormBundleSection.xml
@@ -125,5 +125,7 @@
+
+
diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/AdminAddDecimalDefaultToBundleItemsTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/AdminAddDecimalDefaultToBundleItemsTest.xml
new file mode 100644
index 000000000000..25c94f015a10
--- /dev/null
+++ b/app/code/Magento/Bundle/Test/Mftf/Test/AdminAddDecimalDefaultToBundleItemsTest.xml
@@ -0,0 +1,102 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+ $grabbedFirstBundleOptionQuantity
+
+
+
+ 1
+ $grabbedSecondBundleOptionQuantity
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Bundle/Test/Unit/Ui/DataProvider/Product/BundleDataProviderTest.php b/app/code/Magento/Bundle/Test/Unit/Ui/DataProvider/Product/BundleDataProviderTest.php
index 9eb0e7aa8946..2cf0c201f120 100644
--- a/app/code/Magento/Bundle/Test/Unit/Ui/DataProvider/Product/BundleDataProviderTest.php
+++ b/app/code/Magento/Bundle/Test/Unit/Ui/DataProvider/Product/BundleDataProviderTest.php
@@ -14,12 +14,13 @@
use Magento\Framework\App\RequestInterface;
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
use Magento\Store\Model\Store;
+use Magento\Ui\DataProvider\Modifier\PoolInterface;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
class BundleDataProviderTest extends TestCase
{
- const ALLOWED_TYPE = 'simple';
+ private const ALLOWED_TYPE = 'simple';
/**
* @var ObjectManager
@@ -46,6 +47,11 @@ class BundleDataProviderTest extends TestCase
*/
protected $dataHelperMock;
+ /**
+ * @var PoolInterface|MockObject
+ */
+ private $modifierPool;
+
/**
* @return void
*/
@@ -53,6 +59,9 @@ protected function setUp(): void
{
$this->objectManager = new ObjectManager($this);
+ $this->modifierPool = $this->getMockBuilder(PoolInterface::class)
+ ->getMockForAbstractClass();
+
$this->requestMock = $this->getMockBuilder(RequestInterface::class)
->getMockForAbstractClass();
$this->collectionMock = $this->getMockBuilder(Collection::class)
@@ -97,6 +106,7 @@ protected function getModel()
'addFilterStrategies' => [],
'meta' => [],
'data' => [],
+ 'modifiersPool' => $this->modifierPool,
]);
}
@@ -128,6 +138,9 @@ public function testGetData()
$this->collectionMock->expects($this->once())
->method('getSize')
->willReturn(count($items));
+ $this->modifierPool->expects($this->once())
+ ->method('getModifiersInstances')
+ ->willReturn([]);
$this->assertEquals($expectedData, $this->getModel()->getData());
}
diff --git a/app/code/Magento/Bundle/Ui/DataProvider/Product/BundleDataProvider.php b/app/code/Magento/Bundle/Ui/DataProvider/Product/BundleDataProvider.php
index 5f1ffc3c2682..827082dc7744 100644
--- a/app/code/Magento/Bundle/Ui/DataProvider/Product/BundleDataProvider.php
+++ b/app/code/Magento/Bundle/Ui/DataProvider/Product/BundleDataProvider.php
@@ -8,6 +8,9 @@
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;
use Magento\Catalog\Ui\DataProvider\Product\ProductDataProvider;
use Magento\Bundle\Helper\Data;
+use Magento\Framework\App\ObjectManager;
+use Magento\Ui\DataProvider\Modifier\ModifierInterface;
+use Magento\Ui\DataProvider\Modifier\PoolInterface;
class BundleDataProvider extends ProductDataProvider
{
@@ -16,6 +19,11 @@ class BundleDataProvider extends ProductDataProvider
*/
protected $dataHelper;
+ /**
+ * @var PoolInterface
+ */
+ private $modifiersPool;
+
/**
* Construct
*
@@ -24,10 +32,12 @@ class BundleDataProvider extends ProductDataProvider
* @param string $requestFieldName
* @param CollectionFactory $collectionFactory
* @param Data $dataHelper
- * @param \Magento\Ui\DataProvider\AddFieldToCollectionInterface[] $addFieldStrategies
- * @param \Magento\Ui\DataProvider\AddFilterToCollectionInterface[] $addFilterStrategies
* @param array $meta
* @param array $data
+ * @param \Magento\Ui\DataProvider\AddFieldToCollectionInterface[] $addFieldStrategies
+ * @param \Magento\Ui\DataProvider\AddFilterToCollectionInterface[] $addFilterStrategies
+ * @param PoolInterface|null $modifiersPool
+ * @SuppressWarnings(PHPMD.ExcessiveParameterList)
*/
public function __construct(
$name,
@@ -38,7 +48,8 @@ public function __construct(
array $meta = [],
array $data = [],
array $addFieldStrategies = [],
- array $addFilterStrategies = []
+ array $addFilterStrategies = [],
+ PoolInterface $modifiersPool = null
) {
parent::__construct(
$name,
@@ -52,6 +63,7 @@ public function __construct(
);
$this->dataHelper = $dataHelper;
+ $this->modifiersPool = $modifiersPool ?: ObjectManager::getInstance()->get(PoolInterface::class);
}
/**
@@ -72,11 +84,34 @@ public function getData()
);
$this->getCollection()->load();
}
+
$items = $this->getCollection()->toArray();
- return [
+ $data = [
'totalRecords' => $this->getCollection()->getSize(),
'items' => array_values($items),
];
+
+ /** @var ModifierInterface $modifier */
+ foreach ($this->modifiersPool->getModifiersInstances() as $modifier) {
+ $data = $modifier->modifyData($data);
+ }
+
+ return $data;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getMeta()
+ {
+ $meta = parent::getMeta();
+
+ /** @var ModifierInterface $modifier */
+ foreach ($this->modifiersPool->getModifiersInstances() as $modifier) {
+ $meta = $modifier->modifyMeta($meta);
+ }
+
+ return $meta;
}
}
diff --git a/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/AddSelectionQtyTypeToProductsData.php b/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/AddSelectionQtyTypeToProductsData.php
new file mode 100644
index 000000000000..a2170aa30f8d
--- /dev/null
+++ b/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/AddSelectionQtyTypeToProductsData.php
@@ -0,0 +1,76 @@
+stockRegistryPreloader = $stockRegistryPreloader;
+ }
+
+ /**
+ * Modify Meta
+ *
+ * @param array $meta
+ * @return array
+ */
+ public function modifyMeta(array $meta)
+ {
+ return $meta;
+ }
+
+ /**
+ * Modify Data - checks if new selection can have decimal quantity
+ *
+ * @param array $data
+ * @return array
+ * @throws NoSuchEntityException
+ */
+ public function modifyData(array $data): array
+ {
+ $productIds = array_column($data['items'], 'entity_id');
+
+ $stockItems = [];
+ if ($productIds) {
+ $stockItems = $this->stockRegistryPreloader->preloadStockItems($productIds);
+ }
+
+ $isQtyDecimals = [];
+ foreach ($stockItems as $stockItem) {
+ $isQtyDecimals[$stockItem->getProductId()] = $stockItem->getIsQtyDecimal();
+ }
+
+ foreach ($data['items'] as &$item) {
+ if (isset($isQtyDecimals[$item['entity_id']])) {
+ $item['selection_qty_is_integer'] = !$isQtyDecimals[$item['entity_id']];
+ }
+ }
+
+ return $data;
+ }
+}
diff --git a/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/BundlePanel.php b/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/BundlePanel.php
index 4e2f17fa46d4..7b1c254eae6f 100644
--- a/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/BundlePanel.php
+++ b/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/BundlePanel.php
@@ -403,6 +403,7 @@ protected function getBundleOptions()
'selection_price_type' => '',
'selection_price_value' => '',
'selection_qty' => '',
+ 'selection_qty_is_integer'=> 'selection_qty_is_integer',
],
'links' => [
'insertData' => '${ $.provider }:${ $.dataProvider }',
diff --git a/app/code/Magento/Bundle/etc/adminhtml/di.xml b/app/code/Magento/Bundle/etc/adminhtml/di.xml
index f173bb26fcc3..4f3069dee65b 100644
--- a/app/code/Magento/Bundle/etc/adminhtml/di.xml
+++ b/app/code/Magento/Bundle/etc/adminhtml/di.xml
@@ -76,4 +76,21 @@
+
+
+
+ -
+
- Magento\Bundle\Ui\DataProvider\Product\Form\Modifier\AddSelectionQtyTypeToProductsData
+ - 200
+
+
+
+
+
+
+
+ Magento\Bundle\Ui\DataProvider\Product\Form\Modifier\ModifiersPool
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AddNewProductAttributeInProductPageTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AddNewProductAttributeInProductPageTest.xml
index 1aaa26d893fc..cffeb9006d44 100755
--- a/app/code/Magento/Catalog/Test/Mftf/Test/AddNewProductAttributeInProductPageTest.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Test/AddNewProductAttributeInProductPageTest.xml
@@ -21,6 +21,7 @@
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceInStockWithCustomOptionsVisibleInSearchOnlyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceInStockWithCustomOptionsVisibleInSearchOnlyTest.xml
index 0aa6f8827e40..7c066343ee7f 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceInStockWithCustomOptionsVisibleInSearchOnlyTest.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceInStockWithCustomOptionsVisibleInSearchOnlyTest.xml
@@ -29,6 +29,9 @@
+
+
+
diff --git a/app/code/Magento/CatalogInventory/Model/Quote/Item/QuantityValidator/Initializer/StockItem.php b/app/code/Magento/CatalogInventory/Model/Quote/Item/QuantityValidator/Initializer/StockItem.php
index f104552b4e0f..ea4c35de053b 100644
--- a/app/code/Magento/CatalogInventory/Model/Quote/Item/QuantityValidator/Initializer/StockItem.php
+++ b/app/code/Magento/CatalogInventory/Model/Quote/Item/QuantityValidator/Initializer/StockItem.php
@@ -35,6 +35,8 @@ class StockItem
/**
* @var StockStateProviderInterface
+ * @deprecated
+ * @see was overriding ItemBackorders value with the Default Scope value; caused discrepancy in multistock config
*/
private $stockStateProvider;
@@ -122,11 +124,6 @@ public function initialize(
$quoteItem->setHasError(true);
}
- /* We need to ensure that any possible plugin will not erase the data */
- $backOrdersQty = $this->stockStateProvider->checkQuoteItemQty($stockItem, $rowQty, $qtyForCheck, $qty)
- ->getItemBackorders();
- $result->setItemBackorders($backOrdersQty);
-
if ($stockItem->hasIsChildItem()) {
$stockItem->unsIsChildItem();
}
diff --git a/app/code/Magento/CatalogInventory/Test/Unit/Model/Quote/Item/QuantityValidator/Initializer/StockItemTest.php b/app/code/Magento/CatalogInventory/Test/Unit/Model/Quote/Item/QuantityValidator/Initializer/StockItemTest.php
index 24f46c2414f3..9591b84b4c8d 100644
--- a/app/code/Magento/CatalogInventory/Test/Unit/Model/Quote/Item/QuantityValidator/Initializer/StockItemTest.php
+++ b/app/code/Magento/CatalogInventory/Test/Unit/Model/Quote/Item/QuantityValidator/Initializer/StockItemTest.php
@@ -173,10 +173,7 @@ public function testInitializeWithSubitem()
->method('checkQuoteItemQty')
->withAnyParameters()
->willReturn($result);
- $this->stockStateProviderMock->expects($this->once())
- ->method('checkQuoteItemQty')
- ->withAnyParameters()
- ->willReturn($result);
+ $this->stockStateProviderMock->expects($this->never())->method('checkQuoteItemQty');
$product->expects($this->once())
->method('getCustomOption')
->with('product_type')
@@ -213,7 +210,7 @@ public function testInitializeWithSubitem()
$quoteItem->expects($this->once())->method('setUseOldQty')->with('item')->willReturnSelf();
$result->expects($this->exactly(2))->method('getMessage')->willReturn('message');
$quoteItem->expects($this->once())->method('setMessage')->with('message')->willReturnSelf();
- $result->expects($this->exactly(3))->method('getItemBackorders')->willReturn('backorders');
+ $result->expects($this->exactly(2))->method('getItemBackorders')->willReturn('backorders');
$quoteItem->expects($this->once())->method('setBackorders')->with('backorders')->willReturnSelf();
$quoteItem->expects($this->once())->method('setStockStateResult')->with($result)->willReturnSelf();
@@ -276,10 +273,7 @@ public function testInitializeWithoutSubitem()
->method('checkQuoteItemQty')
->withAnyParameters()
->willReturn($result);
- $this->stockStateProviderMock->expects($this->once())
- ->method('checkQuoteItemQty')
- ->withAnyParameters()
- ->willReturn($result);
+ $this->stockStateProviderMock->expects($this->never())->method('checkQuoteItemQty');
$product->expects($this->once())
->method('getCustomOption')
->with('product_type')
@@ -299,7 +293,7 @@ public function testInitializeWithoutSubitem()
$result->expects($this->once())->method('getHasQtyOptionUpdate')->willReturn(false);
$result->expects($this->once())->method('getItemUseOldQty')->willReturn(null);
$result->expects($this->once())->method('getMessage')->willReturn(null);
- $result->expects($this->exactly(2))->method('getItemBackorders')->willReturn(null);
+ $result->expects($this->exactly(1))->method('getItemBackorders')->willReturn(null);
$this->model->initialize($stockItem, $quoteItem, $qty);
}
diff --git a/app/code/Magento/CatalogSearch/etc/search_request.xml b/app/code/Magento/CatalogSearch/etc/search_request.xml
index 376e4ced4d5a..9a84bf4c458d 100644
--- a/app/code/Magento/CatalogSearch/etc/search_request.xml
+++ b/app/code/Magento/CatalogSearch/etc/search_request.xml
@@ -67,7 +67,7 @@
-
+
diff --git a/app/code/Magento/Customer/Model/Metadata/Form/File.php b/app/code/Magento/Customer/Model/Metadata/Form/File.php
index 54b8b75c9ca3..05788dcaf763 100644
--- a/app/code/Magento/Customer/Model/Metadata/Form/File.php
+++ b/app/code/Magento/Customer/Model/Metadata/Form/File.php
@@ -23,6 +23,8 @@
*/
class File extends AbstractData
{
+ public const UPLOADED_FILE_SUFFIX = '_uploaded';
+
/**
* Validator for check not protected extensions
*
@@ -59,7 +61,8 @@ class File extends AbstractData
/**
* @var FileProcessorFactory
- * @deprecated 101.0.0
+ * @deprecated 101.0.0 Call fileProcessor directly from code
+ * @see $this->fileProcessor
*/
protected $fileProcessorFactory;
@@ -126,7 +129,7 @@ public function extractValue(\Magento\Framework\App\RequestInterface $request)
$attrCode = $this->getAttribute()->getAttributeCode();
// phpcs:disable Magento2.Security.Superglobal
- $uploadedFile = $request->getParam($attrCode . '_uploaded');
+ $uploadedFile = $request->getParam($attrCode . static::UPLOADED_FILE_SUFFIX);
if ($uploadedFile) {
$value = $uploadedFile;
} elseif ($this->_requestScope || !isset($_FILES[$attrCode])) {
@@ -424,7 +427,8 @@ public function outputValue($format = \Magento\Customer\Model\Metadata\ElementFa
* Get file processor
*
* @return FileProcessor
- * @deprecated 100.1.3
+ * @deprecated 100.1.3 we don’t use such approach anymore. Call fileProcessor directly
+ * @see $this->fileProcessor
*/
protected function getFileProcessor()
{
diff --git a/app/code/Magento/Downloadable/Test/Unit/Ui/DataProvider/Product/Form/Modifier/Data/LinksTest.php b/app/code/Magento/Downloadable/Test/Unit/Ui/DataProvider/Product/Form/Modifier/Data/LinksTest.php
index 8ded865057dc..10e7ddbb86c2 100644
--- a/app/code/Magento/Downloadable/Test/Unit/Ui/DataProvider/Product/Form/Modifier/Data/LinksTest.php
+++ b/app/code/Magento/Downloadable/Test/Unit/Ui/DataProvider/Product/Form/Modifier/Data/LinksTest.php
@@ -9,11 +9,14 @@
use Magento\Catalog\Api\Data\ProductInterface;
use Magento\Catalog\Model\Locator\LocatorInterface;
+use Magento\Catalog\Model\Product\Type as ProductType;
+use Magento\Downloadable\Api\Data\LinkInterface;
use Magento\Downloadable\Helper\File as DownloadableFile;
use Magento\Downloadable\Model\Link as LinkModel;
use Magento\Downloadable\Model\Product\Type;
use Magento\Downloadable\Ui\DataProvider\Product\Form\Modifier\Data\Links;
use Magento\Framework\App\Config\ScopeConfigInterface;
+use Magento\Framework\DataObject;
use Magento\Framework\Escaper;
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper;
use Magento\Framework\UrlInterface;
@@ -78,11 +81,14 @@ protected function setUp(): void
{
$this->objectManagerHelper = new ObjectManagerHelper($this);
$this->productMock = $this->getMockBuilder(ProductInterface::class)
- ->setMethods(['getLinksTitle', 'getId', 'getTypeId'])
+ ->onlyMethods(['getId', 'getTypeId'])
+ ->addMethods(['getLinksTitle', 'getTypeInstance', 'getStoreId'])
->getMockForAbstractClass();
$this->locatorMock = $this->getMockForAbstractClass(LocatorInterface::class);
$this->scopeConfigMock = $this->getMockForAbstractClass(ScopeConfigInterface::class);
- $this->escaperMock = $this->createMock(Escaper::class);
+ $this->escaperMock = $this->getMockBuilder(Escaper::class)
+ ->onlyMethods(['escapeHtml'])
+ ->getMockForAbstractClass();
$this->downloadableFileMock = $this->createMock(DownloadableFile::class);
$this->urlBuilderMock = $this->getMockForAbstractClass(UrlInterface::class);
$this->linkModelMock = $this->createMock(LinkModel::class);
@@ -100,6 +106,8 @@ protected function setUp(): void
}
/**
+ * Test case for getLinksTitle
+ *
* @param int|null $id
* @param string $typeId
* @param InvokedCount $expectedGetTitle
@@ -161,4 +169,183 @@ public function getLinksTitleDataProvider()
],
];
}
+
+ /**
+ * Test case for getLinksData
+ *
+ * @param $productTypeMock
+ * @param string $typeId
+ * @param int $storeId
+ * @param array $links
+ * @param array $expectedLinksData
+ * @return void
+ * @dataProvider getLinksDataProvider
+ */
+ public function testGetLinksData(
+ $productTypeMock,
+ string $typeId,
+ int $storeId,
+ array $links,
+ array $expectedLinksData
+ ): void {
+ $this->locatorMock->expects($this->any())
+ ->method('getProduct')
+ ->willReturn($this->productMock);
+ if (!empty($expectedLinksData)) {
+ $this->escaperMock->expects($this->any())
+ ->method('escapeHtml')
+ ->willReturn($expectedLinksData['title']);
+ }
+ $this->productMock->expects($this->any())
+ ->method('getTypeId')
+ ->willReturn($typeId);
+ $this->productMock->expects($this->any())
+ ->method('getTypeInstance')
+ ->willReturn($productTypeMock);
+ $this->productMock->expects($this->any())
+ ->method('getStoreId')
+ ->willReturn($storeId);
+ $productTypeMock->expects($this->any())
+ ->method('getLinks')
+ ->willReturn($links);
+ $getLinksData = $this->links->getLinksData();
+ if (!empty($getLinksData)) {
+ $actualResult = current($getLinksData);
+ } else {
+ $actualResult = $getLinksData;
+ }
+ $this->assertEquals($expectedLinksData, $actualResult);
+ }
+
+ /**
+ * Get Links data provider
+ *
+ * @return array
+ */
+ public function getLinksDataProvider()
+ {
+ $productData1 = [
+ 'link_id' => '1',
+ 'title' => 'test',
+ 'price' => '0.00',
+ 'number_of_downloads' => '0',
+ 'is_shareable' => '1',
+ 'link_url' => 'http://cdn.sourcebooks.com/test',
+ 'type' => 'url',
+ 'sample' =>
+ [
+ 'url' => null,
+ 'type' => null,
+ ],
+ 'sort_order' => '1',
+ 'is_unlimited' => '1',
+ 'use_default_price' => '0',
+ 'use_default_title' => '0',
+
+ ];
+ $productData2 = $productData1;
+ unset($productData2['use_default_price']);
+ unset($productData2['use_default_title']);
+ $productData3 = [
+ 'link_id' => '1',
+ 'title' => 'simple',
+ 'price' => '10.00',
+ 'number_of_downloads' => '0',
+ 'is_shareable' => '0',
+ 'link_url' => '',
+ 'type' => 'simple',
+ 'sample' =>
+ [
+ 'url' => null,
+ 'type' => null,
+ ],
+ 'sort_order' => '1',
+ 'is_unlimited' => '1',
+ 'use_default_price' => '0',
+ 'use_default_title' => '0',
+
+ ];
+ $linkMock1 = $this->getLinkMockObject($productData1, '1', '1');
+ $linkMock2 = $this->getLinkMockObject($productData1, '0', '0');
+ $linkMock3 = $this->getLinkMockObject($productData3, '0', '0');
+ return [
+ 'test case for downloadable product for default store' => [
+ 'type' => $this->createMock(Type::class),
+ 'type_id' => Type::TYPE_DOWNLOADABLE,
+ 'store_id' => 1,
+ 'links' => [$linkMock1],
+ 'expectedLinksData' => $productData1
+ ],
+ 'test case for downloadable product for all store' => [
+ 'type' => $this->createMock(Type::class),
+ 'type_id' => Type::TYPE_DOWNLOADABLE,
+ 'store_id' => 0,
+ 'links' => [$linkMock2],
+ 'expectedLinksData' => $productData2
+ ],
+ 'test case for simple product for default store' => [
+ 'type' => $this->createMock(Type::class),
+ 'type_id' => ProductType::TYPE_SIMPLE,
+ 'store_id' => 1,
+ 'links' => [$linkMock3],
+ 'expectedLinksData' => []
+ ],
+ ];
+ }
+
+ /**
+ * Data provider for getLinks
+ *
+ * @param array $productData
+ * @param string $useDefaultPrice
+ * @param string $useDefaultTitle
+ * @return MockObject
+ */
+ private function getLinkMockObject(
+ array $productData,
+ string $useDefaultPrice,
+ string $useDefaultTitle
+ ): MockObject {
+ $linkMock = $this->getMockBuilder(LinkInterface::class)
+ ->onlyMethods(['getId'])
+ ->addMethods(['getWebsitePrice', 'getStoreTitle'])
+ ->getMockForAbstractClass();
+ $linkMock->expects($this->any())
+ ->method('getId')
+ ->willReturn($productData['link_id']);
+ $linkMock->expects($this->any())
+ ->method('getTitle')
+ ->willReturn($productData['title']);
+ $linkMock->expects($this->any())
+ ->method('getPrice')
+ ->willReturn($productData['price']);
+ $linkMock->expects($this->any())
+ ->method('getNumberOfDownloads')
+ ->willReturn($productData['number_of_downloads']);
+ $linkMock->expects($this->any())
+ ->method('getIsShareable')
+ ->willReturn($productData['is_shareable']);
+ $linkMock->expects($this->any())
+ ->method('getLinkUrl')
+ ->willReturn($productData['link_url']);
+ $linkMock->expects($this->any())
+ ->method('getLinkType')
+ ->willReturn($productData['type']);
+ $linkMock->expects($this->any())
+ ->method('getSampleUrl')
+ ->willReturn($productData['sample']['url']);
+ $linkMock->expects($this->any())
+ ->method('getSampleType')
+ ->willReturn($productData['sample']['type']);
+ $linkMock->expects($this->any())
+ ->method('getSortOrder')
+ ->willReturn($productData['sort_order']);
+ $linkMock->expects($this->any())
+ ->method('getWebsitePrice')
+ ->willReturn($useDefaultPrice);
+ $linkMock->expects($this->any())
+ ->method('getStoreTitle')
+ ->willReturn($useDefaultTitle);
+ return $linkMock;
+ }
}
diff --git a/app/code/Magento/Downloadable/Ui/DataProvider/Product/Form/Modifier/Data/Links.php b/app/code/Magento/Downloadable/Ui/DataProvider/Product/Form/Modifier/Data/Links.php
index 3be1094f7a4b..7c3c30482fd8 100644
--- a/app/code/Magento/Downloadable/Ui/DataProvider/Product/Form/Modifier/Data/Links.php
+++ b/app/code/Magento/Downloadable/Ui/DataProvider/Product/Form/Modifier/Data/Links.php
@@ -120,7 +120,7 @@ public function getLinksData()
$linkData = [];
$linkData['link_id'] = $link->getId();
$linkData['title'] = $this->escaper->escapeHtml($link->getTitle());
- $linkData['price'] = $this->getPriceValue($link->getPrice());
+ $linkData['price'] = $this->getPriceValue((float) $link->getPrice());
$linkData['number_of_downloads'] = $link->getNumberOfDownloads();
$linkData['is_shareable'] = $link->getIsShareable();
$linkData['link_url'] = $link->getLinkUrl();
diff --git a/app/code/Magento/Elasticsearch/Model/Adapter/BatchDataMapper/ProductDataMapper.php b/app/code/Magento/Elasticsearch/Model/Adapter/BatchDataMapper/ProductDataMapper.php
index a9fb67f209aa..c1772086d7ba 100644
--- a/app/code/Magento/Elasticsearch/Model/Adapter/BatchDataMapper/ProductDataMapper.php
+++ b/app/code/Magento/Elasticsearch/Model/Adapter/BatchDataMapper/ProductDataMapper.php
@@ -250,6 +250,7 @@ private function convertAttribute(Attribute $attribute, array $attributeValues,
* - "Visible in Advanced Search" (is_visible_in_advanced_search)
* - "Use in Layered Navigation" (is_filterable)
* - "Use in Search Results Layered Navigation" (is_filterable_in_search)
+ * - "Use in Sorting in Product Listing" (used_for_sort_by)
*
* @param Attribute $attribute
* @return bool
@@ -261,6 +262,7 @@ private function isAttributeLabelsShouldBeMapped(Attribute $attribute): bool
|| $attribute->getIsVisibleInAdvancedSearch()
|| $attribute->getIsFilterable()
|| $attribute->getIsFilterableInSearch()
+ || $attribute->getUsedForSortBy()
);
}
diff --git a/app/code/Magento/Elasticsearch/Test/Unit/Model/Adapter/BatchDataMapper/ProductDataMapperTest.php b/app/code/Magento/Elasticsearch/Test/Unit/Model/Adapter/BatchDataMapper/ProductDataMapperTest.php
index 9f1b59b1bfc8..354ad01f14a6 100644
--- a/app/code/Magento/Elasticsearch/Test/Unit/Model/Adapter/BatchDataMapper/ProductDataMapperTest.php
+++ b/app/code/Magento/Elasticsearch/Test/Unit/Model/Adapter/BatchDataMapper/ProductDataMapperTest.php
@@ -373,6 +373,57 @@ public static function mapProvider(): array
[10 => '44', 11 => '45'],
['color' => [44, 45], 'color_value' => ['red', 'black']],
],
+ 'select with options with sort by and filterable' => [
+ 10,
+ [
+ 'attribute_code' => 'color',
+ 'backend_type' => 'text',
+ 'frontend_input' => 'select',
+ 'is_searchable' => true,
+ 'used_for_sort_by' => true,
+ 'is_filterable_in_grid' => true,
+ 'options' => [
+ ['value' => '44', 'label' => 'red'],
+ ['value' => '45', 'label' => 'black'],
+ ],
+ ],
+ [10 => '44', 11 => '45'],
+ ['color' => [44, 45], 'color_value' => ['red', 'black']],
+ ],
+ 'unsearchable select with options with sort by and filterable' => [
+ 10,
+ [
+ 'attribute_code' => 'color',
+ 'backend_type' => 'text',
+ 'frontend_input' => 'select',
+ 'is_searchable' => false,
+ 'used_for_sort_by' => false,
+ 'is_filterable_in_grid' => false,
+ 'options' => [
+ ['value' => '44', 'label' => 'red'],
+ ['value' => '45', 'label' => 'black'],
+ ],
+ ],
+ '44',
+ ['color' => 44],
+ ],
+ 'select with options with sort by only' => [
+ 10,
+ [
+ 'attribute_code' => 'color',
+ 'backend_type' => 'text',
+ 'frontend_input' => 'select',
+ 'is_searchable' => false,
+ 'used_for_sort_by' => true,
+ 'is_filterable_in_grid' => false,
+ 'options' => [
+ ['value' => '44', 'label' => 'red'],
+ ['value' => '45', 'label' => 'black'],
+ ],
+ ],
+ [10 => '44', 11 => '45'],
+ ['color' => [44, 45], 'color_value' => ['red', 'black']],
+ ],
'multiselect without options' => [
10,
[
diff --git a/app/code/Magento/GoogleAnalytics/Block/Ga.php b/app/code/Magento/GoogleAnalytics/Block/Ga.php
index 0370174c0b7f..3be62a588efa 100644
--- a/app/code/Magento/GoogleAnalytics/Block/Ga.php
+++ b/app/code/Magento/GoogleAnalytics/Block/Ga.php
@@ -82,6 +82,7 @@ public function getPageName()
* @link https://developers.google.com/analytics/devguides/collection/analyticsjs/method-reference#set
* @link https://developers.google.com/analytics/devguides/collection/analyticsjs/method-reference#gaObjectMethods
* @deprecated 100.2.0 please use getPageTrackingData method
+ * @see getPageTrackingData method
*/
public function getPageTrackingCode($accountId)
{
@@ -103,6 +104,7 @@ public function getPageTrackingCode($accountId)
*
* @return string|void
* @deprecated 100.2.0 please use getOrdersTrackingData method
+ * @see getOrdersTrackingData method
*/
public function getOrdersTrackingCode()
{
@@ -120,17 +122,19 @@ public function getOrdersTrackingCode()
foreach ($collection as $order) {
$result[] = "ga('set', 'currencyCode', '" . $order->getOrderCurrencyCode() . "');";
foreach ($order->getAllVisibleItems() as $item) {
+ $quantity = $item->getQtyOrdered() * 1;
+ $format = fmod($quantity, 1) !== 0.00 ? '%.2f' : '%d';
$result[] = sprintf(
"ga('ec:addProduct', {
'id': '%s',
'name': '%s',
- 'price': '%s',
- 'quantity': %s
+ 'price': %.2f,
+ 'quantity': $format
});",
$this->escapeJsQuote($item->getSku()),
$this->escapeJsQuote($item->getName()),
- $item->getPrice(),
- $item->getQtyOrdered()
+ (float)$item->getPrice(),
+ $quantity
);
}
@@ -138,15 +142,15 @@ public function getOrdersTrackingCode()
"ga('ec:setAction', 'purchase', {
'id': '%s',
'affiliation': '%s',
- 'revenue': '%s',
- 'tax': '%s',
- 'shipping': '%s'
+ 'revenue': %.2f,
+ 'tax': %.2f,
+ 'shipping': %.2f
});",
$order->getIncrementId(),
$this->escapeJsQuote($this->_storeManager->getStore()->getFrontendName()),
- $order->getGrandTotal(),
- $order->getTaxAmount(),
- $order->getShippingAmount()
+ (float)$order->getGrandTotal(),
+ (float)$order->getTaxAmount(),
+ (float)$order->getShippingAmount(),
);
$result[] = "ga('send', 'pageview');";
@@ -232,19 +236,20 @@ public function getOrdersTrackingData()
foreach ($collection as $order) {
foreach ($order->getAllVisibleItems() as $item) {
+ $quantity = $item->getQtyOrdered() * 1;
$result['products'][] = [
'id' => $this->escapeJsQuote($item->getSku()),
'name' => $this->escapeJsQuote($item->getName()),
- 'price' => $item->getPrice(),
- 'quantity' => $item->getQtyOrdered(),
+ 'price' => (float)$item->getPrice(),
+ 'quantity' => $quantity,
];
}
$result['orders'][] = [
'id' => $order->getIncrementId(),
'affiliation' => $this->escapeJsQuote($this->_storeManager->getStore()->getFrontendName()),
- 'revenue' => $order->getGrandTotal(),
- 'tax' => $order->getTaxAmount(),
- 'shipping' => $order->getShippingAmount(),
+ 'revenue' => (float)$order->getGrandTotal(),
+ 'tax' => (float)$order->getTaxAmount(),
+ 'shipping' => (float)$order->getShippingAmount(),
];
$result['currency'] = $order->getOrderCurrencyCode();
}
diff --git a/app/code/Magento/GoogleAnalytics/Test/Unit/Block/GaTest.php b/app/code/Magento/GoogleAnalytics/Test/Unit/Block/GaTest.php
index a367a938d45b..8088b03707b2 100644
--- a/app/code/Magento/GoogleAnalytics/Test/Unit/Block/GaTest.php
+++ b/app/code/Magento/GoogleAnalytics/Test/Unit/Block/GaTest.php
@@ -115,15 +115,21 @@ public function testOrderTrackingCode()
ga('ec:addProduct', {
'id': 'sku0',
'name': 'testName0',
- 'price': '0.00',
+ 'price': 0.00,
'quantity': 1
});
+ ga('ec:addProduct', {
+ 'id': 'sku1',
+ 'name': 'testName1',
+ 'price': 1.00,
+ 'quantity': 1.11
+ });
ga('ec:setAction', 'purchase', {
'id': '100',
'affiliation': 'test',
- 'revenue': '10',
- 'tax': '2',
- 'shipping': '1'
+ 'revenue': 10.00,
+ 'tax': 2.00,
+ 'shipping': 2.00
});
ga('send', 'pageview');";
@@ -163,9 +169,9 @@ public function testOrderTrackingData()
[
'id' => 100,
'affiliation' => 'test',
- 'revenue' => 10,
- 'tax' => 2,
- 'shipping' => 1
+ 'revenue' => 10.00,
+ 'tax' => 2.00,
+ 'shipping' => 2.0
]
],
'products' => [
@@ -174,6 +180,12 @@ public function testOrderTrackingData()
'name' => 'testName0',
'price' => 0.00,
'quantity' => 1
+ ],
+ [
+ 'id' => 'sku1',
+ 'name' => 'testName1',
+ 'price' => 1.00,
+ 'quantity' => 1.11
]
],
'currency' => 'USD'
@@ -204,7 +216,7 @@ public function testGetPageTrackingData()
* @param int $orderItemCount
* @return Order|MockObject
*/
- protected function createOrderMock($orderItemCount = 1)
+ protected function createOrderMock($orderItemCount = 2)
{
$orderItems = [];
for ($i = 0; $i < $orderItemCount; $i++) {
@@ -213,8 +225,8 @@ protected function createOrderMock($orderItemCount = 1)
->getMockForAbstractClass();
$orderItemMock->expects($this->once())->method('getSku')->willReturn('sku' . $i);
$orderItemMock->expects($this->once())->method('getName')->willReturn('testName' . $i);
- $orderItemMock->expects($this->once())->method('getPrice')->willReturn($i . '.00');
- $orderItemMock->expects($this->once())->method('getQtyOrdered')->willReturn($i + 1);
+ $orderItemMock->expects($this->once())->method('getPrice')->willReturn((float)($i . '.0000'));
+ $orderItemMock->expects($this->once())->method('getQtyOrdered')->willReturn($i == 1 ? 1.11 : $i + 1);
$orderItems[] = $orderItemMock;
}
@@ -223,9 +235,9 @@ protected function createOrderMock($orderItemCount = 1)
->getMock();
$orderMock->expects($this->once())->method('getIncrementId')->willReturn(100);
$orderMock->expects($this->once())->method('getAllVisibleItems')->willReturn($orderItems);
- $orderMock->expects($this->once())->method('getGrandTotal')->willReturn(10);
- $orderMock->expects($this->once())->method('getTaxAmount')->willReturn(2);
- $orderMock->expects($this->once())->method('getShippingAmount')->willReturn($orderItemCount);
+ $orderMock->expects($this->once())->method('getGrandTotal')->willReturn(10.00);
+ $orderMock->expects($this->once())->method('getTaxAmount')->willReturn(2.00);
+ $orderMock->expects($this->once())->method('getShippingAmount')->willReturn(round((float)$orderItemCount, 2));
$orderMock->expects($this->once())->method('getOrderCurrencyCode')->willReturn('USD');
return $orderMock;
}
@@ -241,7 +253,7 @@ protected function createCollectionMock()
$collectionMock->expects($this->any())
->method('getIterator')
- ->willReturn(new \ArrayIterator([$this->createOrderMock(1)]));
+ ->willReturn(new \ArrayIterator([$this->createOrderMock(2)]));
return $collectionMock;
}
diff --git a/app/code/Magento/Indexer/Model/Indexer.php b/app/code/Magento/Indexer/Model/Indexer.php
index ac8b9590e58f..7be1d5a3a9e2 100644
--- a/app/code/Magento/Indexer/Model/Indexer.php
+++ b/app/code/Magento/Indexer/Model/Indexer.php
@@ -441,8 +441,10 @@ public function reindexAll()
}
try {
$this->getActionInstance()->executeFull();
- $state->setStatus(StateInterface::STATUS_VALID);
- $state->save();
+ if ($this->workingStateProvider->isWorking($this->getId())) {
+ $state->setStatus(StateInterface::STATUS_VALID);
+ $state->save();
+ }
if (!empty($sharedIndexers)) {
$this->resumeSharedViews($sharedIndexers);
}
diff --git a/app/code/Magento/Indexer/Model/Processor.php b/app/code/Magento/Indexer/Model/Processor.php
index 78b8fa070b15..7846421daa70 100644
--- a/app/code/Magento/Indexer/Model/Processor.php
+++ b/app/code/Magento/Indexer/Model/Processor.php
@@ -59,7 +59,7 @@ public function __construct(
IndexerInterfaceFactory $indexerFactory,
Indexer\CollectionFactory $indexersFactory,
ProcessorInterface $mviewProcessor,
- MakeSharedIndexValid $makeSharedValid = null
+ ?MakeSharedIndexValid $makeSharedValid = null
) {
$this->config = $config;
$this->indexerFactory = $indexerFactory;
@@ -86,9 +86,11 @@ public function reindexAllInvalid()
$sharedIndex = $indexerConfig['shared_index'] ?? null;
if (!in_array($sharedIndex, $this->sharedIndexesComplete)) {
$indexer->reindexAll();
-
- if (!empty($sharedIndex) && $this->makeSharedValid->execute($sharedIndex)) {
- $this->sharedIndexesComplete[] = $sharedIndex;
+ $indexer->load($indexer->getId());
+ if ($indexer->isValid()) {
+ if (!empty($sharedIndex) && $this->makeSharedValid->execute($sharedIndex)) {
+ $this->sharedIndexesComplete[] = $sharedIndex;
+ }
}
}
}
diff --git a/app/code/Magento/Indexer/Test/Unit/Model/IndexerTest.php b/app/code/Magento/Indexer/Test/Unit/Model/IndexerTest.php
index bcdfbea78b0b..451d4c211ead 100644
--- a/app/code/Magento/Indexer/Test/Unit/Model/IndexerTest.php
+++ b/app/code/Magento/Indexer/Test/Unit/Model/IndexerTest.php
@@ -144,7 +144,8 @@ public function testLoadWithException()
public function testGetView()
{
$indexId = 'indexer_internal_name';
- $this->viewMock->expects($this->once())->method('load')->with('view_test')->willReturnSelf();
+ $this->viewMock->expects($this->once())
+ ->method('load')->with('view_test')->willReturnSelf();
$this->loadIndexer($indexId);
$this->assertEquals($this->viewMock, $this->model->getView());
@@ -224,11 +225,14 @@ public function testReindexAll()
$indexId = 'indexer_internal_name';
$this->loadIndexer($indexId);
+ $this->workingStateProvider->method('isWorking')->willReturnOnConsecutiveCalls(false, true);
+
$stateMock = $this->createPartialMock(
State::class,
['load', 'getId', 'setIndexerId', '__wakeup', 'getStatus', 'setStatus', 'save']
);
- $stateMock->expects($this->once())->method('load')->with($indexId, 'indexer_id')->willReturnSelf();
+ $stateMock->expects($this->once())
+ ->method('load')->with($indexId, 'indexer_id')->willReturnSelf();
$stateMock->expects($this->never())->method('setIndexerId');
$stateMock->expects($this->once())->method('getId')->willReturn(1);
$stateMock->expects($this->exactly(2))->method('setStatus')->willReturnSelf();
@@ -268,7 +272,8 @@ public function testReindexAllWithException()
State::class,
['load', 'getId', 'setIndexerId', '__wakeup', 'getStatus', 'setStatus', 'save']
);
- $stateMock->expects($this->once())->method('load')->with($indexId, 'indexer_id')->willReturnSelf();
+ $stateMock->expects($this->once())
+ ->method('load')->with($indexId, 'indexer_id')->willReturnSelf();
$stateMock->expects($this->never())->method('setIndexerId');
$stateMock->expects($this->once())->method('getId')->willReturn(1);
$stateMock->expects($this->exactly(2))->method('setStatus')->willReturnSelf();
@@ -313,7 +318,8 @@ public function testReindexAllWithError()
State::class,
['load', 'getId', 'setIndexerId', '__wakeup', 'getStatus', 'setStatus', 'save']
);
- $stateMock->expects($this->once())->method('load')->with($indexId, 'indexer_id')->willReturnSelf();
+ $stateMock->expects($this->once())
+ ->method('load')->with($indexId, 'indexer_id')->willReturnSelf();
$stateMock->expects($this->never())->method('setIndexerId');
$stateMock->expects($this->once())->method('getId')->willReturn(1);
$stateMock->expects($this->exactly(2))->method('setStatus')->willReturnSelf();
@@ -483,7 +489,8 @@ public function testInvalidate()
);
$this->stateFactoryMock->expects($this->once())->method('create')->willReturn($stateMock);
- $stateMock->expects($this->once())->method('setStatus')->with(StateInterface::STATUS_INVALID)->willReturnSelf();
+ $stateMock->expects($this->once())
+ ->method('setStatus')->with(StateInterface::STATUS_INVALID)->willReturnSelf();
$stateMock->expects($this->once())->method('save')->willReturnSelf();
$this->model->invalidate();
}
diff --git a/app/code/Magento/Indexer/Test/Unit/Model/ProcessorTest.php b/app/code/Magento/Indexer/Test/Unit/Model/ProcessorTest.php
index b0a339551955..ba6216f37f7d 100644
--- a/app/code/Magento/Indexer/Test/Unit/Model/ProcessorTest.php
+++ b/app/code/Magento/Indexer/Test/Unit/Model/ProcessorTest.php
@@ -102,18 +102,14 @@ public function testReindexAllInvalid(): void
$this->configMock->expects($this->once())->method('getIndexers')->willReturn($indexers);
$state1Mock = $this->createPartialMock(State::class, ['getStatus', '__wakeup']);
- $state1Mock->expects(
- $this->once()
- )->method(
- 'getStatus'
- )->willReturn(
- StateInterface::STATUS_INVALID
- );
+ $state1Mock->expects($this->exactly(2))
+ ->method('getStatus')
+ ->willReturnOnConsecutiveCalls(StateInterface::STATUS_INVALID, StateInterface::STATUS_VALID);
$indexer1Mock = $this->createPartialMock(
Indexer::class,
['load', 'getState', 'reindexAll']
);
- $indexer1Mock->expects($this->once())->method('getState')->willReturn($state1Mock);
+ $indexer1Mock->expects($this->exactly(2))->method('getState')->willReturn($state1Mock);
$indexer1Mock->expects($this->once())->method('reindexAll');
$state2Mock = $this->createPartialMock(State::class, ['getStatus', '__wakeup']);
@@ -169,7 +165,10 @@ function ($elem) {
$stateMock = $this->createPartialMock(State::class, ['getStatus', '__wakeup']);
$stateMock->expects($this->any())
->method('getStatus')
- ->willReturn($indexerStates[$indexerData['indexer_id']]);
+ ->willReturnOnConsecutiveCalls(
+ $indexerStates[$indexerData['indexer_id']],
+ StateInterface::STATUS_VALID
+ );
$indexerMock = $this->createPartialMock(Indexer::class, ['load', 'getState', 'reindexAll']);
$indexerMock->expects($this->any())->method('getState')->willReturn($stateMock);
$indexerMock->expects($expectedReindexAllCalls[$indexerData['indexer_id']])->method('reindexAll');
diff --git a/app/code/Magento/MediaGalleryRenditions/etc/media_content.xml b/app/code/Magento/MediaGalleryRenditions/etc/media_content.xml
index 7596de07b892..05d2c3006651 100644
--- a/app/code/Magento/MediaGalleryRenditions/etc/media_content.xml
+++ b/app/code/Magento/MediaGalleryRenditions/etc/media_content.xml
@@ -9,7 +9,7 @@
/{{media url=(?:"|")(?:.renditions)?(.*?)(?:"|")}}/
- /{{media url="?(?:.*?\.renditions\/)(.*?)"?}}/
+ /{{media url="?(?:.*?\.renditions\/)?(.*?)"?}}/
/src=".*\/media\/(?:.renditions\/)*(.*?)"/
/^\/?media\/(?:.renditions\/)?(.*)/
/^\/pub\/?media\/(?:.renditions\/)?(.*)/
diff --git a/app/code/Magento/Paypal/Model/Payflow/Service/Response/Validator/CVV2Match.php b/app/code/Magento/Paypal/Model/Payflow/Service/Response/Validator/CVV2Match.php
index 705b667ab2f6..53c4a4e08318 100644
--- a/app/code/Magento/Paypal/Model/Payflow/Service/Response/Validator/CVV2Match.php
+++ b/app/code/Magento/Paypal/Model/Payflow/Service/Response/Validator/CVV2Match.php
@@ -9,41 +9,38 @@
use Magento\Paypal\Model\Payflow\Service\Response\ValidatorInterface;
use Magento\Paypal\Model\Payflow\Transparent;
-/**
- * Class CVV2Match
- */
class CVV2Match implements ValidatorInterface
{
/**
* Result of the card security code (CVV2) check
*/
- const CVV2MATCH = 'cvv2match';
+ public const CVV2MATCH = 'cvv2match';
/**
* This field returns the transaction amount, or if performing a partial authorization,
* the amount approved for the partial authorization.
*/
- const AMT = 'amt';
+ public const AMT = 'amt';
/**
* Message if validation fail
*/
- const ERROR_MESSAGE = 'Card security code does not match.';
+ public const ERROR_MESSAGE = 'Card security code does not match.';
/**#@+ Values of the response */
- const RESPONSE_YES = 'y';
+ public const RESPONSE_YES = 'y';
- const RESPONSE_NO = 'n';
+ public const RESPONSE_NO = 'n';
- const RESPONSE_NOT_SUPPORTED = 'x';
+ public const RESPONSE_NOT_SUPPORTED = 'x';
/**#@-*/
/**#@+ Validation settings payments */
- const CONFIG_ON = 1;
+ public const CONFIG_ON = 1;
- const CONFIG_OFF = 0;
+ public const CONFIG_OFF = 0;
- const CONFIG_NAME = 'avs_security_code';
+ public const CONFIG_NAME = 'avs_security_code';
/**#@-*/
/**
@@ -55,7 +52,7 @@ class CVV2Match implements ValidatorInterface
*/
public function validate(DataObject $response, Transparent $transparentModel)
{
- if ($transparentModel->getConfig()->getValue(static::CONFIG_NAME) === static::CONFIG_OFF) {
+ if ((int)$transparentModel->getConfig()->getValue(static::CONFIG_NAME) === static::CONFIG_OFF) {
return true;
}
diff --git a/app/code/Magento/Paypal/Test/Unit/Model/Payflow/Service/Response/Validator/CVV2MatchTest.php b/app/code/Magento/Paypal/Test/Unit/Model/Payflow/Service/Response/Validator/CVV2MatchTest.php
index affb335491c5..b2179fb32fe5 100644
--- a/app/code/Magento/Paypal/Test/Unit/Model/Payflow/Service/Response/Validator/CVV2MatchTest.php
+++ b/app/code/Magento/Paypal/Test/Unit/Model/Payflow/Service/Response/Validator/CVV2MatchTest.php
@@ -137,6 +137,15 @@ public function validationDataProvider()
'response' => new DataObject(),
'configValue' => '1',
],
+ [
+ 'expectedResult' => true,
+ 'response' => new DataObject(
+ [
+ 'cvv2match' => 'N',
+ ]
+ ),
+ 'configValue' => '0',
+ ],
];
}
}
diff --git a/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote/Save.php b/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote/Save.php
index a0d3977ba83d..1c49b16161a5 100644
--- a/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote/Save.php
+++ b/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote/Save.php
@@ -64,7 +64,7 @@ public function execute()
{
$data = $this->getRequest()->getPostValue();
if ($data) {
- $data['simple_free_shipping'] = ($data['simple_free_shipping'] === '')
+ $data['simple_free_shipping'] = (($data['simple_free_shipping'] ?? '') === '')
? null : $data['simple_free_shipping'];
try {
diff --git a/app/code/Magento/SalesRule/Model/ResourceModel/Rule.php b/app/code/Magento/SalesRule/Model/ResourceModel/Rule.php
index d65021ed82a2..125e2194b45e 100644
--- a/app/code/Magento/SalesRule/Model/ResourceModel/Rule.php
+++ b/app/code/Magento/SalesRule/Model/ResourceModel/Rule.php
@@ -312,6 +312,10 @@ public function getActiveAttributes()
['ea' => $this->getTable('eav_attribute')],
'ea.attribute_id = a.attribute_id',
[]
+ )->joinInner(
+ ['sr' => $this->getTable('salesrule')],
+ 'a.' . $this->getLinkField() . ' = sr.' . $this->getLinkField() . ' AND sr.is_active = 1',
+ []
);
return $connection->fetchAll($select);
}
diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/file-uploader.js b/app/code/Magento/Ui/view/base/web/js/form/element/file-uploader.js
index e7dc245d47d6..988ff2ffe76f 100644
--- a/app/code/Magento/Ui/view/base/web/js/form/element/file-uploader.js
+++ b/app/code/Magento/Ui/view/base/web/js/form/element/file-uploader.js
@@ -75,7 +75,14 @@ define([
* @returns {FileUploader} Chainable.
*/
setInitialValue: function () {
- var value = this.getInitialValue();
+ var value = this.getInitialValue(),
+ imageSize = this.setImageSize;
+
+ _.each(value, function (val) {
+ if (val.type !== undefined && val.type.indexOf('image') >= 0) {
+ imageSize(val);
+ }
+ }, this);
value = value.map(this.processFile, this);
@@ -88,6 +95,19 @@ define([
return this;
},
+ /**
+ * Set image size for already loaded image
+ *
+ * @param value
+ * @returns {Promise}
+ */
+ async setImageSize(value) {
+ let response = await fetch(value.url),
+ blob = await response.blob();
+
+ value.size = blob.size;
+ },
+
/**
* Empties files list.
*
diff --git a/app/code/Magento/UrlRewrite/Controller/Adminhtml/Url/Rewrite/Save.php b/app/code/Magento/UrlRewrite/Controller/Adminhtml/Url/Rewrite/Save.php
index c508e85d87c3..4ef7ea4b2062 100644
--- a/app/code/Magento/UrlRewrite/Controller/Adminhtml/Url/Rewrite/Save.php
+++ b/app/code/Magento/UrlRewrite/Controller/Adminhtml/Url/Rewrite/Save.php
@@ -97,17 +97,51 @@ protected function getTargetPath($model)
];
$rewrite = $this->urlFinder->findOneByData($data);
if (!$rewrite) {
- $message = $model->getEntityType() === self::ENTITY_TYPE_PRODUCT
- ? __("The selected product isn't associated with the selected store or category.")
- : __("The selected category isn't associated with the selected store.");
- throw new LocalizedException($message);
+ $model->getEntityType() === self::ENTITY_TYPE_PRODUCT ? $this->checkProductCorrelation($model) :
+ $this->checkCategoryCorrelation($model);
+ } else {
+ $targetPath = $rewrite->getRequestPath();
}
- $targetPath = $rewrite->getRequestPath();
}
return $targetPath;
}
/**
+ * Checks if rewrite details match category properties
+ *
+ * @param \Magento\UrlRewrite\Model\UrlRewrite $model
+ * @return void
+ * @throws LocalizedException
+ */
+ private function checkCategoryCorrelation(\Magento\UrlRewrite\Model\UrlRewrite $model): void
+ {
+ if (false === in_array($model->getStoreId(), $this->_getCategory()->getStoreIds())) {
+ throw new LocalizedException(
+ __("The selected category isn't associated with the selected store.")
+ );
+ }
+ }
+
+ /**
+ * Checks if rewrite details match product properties
+ *
+ * @param \Magento\UrlRewrite\Model\UrlRewrite $model
+ * @return void
+ * @throws LocalizedException
+ */
+ private function checkProductCorrelation(\Magento\UrlRewrite\Model\UrlRewrite $model): void
+ {
+ if (false === ($this->_getProduct()->canBeShowInCategory($this->_getCategory()->getId())) &&
+ in_array($model->getStoreId(), $this->_getProduct()->getStoreIds())) {
+ throw new LocalizedException(
+ __("The selected product isn't associated with the selected store or category.")
+ );
+ }
+ }
+
+ /**
+ * Get rewrite canonical target path
+ *
* @return string
*/
protected function getCanonicalTargetPath()
@@ -142,6 +176,8 @@ private function _handleCmsPageUrlRewrite($model)
}
/**
+ * Process save URL rewrite request
+ *
* @return void
*/
public function execute()
diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Page/AdminUrlRewriteProductCategoryPage.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Page/AdminUrlRewriteProductCategoryPage.xml
new file mode 100644
index 000000000000..33db1aff8f55
--- /dev/null
+++ b/app/code/Magento/UrlRewrite/Test/Mftf/Page/AdminUrlRewriteProductCategoryPage.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Section/AdminUrlRewriteIndexSection.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Section/AdminUrlRewriteIndexSection.xml
index b6a155c9db6f..03cc49f95e63 100644
--- a/app/code/Magento/UrlRewrite/Test/Mftf/Section/AdminUrlRewriteIndexSection.xml
+++ b/app/code/Magento/UrlRewrite/Test/Mftf/Section/AdminUrlRewriteIndexSection.xml
@@ -15,5 +15,6 @@
+
diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCreateProductUrlRewriteTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCreateProductUrlRewriteTest.xml
new file mode 100644
index 000000000000..eacf142f66a2
--- /dev/null
+++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCreateProductUrlRewriteTest.xml
@@ -0,0 +1,77 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/User/Test/Mftf/ActionGroup/AdminDeleteNewUserActionGroup.xml b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminDeleteNewUserActionGroup.xml
index a4e5492f8e3e..a1410213daa1 100644
--- a/app/code/Magento/User/Test/Mftf/ActionGroup/AdminDeleteNewUserActionGroup.xml
+++ b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminDeleteNewUserActionGroup.xml
@@ -16,7 +16,7 @@
-
+
diff --git a/app/code/Magento/User/Test/Mftf/Test/AdminDeleteOwnAdminUserAccountTest.xml b/app/code/Magento/User/Test/Mftf/Test/AdminDeleteOwnAdminUserAccountTest.xml
index 13f85157ead0..294a6e337f31 100644
--- a/app/code/Magento/User/Test/Mftf/Test/AdminDeleteOwnAdminUserAccountTest.xml
+++ b/app/code/Magento/User/Test/Mftf/Test/AdminDeleteOwnAdminUserAccountTest.xml
@@ -35,8 +35,9 @@
-
-
+
+
+
diff --git a/dev/tests/integration/testsuite/Magento/CatalogSearch/Controller/Advanced/ResultTest.php b/dev/tests/integration/testsuite/Magento/CatalogSearch/Controller/Advanced/ResultTest.php
index c032f47d8834..8f4b804de157 100644
--- a/dev/tests/integration/testsuite/Magento/CatalogSearch/Controller/Advanced/ResultTest.php
+++ b/dev/tests/integration/testsuite/Magento/CatalogSearch/Controller/Advanced/ResultTest.php
@@ -165,6 +165,42 @@ public function testExecuteWithArrayInParam(array $searchParams): void
);
}
+ /**
+ * Advanced search test by difference product attributes.
+ *
+ * @magentoAppArea frontend
+ * @magentoDataFixture Magento/CatalogSearch/_files/product_for_search.php
+ * @magentoDataFixture Magento/CatalogSearch/_files/full_reindex.php
+ * @dataProvider testDataForAttributesCombination
+ *
+ * @param array $searchParams
+ * @param bool $isProductShown
+ * @return void
+ */
+ public function testExecuteForAttributesCombination(array $searchParams, bool $isProductShown): void
+ {
+ $this->getRequest()->setQuery(
+ $this->_objectManager->create(
+ Parameters::class,
+ [
+ 'values' => $searchParams
+ ]
+ )
+ );
+ $this->dispatch('catalogsearch/advanced/result');
+ $responseBody = $this->getResponse()->getBody();
+
+ if ($isProductShown) {
+ $this->assertStringContainsString('Simple product name', $responseBody);
+ } else {
+ $this->assertStringContainsString(
+ 'We can't find any items matching these search criteria.',
+ $responseBody
+ );
+ }
+ $this->assertStringNotContainsString('Not visible simple product', $responseBody);
+ }
+
/**
* Data provider with array in params values
*
@@ -339,4 +375,71 @@ private function getAttributeOptionValueByOptionLabel(string $attributeCode, str
return $attribute->getSource()->getOptionId($optionLabel);
}
+
+ /**
+ * Data provider with strings for quick search.
+ *
+ * @return array
+ */
+ public function testDataForAttributesCombination(): array
+ {
+ return [
+ 'search_product_by_name_and_price' => [
+ [
+ 'name' => 'Simple product name',
+ 'sku' => '',
+ 'description' => '',
+ 'short_description' => '',
+ 'price' => [
+ 'from' => 99,
+ 'to' => 101,
+ ],
+ 'test_searchable_attribute' => '',
+ ],
+ true
+ ],
+ 'search_product_by_name_and_price_not_shown' => [
+ [
+ 'name' => 'Simple product name',
+ 'sku' => '',
+ 'description' => '',
+ 'short_description' => '',
+ 'price' => [
+ 'from' => 101,
+ 'to' => 102,
+ ],
+ 'test_searchable_attribute' => '',
+ ],
+ false
+ ],
+ 'search_product_by_sku' => [
+ [
+ 'name' => '',
+ 'sku' => 'simple_for_search',
+ 'description' => '',
+ 'short_description' => '',
+ 'price' => [
+ 'from' => 99,
+ 'to' => 101,
+ ],
+ 'test_searchable_attribute' => '',
+ ],
+ true
+ ],
+ 'search_product_by_sku_not_shown' => [
+ [
+ 'name' => '',
+ 'sku' => 'simple_for_search',
+ 'description' => '',
+ 'short_description' => '',
+ 'price' => [
+ 'from' => 990,
+ 'to' => 1010,
+ ],
+ 'test_searchable_attribute' => '',
+ ],
+ false
+ ],
+ ];
+ }
}
diff --git a/dev/tests/integration/testsuite/Magento/Framework/Backup/DbTest.php b/dev/tests/integration/testsuite/Magento/Framework/Backup/DbTest.php
index f25880e10c81..9d48de03c736 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/Backup/DbTest.php
+++ b/dev/tests/integration/testsuite/Magento/Framework/Backup/DbTest.php
@@ -7,11 +7,12 @@
namespace Magento\Framework\Backup;
use Magento\Backup\Helper\Data;
+use Magento\Backup\Model\ResourceModel\Db;
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\Filesystem;
use Magento\Framework\Module\Setup;
use Magento\TestFramework\Helper\Bootstrap;
-use PHPUnit\Framework\TestCase;
+use Magento\Framework\Backup\BackupInterface;
/**
* Provide tests for \Magento\Framework\Backup\Db.
@@ -32,16 +33,17 @@ public static function setUpBeforeClass(): void
}
/**
- * Test db backup includes triggers.
+ * Test db backup and rollback including triggers.
*
* @magentoConfigFixture default/system/backup/functionality_enabled 1
* @magentoDataFixture Magento/Framework/Backup/_files/trigger.php
* @magentoDbIsolation disabled
*/
- public function testBackupIncludesCustomTriggers()
+ public function testBackupAndRollbackIncludesCustomTriggers()
{
$helper = Bootstrap::getObjectManager()->get(Data::class);
$time = time();
+ /** BackupInterface $backupManager */
$backupManager = Bootstrap::getObjectManager()->get(Factory::class)->create(
Factory::TYPE_DB
)->setBackupExtension(
@@ -60,6 +62,12 @@ public function testBackupIncludesCustomTriggers()
'/CREATE TRIGGER `?test_custom_trigger`? AFTER INSERT ON `?'. $tableName . '`? FOR EACH ROW/',
$content
);
+
+ // Test rollback
+ $backupResourceModel = Bootstrap::getObjectManager()->get(Db::class);
+ $backupManager->setResourceModel($backupResourceModel);
+ $backupManager->rollback();
+
//Clean up.
$write->delete('/backups/' . $time . '_db_testbackup.sql');
}
diff --git a/dev/tests/integration/testsuite/Magento/MediaContent/Model/ExtractAssetsFromContentTest.php b/dev/tests/integration/testsuite/Magento/MediaContent/Model/ExtractAssetsFromContentTest.php
index e561311fc4e7..85b0b53e6426 100644
--- a/dev/tests/integration/testsuite/Magento/MediaContent/Model/ExtractAssetsFromContentTest.php
+++ b/dev/tests/integration/testsuite/Magento/MediaContent/Model/ExtractAssetsFromContentTest.php
@@ -77,6 +77,12 @@ public function contentProvider()
2020
]
],
+ 'Relevant paths in content without quotes' => [
+ 'content {{media url=testDirectory/path.jpg}} content',
+ [
+ 2020
+ ]
+ ],
'Relevant wysiwyg paths in content' => [
'content getRequest()->setMethod(Http::METHOD_POST);
+ $this->getRequest()->setPostValue($requestData);
+
+ $this->dispatch('backend/sales_rule/promo_quote/save');
+ $this->assertSessionMessages(
+ self::equalTo(['You saved the rule.']),
+ MessageInterface::TYPE_SUCCESS
+ );
+ }
+
+ public function testCreateRuleWithFreeShipping(): void
+ {
+ $ruleCollection = Bootstrap::getObjectManager()->create(Collection::class);
+ $resource = $ruleCollection->getResource();
+ $select = $resource->getConnection()->select();
+ $select->from($resource->getTable('salesrule'), [new \Zend_Db_Expr('MAX(rule_id)')]);
+ $maxId = (int)$resource->getConnection()->fetchOne($select);
+
+ $requestData = [
+ 'simple_free_shipping' => 1,
+ ];
+ $this->getRequest()->setMethod(Http::METHOD_POST);
+ $this->getRequest()->setPostValue($requestData);
+
+ $this->dispatch('backend/sales_rule/promo_quote/save');
+ $this->assertSessionMessages(
+ self::equalTo(['You saved the rule.']),
+ MessageInterface::TYPE_SUCCESS
+ );
+
+ $select = $resource->getConnection()->select();
+ $select
+ ->from($resource->getTable('salesrule'), ['simple_free_shipping'])
+ ->where('rule_id > ?', $maxId);
+ $simpleFreeShipping = (int)$resource->getConnection()->fetchOne($select);
+
+ $this->assertEquals(1, $simpleFreeShipping);
+ }
+
+ public function testCreateRuleWithWrongDates(): void
+ {
+ $requestData = [
+ 'from_date' => '2023-02-02',
+ 'to_date' => '2023-01-01',
+ ];
+ $this->getRequest()->setMethod(Http::METHOD_POST);
+ $this->getRequest()->setPostValue($requestData);
+
+ $this->dispatch('backend/sales_rule/promo_quote/save');
+ $this->assertSessionMessages(
+ self::equalTo(['End Date must follow Start Date.']),
+ MessageInterface::TYPE_ERROR
+ );
+ }
+}
diff --git a/dev/tests/integration/testsuite/Magento/SalesRule/Model/ResourceModel/RuleTest.php b/dev/tests/integration/testsuite/Magento/SalesRule/Model/ResourceModel/RuleTest.php
index ccab0fc9f154..1299c5fca09f 100644
--- a/dev/tests/integration/testsuite/Magento/SalesRule/Model/ResourceModel/RuleTest.php
+++ b/dev/tests/integration/testsuite/Magento/SalesRule/Model/ResourceModel/RuleTest.php
@@ -5,22 +5,78 @@
*/
namespace Magento\SalesRule\Model\ResourceModel;
+use Magento\SalesRule\Test\Fixture\ProductCondition as ProductConditionFixture;
+use Magento\SalesRule\Test\Fixture\ProductFoundInCartConditions as ProductFoundInCartConditionsFixture;
+use Magento\SalesRule\Test\Fixture\Rule as RuleFixture;
+use Magento\TestFramework\Fixture\DataFixture;
+use Magento\TestFramework\Fixture\DataFixtureStorage;
+use Magento\TestFramework\Fixture\DataFixtureStorageManager;
+use Magento\TestFramework\Helper\Bootstrap;
+
/**
* @magentoDbIsolation enabled
* @magentoAppIsolation enabled
*/
class RuleTest extends \PHPUnit\Framework\TestCase
{
+ /**
+ * @var DataFixtureStorage
+ */
+ private $fixtures;
+
+ /**
+ * @var Rule
+ */
+ private $resource;
+
+ /**
+ * @inheirtDoc
+ */
+ protected function setUp(): void
+ {
+ $this->fixtures = Bootstrap::getObjectManager()->get(
+ DataFixtureStorageManager::class
+ )->getStorage();
+ $this->resource = Bootstrap::getObjectManager()->create(
+ Rule::class
+ );
+ }
+
/**
* @magentoDataFixture Magento/SalesRule/_files/rule_custom_product_attribute.php
*/
public function testAfterSave()
{
- $resource = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
- \Magento\SalesRule\Model\ResourceModel\Rule::class
- );
- $items = $resource->getActiveAttributes();
+ $items = $this->resource->getActiveAttributes();
$this->assertEquals([['attribute_code' => 'attribute_for_sales_rule_1']], $items);
}
+
+ #[
+ DataFixture(
+ ProductConditionFixture::class,
+ ['attribute' => 'category_ids', 'value' => '2'],
+ 'cond11'
+ ),
+ DataFixture(
+ ProductFoundInCartConditionsFixture::class,
+ ['conditions' => ['$cond11$']],
+ 'cond1'
+ ),
+ DataFixture(
+ RuleFixture::class,
+ ['discount_amount' => 50, 'conditions' => ['$cond1$'], 'is_active' => 0],
+ 'rule1'
+ )
+ ]
+ public function testGetActiveAttributes()
+ {
+ $rule = $this->fixtures->get('rule1');
+ $items = $this->resource->getActiveAttributes();
+ $this->assertEquals([], $items);
+ $rule->setIsActive(1);
+ $rule->save();
+ $items = $this->resource->getActiveAttributes();
+ $this->assertEquals([['attribute_code' => 'category_ids']], $items);
+ }
}
diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/file-uploader.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/file-uploader.test.js
index ba5ad61cfe31..d7516c64fedc 100644
--- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/file-uploader.test.js
+++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/file-uploader.test.js
@@ -33,7 +33,13 @@ define([
},
component,
dataScope = 'dataScope',
- originalJQuery = jQuery.fn;
+ originalJQuery = jQuery.fn,
+ params = {
+ provider: 'provName',
+ name: '',
+ index: '',
+ dataScope: dataScope
+ };
beforeEach(function (done) {
injector.mock(mocks);
@@ -41,12 +47,7 @@ define([
'Magento_Ui/js/form/element/file-uploader',
'knockoutjs/knockout-es5'
], function (Constr) {
- component = new Constr({
- provider: 'provName',
- name: '',
- index: '',
- dataScope: dataScope
- });
+ component = new Constr(params);
done();
});
@@ -69,6 +70,40 @@ define([
});
});
+ describe('setInitialValue method', function () {
+
+ it('check for chainable', function () {
+ expect(component.setInitialValue()).toEqual(component);
+ });
+ it('check for set value', function () {
+ var initialValue = [
+ {
+ 'name': 'test.png',
+ 'size': 0,
+ 'type': 'image/png',
+ 'url': 'http://localhost:8000/media/wysiwyg/test.png'
+ }
+ ], expectedValue = [
+ {
+ 'name': 'test.png',
+ 'size': 2000,
+ 'type': 'image/png',
+ 'url': 'http://localhost:8000/media/wysiwyg/test.png'
+ }
+ ];
+
+ spyOn(component, 'setImageSize').and.callFake(function () {
+ component.value().size = 2000;
+ });
+ spyOn(component, 'getInitialValue').and.returnValue(initialValue);
+ component.service = true;
+ expect(component.setInitialValue()).toEqual(component);
+ expect(component.getInitialValue).toHaveBeenCalled();
+ component.setImageSize(initialValue);
+ expect(component.value().size).toEqual(expectedValue[0].size);
+ });
+ });
+
describe('isFileAllowed method', function () {
var invalidFile,
validFile;
diff --git a/lib/internal/Magento/Framework/Backup/Filesystem/Iterator/File.php b/lib/internal/Magento/Framework/Backup/Filesystem/Iterator/File.php
index b58ad53dd139..1409fba14c5f 100644
--- a/lib/internal/Magento/Framework/Backup/Filesystem/Iterator/File.php
+++ b/lib/internal/Magento/Framework/Backup/Filesystem/Iterator/File.php
@@ -19,6 +19,13 @@ class File extends \SplFileObject
*/
protected $_currentStatement = '';
+ /**
+ * Store current statement delimiter.
+ *
+ * @var string
+ */
+ private string $statementDelimiter = ';';
+
/**
* Return current sql statement
*
@@ -41,15 +48,35 @@ public function next()
$this->_currentStatement = '';
while (!$this->eof()) {
$line = $this->fgets();
- if (strlen(trim($line))) {
- $this->_currentStatement .= $line;
- if ($this->_isLineLastInCommand($line)) {
+ $trimmedLine = trim($line);
+ if (!empty($trimmedLine) && !$this->isDelimiterChanged($trimmedLine)) {
+ $statementFinalLine = '/(?.*)' . preg_quote($this->statementDelimiter, '/') . '$/';
+ if (preg_match($statementFinalLine, $trimmedLine, $matches)) {
+ $this->_currentStatement .= $matches['statement'];
break;
+ } else {
+ $this->_currentStatement .= $line;
}
}
}
}
+ /**
+ * Check whether statement delimiter has been changed.
+ *
+ * @param string $line
+ * @return bool
+ */
+ private function isDelimiterChanged(string $line): bool
+ {
+ if (preg_match('/^delimiter\s+(?.+)$/i', $line, $matches)) {
+ $this->statementDelimiter = $matches['delimiter'];
+ return true;
+ }
+
+ return false;
+ }
+
/**
* Return to first statement
*
@@ -72,26 +99,4 @@ protected function _isComment($line)
{
return $line[0] == '#' || ($line && substr($line, 0, 2) == '--');
}
-
- /**
- * Check is line a last in sql command
- *
- * @param string $line
- * @return bool
- */
- protected function _isLineLastInCommand($line)
- {
- $cleanLine = trim($line);
- $lineLength = strlen($cleanLine);
-
- $returnResult = false;
- if ($lineLength > 0) {
- $lastSymbolIndex = $lineLength - 1;
- if ($cleanLine[$lastSymbolIndex] == ';') {
- $returnResult = true;
- }
- }
-
- return $returnResult;
- }
}