diff --git a/app/code/Magento/Checkout/i18n/en_US.csv b/app/code/Magento/Checkout/i18n/en_US.csv
index 4a78f8deae841..85ee4e1f03f0e 100644
--- a/app/code/Magento/Checkout/i18n/en_US.csv
+++ b/app/code/Magento/Checkout/i18n/en_US.csv
@@ -176,7 +176,7 @@ Summary,Summary
"We'll send your order confirmation here.","We'll send your order confirmation here."
Payment,Payment
"Not yet calculated","Not yet calculated"
-"We received your order!","We received your order!"
+"The order was not successful!","The order was not successful!"
"Thank you for your purchase!","Thank you for your purchase!"
"Password", "Password"
"Something went wrong while saving the page. Please refresh the page and try again.","Something went wrong while saving the page. Please refresh the page and try again."
@@ -184,4 +184,4 @@ Payment,Payment
"Items in Cart","Items in Cart"
"Close","Close"
"Show Cross-sell Items in the Shopping Cart","Show Cross-sell Items in the Shopping Cart"
-"You added %1 to your shopping cart .","You added %1 to your shopping cart ."
\ No newline at end of file
+"You added %1 to your shopping cart .","You added %1 to your shopping cart ."
diff --git a/app/code/Magento/Checkout/view/frontend/layout/checkout_onepage_failure.xml b/app/code/Magento/Checkout/view/frontend/layout/checkout_onepage_failure.xml
index 3ab37c2ab6b9f..b815bf74c155a 100644
--- a/app/code/Magento/Checkout/view/frontend/layout/checkout_onepage_failure.xml
+++ b/app/code/Magento/Checkout/view/frontend/layout/checkout_onepage_failure.xml
@@ -9,7 +9,7 @@
- We received your order!
+ The order was not successful!
diff --git a/app/code/Magento/MediaGalleryCatalogUi/Test/Mftf/ActionGroup/AdminAssertCategoryGridPageDetailsActionGroup.xml b/app/code/Magento/MediaGalleryCatalogUi/Test/Mftf/ActionGroup/AdminAssertCategoryGridPageDetailsActionGroup.xml
index 0788bbd60291a..884fa47152932 100644
--- a/app/code/Magento/MediaGalleryCatalogUi/Test/Mftf/ActionGroup/AdminAssertCategoryGridPageDetailsActionGroup.xml
+++ b/app/code/Magento/MediaGalleryCatalogUi/Test/Mftf/ActionGroup/AdminAssertCategoryGridPageDetailsActionGroup.xml
@@ -12,9 +12,12 @@
Assert category grid page basic columns values for default category
+
+
+
diff --git a/app/code/Magento/MediaGalleryCatalogUi/Test/Mftf/ActionGroup/AssertAdminMediaGalleryAssetFilterPlaceHolderActionGroup.xml b/app/code/Magento/MediaGalleryCatalogUi/Test/Mftf/ActionGroup/AssertAdminMediaGalleryAssetFilterPlaceHolderActionGroup.xml
new file mode 100644
index 0000000000000..c9c9a25d8a2a3
--- /dev/null
+++ b/app/code/Magento/MediaGalleryCatalogUi/Test/Mftf/ActionGroup/AssertAdminMediaGalleryAssetFilterPlaceHolderActionGroup.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+ Assert asset filter placeholder value
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/MediaGalleryCatalogUi/Test/Mftf/Section/AdminMediaGalleryCatalogUiCategoryGridSection.xml b/app/code/Magento/MediaGalleryCatalogUi/Test/Mftf/Section/AdminMediaGalleryCatalogUiCategoryGridSection.xml
index f52799be3b410..b787f6feaf61e 100644
--- a/app/code/Magento/MediaGalleryCatalogUi/Test/Mftf/Section/AdminMediaGalleryCatalogUiCategoryGridSection.xml
+++ b/app/code/Magento/MediaGalleryCatalogUi/Test/Mftf/Section/AdminMediaGalleryCatalogUiCategoryGridSection.xml
@@ -9,10 +9,14 @@
diff --git a/app/code/Magento/MediaGalleryCatalogUi/Test/Mftf/Test/AdminMediaGalleryCatalogUiUsedInProductFilterTest.xml b/app/code/Magento/MediaGalleryCatalogUi/Test/Mftf/Test/AdminMediaGalleryCatalogUiUsedInProductFilterTest.xml
index d68fd4cb7cca8..74633fbb73542 100644
--- a/app/code/Magento/MediaGalleryCatalogUi/Test/Mftf/Test/AdminMediaGalleryCatalogUiUsedInProductFilterTest.xml
+++ b/app/code/Magento/MediaGalleryCatalogUi/Test/Mftf/Test/AdminMediaGalleryCatalogUiUsedInProductFilterTest.xml
@@ -62,12 +62,20 @@
+
+
+
+
+
+
+
+
-
+
diff --git a/app/code/Magento/MediaGalleryCatalogUi/Test/Mftf/Test/AdminMediaGalleryCatalogUiVerifyUsedInLinkCategoryGridTest.xml b/app/code/Magento/MediaGalleryCatalogUi/Test/Mftf/Test/AdminMediaGalleryCatalogUiVerifyUsedInLinkCategoryGridTest.xml
index e761ef5cd08ba..7e0fa6c477c45 100644
--- a/app/code/Magento/MediaGalleryCatalogUi/Test/Mftf/Test/AdminMediaGalleryCatalogUiVerifyUsedInLinkCategoryGridTest.xml
+++ b/app/code/Magento/MediaGalleryCatalogUi/Test/Mftf/Test/AdminMediaGalleryCatalogUiVerifyUsedInLinkCategoryGridTest.xml
@@ -54,6 +54,9 @@
+
+
+
diff --git a/app/code/Magento/MediaGalleryCatalogUi/Ui/Component/Listing/Columns/InMenu.php b/app/code/Magento/MediaGalleryCatalogUi/Ui/Component/Listing/Columns/InMenu.php
new file mode 100644
index 0000000000000..fe4720b4a3e60
--- /dev/null
+++ b/app/code/Magento/MediaGalleryCatalogUi/Ui/Component/Listing/Columns/InMenu.php
@@ -0,0 +1,36 @@
+getData('name');
+ foreach ($dataSource['data']['items'] as & $item) {
+ if (isset($item[$fieldName]) && $item[$fieldName] == 1) {
+ $item[$fieldName] = 'Yes';
+ } else {
+ $item[$fieldName] = 'No';
+ }
+ }
+ }
+
+ return $dataSource;
+ }
+}
diff --git a/app/code/Magento/MediaGalleryCatalogUi/Ui/Component/Listing/Columns/IsActive.php b/app/code/Magento/MediaGalleryCatalogUi/Ui/Component/Listing/Columns/IsActive.php
new file mode 100644
index 0000000000000..c6f20c937d5b3
--- /dev/null
+++ b/app/code/Magento/MediaGalleryCatalogUi/Ui/Component/Listing/Columns/IsActive.php
@@ -0,0 +1,36 @@
+getData('name');
+ foreach ($dataSource['data']['items'] as & $item) {
+ if (isset($item[$fieldName]) && $item[$fieldName] == 1) {
+ $item[$fieldName] = 'Yes';
+ } else {
+ $item[$fieldName] = 'No';
+ }
+ }
+ }
+
+ return $dataSource;
+ }
+}
diff --git a/app/code/Magento/MediaGalleryCatalogUi/Ui/Component/Listing/Columns/Thumbnail.php b/app/code/Magento/MediaGalleryCatalogUi/Ui/Component/Listing/Columns/Thumbnail.php
index efb2ad2f8dae5..dada8ee7acc19 100644
--- a/app/code/Magento/MediaGalleryCatalogUi/Ui/Component/Listing/Columns/Thumbnail.php
+++ b/app/code/Magento/MediaGalleryCatalogUi/Ui/Component/Listing/Columns/Thumbnail.php
@@ -5,8 +5,9 @@
*/
namespace Magento\MediaGalleryCatalogUi\Ui\Component\Listing\Columns;
-use Magento\Catalog\Helper\Image;
-use Magento\Framework\DataObject;
+use Magento\Catalog\Model\Category\Image;
+use Magento\Catalog\Model\CategoryRepository;
+use Magento\Framework\View\Asset\Repository as AssetRepository;
use Magento\Framework\View\Element\UiComponent\ContextInterface;
use Magento\Framework\View\Element\UiComponentFactory;
use Magento\Store\Model\Store;
@@ -27,13 +28,32 @@ class Thumbnail extends Column
/**
* @var Image
*/
- private $imageHelper;
+ private $categoryImage;
/**
+ * @var CategoryRepository
+ */
+ private $categoryRepository;
+
+ /**
+ * @var AssetRepository
+ */
+ private $assetRepository;
+
+ /**
+ * @var string[]
+ */
+ private $defaultPlaceholder;
+
+ /**
+ * Thumbnail constructor.
* @param ContextInterface $context
* @param UiComponentFactory $uiComponentFactory
* @param StoreManagerInterface $storeManager
- * @param Image $image
+ * @param Image $categoryImage
+ * @param CategoryRepository $categoryRepository
+ * @param AssetRepository $assetRepository
+ * @param array $defaultPlaceholder
* @param array $components
* @param array $data
*/
@@ -41,13 +61,19 @@ public function __construct(
ContextInterface $context,
UiComponentFactory $uiComponentFactory,
StoreManagerInterface $storeManager,
- Image $image,
+ Image $categoryImage,
+ CategoryRepository $categoryRepository,
+ AssetRepository $assetRepository,
+ array $defaultPlaceholder = [],
array $components = [],
array $data = []
) {
parent::__construct($context, $uiComponentFactory, $components, $data);
- $this->imageHelper = $image;
$this->storeManager = $storeManager;
+ $this->categoryImage = $categoryImage;
+ $this->categoryRepository = $categoryRepository;
+ $this->assetRepository = $assetRepository;
+ $this->defaultPlaceholder = $defaultPlaceholder;
}
/**
@@ -55,20 +81,34 @@ public function __construct(
*
* @param array $dataSource
* @return array
+ * @throws \Magento\Framework\Exception\LocalizedException
+ * @throws \Magento\Framework\Exception\NoSuchEntityException
*/
public function prepareDataSource(array $dataSource)
{
- if (isset($dataSource['data']['items'])) {
- $fieldName = $this->getData('name');
- foreach ($dataSource['data']['items'] as & $item) {
- if (isset($item[$fieldName])) {
- $item[$fieldName . '_src'] = $this->getUrl($item[$fieldName]);
- } else {
- $category = new DataObject($item);
- $imageHelper = $this->imageHelper->init($category, 'product_listing_thumbnail');
- $item[$fieldName . '_src'] = $imageHelper->getUrl();
+ if (!isset($dataSource['data']['items'])) {
+ return $dataSource;
+ }
+
+ $fieldName = $this->getData('name');
+ foreach ($dataSource['data']['items'] as & $item) {
+ if (isset($item[$fieldName])) {
+ $item[$fieldName . '_src'] = $this->getUrl($item[$fieldName]);
+ continue;
+ }
+
+ if (isset($item['entity_id'])) {
+ $src = $this->categoryImage->getUrl(
+ $this->categoryRepository->get($item['entity_id'])
+ );
+
+ if (!empty($src)) {
+ $item[$fieldName . '_src'] = $src;
+ continue;
}
}
+
+ $item[$fieldName . '_src'] = $this->assetRepository->getUrl($this->defaultPlaceholder['image']);
}
return $dataSource;
diff --git a/app/code/Magento/MediaGalleryCatalogUi/Ui/Component/Listing/Filters/UsedInProducts.php b/app/code/Magento/MediaGalleryCatalogUi/Ui/Component/Listing/Filters/UsedInProducts.php
index 254ebd047c954..d86617e12b8f8 100644
--- a/app/code/Magento/MediaGalleryCatalogUi/Ui/Component/Listing/Filters/UsedInProducts.php
+++ b/app/code/Magento/MediaGalleryCatalogUi/Ui/Component/Listing/Filters/UsedInProducts.php
@@ -80,54 +80,36 @@ public function prepare()
{
$options = [];
$productIds = [];
- $bookmarks = $this->bookmarkManagement->loadByNamespace($this->context->getNameSpace())->getItems();
- foreach ($bookmarks as $bookmark) {
- if ($bookmark->getIdentifier() === 'current') {
- $applied = $bookmark->getConfig()['current']['filters']['applied'];
- if (isset($applied[$this->getName()])) {
- $productIds = $applied[$this->getName()];
- }
- }
+ $bookmark = $this->bookmarkManagement->getByIdentifierNamespace(
+ 'current',
+ $this->context->getNameSpace()
+ );
+ if ($bookmark === null) {
+ parent::prepare();
+ return;
}
- foreach ($productIds as $id) {
- $product = $this->productRepository->getById($id);
- $options[] = [
- 'value' => $id,
- 'label' => $product->getName(),
- 'is_active' => $product->getStatus(),
- 'path' => $product->getSku(),
- 'optgroup' => false
+ $applied = $bookmark->getConfig()['current']['filters']['applied'];
- ];
+ if (isset($applied[$this->getName()])) {
+ $productIds = $applied[$this->getName()];
}
- $this->wrappedComponent = $this->uiComponentFactory->create(
- $this->getName(),
- parent::COMPONENT,
- [
- 'context' => $this->getContext(),
- 'options' => $options
- ]
- );
-
- $this->wrappedComponent->prepare();
- $productsFilterJsConfig = array_replace_recursive(
- $this->getJsConfig($this->wrappedComponent),
- $this->getJsConfig($this)
- );
- $this->setData('js_config', $productsFilterJsConfig);
-
- $this->setData(
- 'config',
- array_replace_recursive(
- (array)$this->wrappedComponent->getData('config'),
- (array)$this->getData('config')
- )
- );
-
- $this->applyFilter();
-
+ foreach ($productIds as $id) {
+ try {
+ $product = $this->productRepository->getById($id);
+ $options[] = [
+ 'value' => $id,
+ 'label' => $product->getName(),
+ 'is_active' => $product->getStatus(),
+ 'path' => $product->getSku(),
+ 'optgroup' => false
+ ];
+ } catch (\Exception $e) {
+ continue;
+ }
+ }
+ $this->optionsProvider = $options;
parent::prepare();
}
}
diff --git a/app/code/Magento/MediaGalleryCatalogUi/etc/adminhtml/di.xml b/app/code/Magento/MediaGalleryCatalogUi/etc/adminhtml/di.xml
index ae01c29928b4a..2aaf5a56cf837 100644
--- a/app/code/Magento/MediaGalleryCatalogUi/etc/adminhtml/di.xml
+++ b/app/code/Magento/MediaGalleryCatalogUi/etc/adminhtml/di.xml
@@ -38,4 +38,11 @@
+
+
+
+ - Magento_MediaGalleryCatalogUi::images/category/placeholder/image.jpg
+
+
+
diff --git a/app/code/Magento/MediaGalleryCatalogUi/view/adminhtml/ui_component/media_gallery_category_listing.xml b/app/code/Magento/MediaGalleryCatalogUi/view/adminhtml/ui_component/media_gallery_category_listing.xml
index 9945643ccffef..e12d90b95303b 100644
--- a/app/code/Magento/MediaGalleryCatalogUi/view/adminhtml/ui_component/media_gallery_category_listing.xml
+++ b/app/code/Magento/MediaGalleryCatalogUi/view/adminhtml/ui_component/media_gallery_category_listing.xml
@@ -167,12 +167,12 @@
Products
-
+
In Menu
-
+
Enabled
diff --git a/app/code/Magento/MediaGalleryCatalogUi/view/adminhtml/web/images/category/placeholder/image.jpg b/app/code/Magento/MediaGalleryCatalogUi/view/adminhtml/web/images/category/placeholder/image.jpg
new file mode 100644
index 0000000000000..0d5ef7e1bd412
Binary files /dev/null and b/app/code/Magento/MediaGalleryCatalogUi/view/adminhtml/web/images/category/placeholder/image.jpg differ
diff --git a/app/code/Magento/MediaGalleryCmsUi/Ui/Component/Listing/Filters/UsedInBlocks.php b/app/code/Magento/MediaGalleryCmsUi/Ui/Component/Listing/Filters/UsedInBlocks.php
index 09fea24c8a2a9..66f8caa71d70a 100644
--- a/app/code/Magento/MediaGalleryCmsUi/Ui/Component/Listing/Filters/UsedInBlocks.php
+++ b/app/code/Magento/MediaGalleryCmsUi/Ui/Component/Listing/Filters/UsedInBlocks.php
@@ -80,52 +80,36 @@ public function prepare()
{
$options = [];
$blockIds = [];
- $bookmarks = $this->bookmarkManagement->loadByNamespace($this->context->getNameSpace())->getItems();
- foreach ($bookmarks as $bookmark) {
- if ($bookmark->getIdentifier() === 'current') {
- $applied = $bookmark->getConfig()['current']['filters']['applied'];
- if (isset($applied[$this->getName()])) {
- $blockIds = $applied[$this->getName()];
- }
- }
- }
-
- foreach ($blockIds as $id) {
- $block = $this->blockRepository->getById($id);
- $options[] = [
- 'value' => $id,
- 'label' => $block->getTitle(),
- 'is_active' => $block->isActive(),
- 'optgroup' => false
- ];
+ $bookmark = $this->bookmarkManagement->getByIdentifierNamespace(
+ 'current',
+ $this->context->getNameSpace()
+ );
+ if ($bookmark === null) {
+ parent::prepare();
+ return;
}
- $this->wrappedComponent = $this->uiComponentFactory->create(
- $this->getName(),
- parent::COMPONENT,
- [
- 'context' => $this->getContext(),
- 'options' => $options
- ]
- );
+ $applied = $bookmark->getConfig()['current']['filters']['applied'];
- $this->wrappedComponent->prepare();
- $jsConfig = array_replace_recursive(
- $this->getJsConfig($this->wrappedComponent),
- $this->getJsConfig($this)
- );
- $this->setData('js_config', $jsConfig);
-
- $this->setData(
- 'config',
- array_replace_recursive(
- (array)$this->wrappedComponent->getData('config'),
- (array)$this->getData('config')
- )
- );
+ if (isset($applied[$this->getName()])) {
+ $blockIds = $applied[$this->getName()];
+ }
- $this->applyFilter();
+ foreach ($blockIds as $id) {
+ try {
+ $block = $this->blockRepository->getById($id);
+ $options[] = [
+ 'value' => $id,
+ 'label' => $block->getTitle(),
+ 'is_active' => $block->isActive(),
+ 'optgroup' => false
+ ];
+ } catch (\Exception $e) {
+ continue;
+ }
+ }
+ $this->optionsProvider = $options;
parent::prepare();
}
}
diff --git a/app/code/Magento/MediaGalleryCmsUi/Ui/Component/Listing/Filters/UsedInPages.php b/app/code/Magento/MediaGalleryCmsUi/Ui/Component/Listing/Filters/UsedInPages.php
index 235a77cdcb8c5..78ab1b63d32d1 100644
--- a/app/code/Magento/MediaGalleryCmsUi/Ui/Component/Listing/Filters/UsedInPages.php
+++ b/app/code/Magento/MediaGalleryCmsUi/Ui/Component/Listing/Filters/UsedInPages.php
@@ -80,52 +80,35 @@ public function prepare()
{
$options = [];
$pageIds = [];
- $bookmarks = $this->bookmarkManagement->loadByNamespace($this->context->getNameSpace())->getItems();
- foreach ($bookmarks as $bookmark) {
- if ($bookmark->getIdentifier() === 'current') {
- $applied = $bookmark->getConfig()['current']['filters']['applied'];
- if (isset($applied[$this->getName()])) {
- $pageIds = $applied[$this->getName()];
- }
- }
- }
-
- foreach ($pageIds as $id) {
- $page = $this->pageRepository->getById($id);
- $options[] = [
- 'value' => $id,
- 'label' => $page->getTitle(),
- 'is_active' => $page->isActive(),
- 'optgroup' => false
- ];
- }
-
- $this->wrappedComponent = $this->uiComponentFactory->create(
- $this->getName(),
- parent::COMPONENT,
- [
- 'context' => $this->getContext(),
- 'options' => $options
- ]
- );
-
- $this->wrappedComponent->prepare();
- $pagesFilterjsConfig = array_replace_recursive(
- $this->getJsConfig($this->wrappedComponent),
- $this->getJsConfig($this)
+ $bookmark = $this->bookmarkManagement->getByIdentifierNamespace(
+ 'current',
+ $this->context->getNameSpace()
);
- $this->setData('js_config', $pagesFilterjsConfig);
+ if ($bookmark === null) {
+ parent::prepare();
+ return;
+ }
- $this->setData(
- 'config',
- array_replace_recursive(
- (array)$this->wrappedComponent->getData('config'),
- (array)$this->getData('config')
- )
- );
+ $applied = $bookmark->getConfig()['current']['filters']['applied'];
- $this->applyFilter();
+ if (isset($applied[$this->getName()])) {
+ $pageIds = $applied[$this->getName()];
+ }
+ foreach ($pageIds as $id) {
+ try {
+ $page = $this->pageRepository->getById($id);
+ $options[] = [
+ 'value' => $id,
+ 'label' => $page->getTitle(),
+ 'is_active' => $page->isActive(),
+ 'optgroup' => false
+ ];
+ } catch (\Exception $e) {
+ continue;
+ }
+ }
+ $this->optionsProvider = $options;
parent::prepare();
}
}
diff --git a/app/code/Magento/MediaGalleryIntegration/Model/OpenDialogUrlProvider.php b/app/code/Magento/MediaGalleryIntegration/Plugin/NewMediaGalleryOpenDialogUrl.php
similarity index 57%
rename from app/code/Magento/MediaGalleryIntegration/Model/OpenDialogUrlProvider.php
rename to app/code/Magento/MediaGalleryIntegration/Plugin/NewMediaGalleryOpenDialogUrl.php
index 317b811df5692..ed8108f012af0 100644
--- a/app/code/Magento/MediaGalleryIntegration/Model/OpenDialogUrlProvider.php
+++ b/app/code/Magento/MediaGalleryIntegration/Plugin/NewMediaGalleryOpenDialogUrl.php
@@ -5,15 +5,15 @@
*/
declare(strict_types=1);
-namespace Magento\MediaGalleryIntegration\Model;
+namespace Magento\MediaGalleryIntegration\Plugin;
-use Magento\Framework\DataObject;
use Magento\MediaGalleryUiApi\Api\ConfigInterface;
+use Magento\Ui\Component\Form\Element\DataType\Media\OpenDialogUrl;
/**
- * Provider to get open media gallery dialog URL for WYSIWYG and widgets
+ * Plugin to get open media gallery dialog URL for WYSIWYG and widgets
*/
-class OpenDialogUrlProvider extends DataObject
+class NewMediaGalleryOpenDialogUrl
{
/**
* @var ConfigInterface
@@ -31,10 +31,13 @@ public function __construct(ConfigInterface $config)
/**
* Get Url based on media gallery configuration
*
+ * @param OpenDialogUrl $subject
+ * @param string $result
+ * @SuppressWarnings(PHPMD.UnusedFormalParameter)
* @return string
*/
- public function getUrl(): string
+ public function afterGet(OpenDialogUrl $subject, string $result)
{
- return $this->config->isEnabled() ? 'media_gallery/index/index' : 'cms/wysiwyg_images/index';
+ return $this->config->isEnabled() ? 'media_gallery/index/index' : $result;
}
}
diff --git a/app/code/Magento/MediaGalleryIntegration/Test/Integration/Model/OpenDialogUrlProviderTest.php b/app/code/Magento/MediaGalleryIntegration/Test/Integration/Model/OpenDialogUrlTest.php
similarity index 80%
rename from app/code/Magento/MediaGalleryIntegration/Test/Integration/Model/OpenDialogUrlProviderTest.php
rename to app/code/Magento/MediaGalleryIntegration/Test/Integration/Model/OpenDialogUrlTest.php
index 7a3316f293879..90f363d6d792b 100644
--- a/app/code/Magento/MediaGalleryIntegration/Test/Integration/Model/OpenDialogUrlProviderTest.php
+++ b/app/code/Magento/MediaGalleryIntegration/Test/Integration/Model/OpenDialogUrlTest.php
@@ -9,16 +9,16 @@
namespace Magento\MediaGalleryIntegration\Test\Integration\Model;
use Magento\Framework\ObjectManagerInterface;
-use Magento\MediaGalleryIntegration\Model\OpenDialogUrlProvider;
use Magento\MediaGalleryUiApi\Api\ConfigInterface;
use Magento\TestFramework\Helper\Bootstrap;
+use Magento\Ui\Component\Form\Element\DataType\Media\OpenDialogUrl;
use PHPUnit\Framework\TestCase;
/**
* Provide tests cover getting correct url based on the config settings.
* @magentoAppArea adminhtml
*/
-class OpenDialogUrlProviderTest extends TestCase
+class OpenDialogUrlTest extends TestCase
{
/**
* @var ObjectManagerInterface
@@ -26,9 +26,9 @@ class OpenDialogUrlProviderTest extends TestCase
private $objectManger;
/**
- * @var OpenDialogUrlProvider
+ * @var OpenDialogUrl
*/
- private $openDialogUrlProvider;
+ private $openDialogUrl;
/**
* @inheritdoc
@@ -37,8 +37,8 @@ protected function setUp(): void
{
$this->objectManger = Bootstrap::getObjectManager();
$config = $this->objectManger->create(ConfigInterface::class);
- $this->openDialogUrlProvider = $this->objectManger->create(
- OpenDialogUrlProvider::class,
+ $this->openDialogUrl = $this->objectManger->create(
+ OpenDialogUrl::class,
['config' => $config]
);
}
@@ -49,7 +49,7 @@ protected function setUp(): void
*/
public function testWithEnhancedMediaGalleryDisabled(): void
{
- self::assertEquals('cms/wysiwyg_images/index', $this->openDialogUrlProvider->getUrl());
+ self::assertEquals('cms/wysiwyg_images/index', $this->openDialogUrl->get());
}
/**
@@ -58,6 +58,6 @@ public function testWithEnhancedMediaGalleryDisabled(): void
*/
public function testWithEnhancedMediaGalleryEnabled(): void
{
- self::assertEquals('media_gallery/index/index', $this->openDialogUrlProvider->getUrl());
+ self::assertEquals('media_gallery/index/index', $this->openDialogUrl->get());
}
}
diff --git a/app/code/Magento/MediaGalleryIntegration/composer.json b/app/code/Magento/MediaGalleryIntegration/composer.json
index c55d6e0b89733..a9709da81222e 100644
--- a/app/code/Magento/MediaGalleryIntegration/composer.json
+++ b/app/code/Magento/MediaGalleryIntegration/composer.json
@@ -6,7 +6,8 @@
"magento/framework": "*",
"magento/module-media-gallery-ui-api": "*",
"magento/module-media-gallery-api": "*",
- "magento/module-media-gallery-synchronization-api": "*"
+ "magento/module-media-gallery-synchronization-api": "*",
+ "magento/module-ui": "*"
},
"require-dev": {
"magento/module-cms": "*"
diff --git a/app/code/Magento/MediaGalleryIntegration/etc/adminhtml/di.xml b/app/code/Magento/MediaGalleryIntegration/etc/adminhtml/di.xml
index 1559a6d7dfcd5..08e83ce6cad88 100644
--- a/app/code/Magento/MediaGalleryIntegration/etc/adminhtml/di.xml
+++ b/app/code/Magento/MediaGalleryIntegration/etc/adminhtml/di.xml
@@ -7,9 +7,7 @@
-->
-
- Magento\MediaGalleryIntegration\Model\OpenDialogUrlProvider
-
+
diff --git a/app/code/Magento/MediaGalleryMetadata/Model/GetIptcMetadata.php b/app/code/Magento/MediaGalleryMetadata/Model/GetIptcMetadata.php
index d7290f31ee34e..e100a7f852e42 100644
--- a/app/code/Magento/MediaGalleryMetadata/Model/GetIptcMetadata.php
+++ b/app/code/Magento/MediaGalleryMetadata/Model/GetIptcMetadata.php
@@ -9,7 +9,6 @@
use Magento\MediaGalleryMetadataApi\Api\Data\MetadataInterface;
use Magento\MediaGalleryMetadataApi\Api\Data\MetadataInterfaceFactory;
-use Magento\MediaGalleryMetadataApi\Model\SegmentInterface;
/**
* Get metadata from IPTC block
@@ -42,8 +41,8 @@ public function __construct(
*/
public function execute(string $data): MetadataInterface
{
- $title = '';
- $description = '';
+ $title = null;
+ $description = null;
$keywords = [];
if (is_callable('iptcparse')) {
@@ -65,7 +64,7 @@ public function execute(string $data): MetadataInterface
return $this->metadataFactory->create([
'title' => $title,
'description' => $description,
- 'keywords' => $keywords
+ 'keywords' => !empty($keywords) ? $keywords : null
]);
}
}
diff --git a/app/code/Magento/MediaGalleryMetadata/Model/Jpeg/Segment/ReadExif.php b/app/code/Magento/MediaGalleryMetadata/Model/Jpeg/Segment/ReadExif.php
new file mode 100644
index 0000000000000..b6c32296f3f7d
--- /dev/null
+++ b/app/code/Magento/MediaGalleryMetadata/Model/Jpeg/Segment/ReadExif.php
@@ -0,0 +1,104 @@
+metadataFactory = $metadataFactory;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function execute(FileInterface $file): MetadataInterface
+ {
+ if (!is_callable('exif_read_data')) {
+ throw new LocalizedException(
+ __('exif_read_data() must be enabled in php configuration')
+ );
+ }
+
+ foreach ($file->getSegments() as $segment) {
+ if ($this->isExifSegment($segment)) {
+ return $this->getExifData($file->getPath());
+ }
+ }
+
+ return $this->metadataFactory->create([
+ 'title' => null,
+ 'description' => null,
+ 'keywords' => null
+ ]);
+ }
+
+ /**
+ * Parese exif data from segment
+ *
+ * @param string $filePath
+ */
+ private function getExifData(string $filePath): MetadataInterface
+ {
+ $title = null;
+ $description = null;
+ $keywords = null;
+
+ $data = exif_read_data($filePath);
+
+ if (!empty($data)) {
+ $title = isset($data['DocumentName']) ? $data['DocumentName'] : null;
+ $description = isset($data['ImageDescription']) ? $data['ImageDescription'] : null;
+ }
+
+ return $this->metadataFactory->create([
+ 'title' => $title,
+ 'description' => $description,
+ 'keywords' => $keywords
+ ]);
+ }
+
+ /**
+ * Does segment contain Exif data
+ *
+ * @param SegmentInterface $segment
+ * @return bool
+ */
+ private function isExifSegment(SegmentInterface $segment): bool
+ {
+ return $segment->getName() === self::EXIF_SEGMENT_NAME
+ && strncmp(
+ substr($segment->getData(), self::EXIF_DATA_START_POSITION, 5),
+ self::EXIF_SEGMENT_START,
+ 5
+ ) == 0;
+ }
+}
diff --git a/app/code/Magento/MediaGalleryMetadata/Model/Jpeg/Segment/ReadIptc.php b/app/code/Magento/MediaGalleryMetadata/Model/Jpeg/Segment/ReadIptc.php
index 94ccb400e5e0a..e56993528a041 100644
--- a/app/code/Magento/MediaGalleryMetadata/Model/Jpeg/Segment/ReadIptc.php
+++ b/app/code/Magento/MediaGalleryMetadata/Model/Jpeg/Segment/ReadIptc.php
@@ -56,9 +56,9 @@ public function execute(FileInterface $file): MetadataInterface
}
}
return $this->metadataFactory->create([
- 'title' => '',
- 'description' => '',
- 'keywords' => []
+ 'title' => null,
+ 'description' => null,
+ 'keywords' => null
]);
}
diff --git a/app/code/Magento/MediaGalleryMetadata/Model/Jpeg/Segment/ReadXmp.php b/app/code/Magento/MediaGalleryMetadata/Model/Jpeg/Segment/ReadXmp.php
index 81ff7200c3475..e68c86d35eb97 100644
--- a/app/code/Magento/MediaGalleryMetadata/Model/Jpeg/Segment/ReadXmp.php
+++ b/app/code/Magento/MediaGalleryMetadata/Model/Jpeg/Segment/ReadXmp.php
@@ -54,9 +54,9 @@ public function execute(FileInterface $file): MetadataInterface
}
}
return $this->metadataFactory->create([
- 'title' => '',
- 'description' => '',
- 'keywords' => []
+ 'title' => null,
+ 'description' => null,
+ 'keywords' => null
]);
}
diff --git a/app/code/Magento/MediaGalleryMetadata/Model/Png/Segment/ReadExif.php b/app/code/Magento/MediaGalleryMetadata/Model/Png/Segment/ReadExif.php
new file mode 100644
index 0000000000000..09aeaf526443a
--- /dev/null
+++ b/app/code/Magento/MediaGalleryMetadata/Model/Png/Segment/ReadExif.php
@@ -0,0 +1,97 @@
+metadataFactory = $metadataFactory;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function execute(FileInterface $file): MetadataInterface
+ {
+ if (!is_callable('exif_read_data')) {
+ throw new LocalizedException(
+ __('exif_read_data() must be enabled in php configuration')
+ );
+ }
+
+ foreach ($file->getSegments() as $segment) {
+ if ($this->isExifSegment($segment)) {
+ return $this->getExifData($segment);
+ }
+ }
+
+ return $this->metadataFactory->create([
+ 'title' => null,
+ 'description' => null,
+ 'keywords' => null
+ ]);
+ }
+
+ /**
+ * Parese exif data from segment
+ *
+ * @param SegmentInterface $segment
+ */
+ private function getExifData(SegmentInterface $segment): MetadataInterface
+ {
+ $title = null;
+ $description = null;
+ $keywords = [];
+
+ $data = exif_read_data('data://image/jpeg;base64,' . base64_encode($segment->getData()));
+
+ if ($data) {
+ $title = isset($data['DocumentName']) ? $data['DocumentName'] : null;
+ $description = isset($data['ImageDescription']) ? $data['ImageDescription'] : null;
+ }
+
+ return $this->metadataFactory->create([
+ 'title' => $title,
+ 'description' => $description,
+ 'keywords' => !empty($keywords) ? $keywords : null
+ ]);
+ }
+
+ /**
+ * Does segment contain Exif data
+ *
+ * @param SegmentInterface $segment
+ * @return bool
+ */
+ private function isExifSegment(SegmentInterface $segment): bool
+ {
+ return strcmp($segment->getName(), self::EXIF_SEGMENT_NAME) === 0;
+ }
+}
diff --git a/app/code/Magento/MediaGalleryMetadata/Model/Png/Segment/ReadXmp.php b/app/code/Magento/MediaGalleryMetadata/Model/Png/Segment/ReadXmp.php
index 83ba554f7bf5d..518697d421474 100644
--- a/app/code/Magento/MediaGalleryMetadata/Model/Png/Segment/ReadXmp.php
+++ b/app/code/Magento/MediaGalleryMetadata/Model/Png/Segment/ReadXmp.php
@@ -55,9 +55,9 @@ public function execute(FileInterface $file): MetadataInterface
}
}
return $this->metadataFactory->create([
- 'title' => '',
- 'description' => '',
- 'keywords' => []
+ 'title' => null,
+ 'description' => null,
+ 'keywords' => null
]);
}
diff --git a/app/code/Magento/MediaGalleryMetadata/Test/Integration/Model/ExtractMetadataTest.php b/app/code/Magento/MediaGalleryMetadata/Test/Integration/Model/ExtractMetadataTest.php
index 982ccbb20fe2c..ebe96183eb1f2 100644
--- a/app/code/Magento/MediaGalleryMetadata/Test/Integration/Model/ExtractMetadataTest.php
+++ b/app/code/Magento/MediaGalleryMetadata/Test/Integration/Model/ExtractMetadataTest.php
@@ -37,14 +37,14 @@ protected function setUp(): void
* @param string $fileName
* @param string $title
* @param string $description
- * @param array $keywords
+ * @param null|array $keywords
* @throws LocalizedException
*/
public function testExecute(
string $fileName,
string $title,
string $description,
- array $keywords
+ ?array $keywords
): void {
$path = realpath(__DIR__ . '/../../_files/' . $fileName);
$metadata = $this->extractMetadata->execute($path);
@@ -62,6 +62,18 @@ public function testExecute(
public function filesProvider(): array
{
return [
+ [
+ 'exif_image.png',
+ 'Exif title png imge',
+ 'Exif description png imge',
+ null
+ ],
+ [
+ 'exif-image.jpeg',
+ 'Exif Magento title',
+ 'Exif description metadata',
+ null
+ ],
[
'macos-photos.jpeg',
'Title of the magento image',
diff --git a/app/code/Magento/MediaGalleryMetadata/Test/_files/empty_iptc.jpeg b/app/code/Magento/MediaGalleryMetadata/Test/_files/empty_iptc.jpeg
index 144a56dac2d3e..1a345c2d33fdd 100644
Binary files a/app/code/Magento/MediaGalleryMetadata/Test/_files/empty_iptc.jpeg and b/app/code/Magento/MediaGalleryMetadata/Test/_files/empty_iptc.jpeg differ
diff --git a/app/code/Magento/MediaGalleryMetadata/Test/_files/exif-image.jpeg b/app/code/Magento/MediaGalleryMetadata/Test/_files/exif-image.jpeg
new file mode 100644
index 0000000000000..cfe27433fd9fc
Binary files /dev/null and b/app/code/Magento/MediaGalleryMetadata/Test/_files/exif-image.jpeg differ
diff --git a/app/code/Magento/MediaGalleryMetadata/Test/_files/exif_image.png b/app/code/Magento/MediaGalleryMetadata/Test/_files/exif_image.png
new file mode 100644
index 0000000000000..4a6bf30c2d516
Binary files /dev/null and b/app/code/Magento/MediaGalleryMetadata/Test/_files/exif_image.png differ
diff --git a/app/code/Magento/MediaGalleryMetadata/Test/_files/macos-preview.png b/app/code/Magento/MediaGalleryMetadata/Test/_files/macos-preview.png
index 966520f0d0112..95eb45f69b3ea 100644
Binary files a/app/code/Magento/MediaGalleryMetadata/Test/_files/macos-preview.png and b/app/code/Magento/MediaGalleryMetadata/Test/_files/macos-preview.png differ
diff --git a/app/code/Magento/MediaGalleryMetadata/etc/di.xml b/app/code/Magento/MediaGalleryMetadata/etc/di.xml
index d2f1f90510488..4cd9a34e43a93 100644
--- a/app/code/Magento/MediaGalleryMetadata/etc/di.xml
+++ b/app/code/Magento/MediaGalleryMetadata/etc/di.xml
@@ -112,6 +112,7 @@
- Magento\MediaGalleryMetadata\Model\Png\Segment\ReadXmp
- Magento\MediaGalleryMetadata\Model\Png\Segment\ReadIptc
+ - Magento\MediaGalleryMetadata\Model\Png\Segment\ReadExif
@@ -121,6 +122,7 @@
- Magento\MediaGalleryMetadata\Model\Jpeg\Segment\ReadXmp
- Magento\MediaGalleryMetadata\Model\Jpeg\Segment\ReadIptc
+ - Magento\MediaGalleryMetadata\Model\Jpeg\Segment\ReadExif
diff --git a/app/code/Magento/MediaGallerySynchronization/Model/CreateAssetFromFile.php b/app/code/Magento/MediaGallerySynchronization/Model/CreateAssetFromFile.php
index 87d477507b680..80b334733ed43 100644
--- a/app/code/Magento/MediaGallerySynchronization/Model/CreateAssetFromFile.php
+++ b/app/code/Magento/MediaGallerySynchronization/Model/CreateAssetFromFile.php
@@ -12,11 +12,10 @@
use Magento\Framework\Filesystem;
use Magento\Framework\Filesystem\Directory\ReadInterface;
use Magento\Framework\Filesystem\Driver\File;
-use Magento\Framework\Stdlib\DateTime\TimezoneInterface;
use Magento\MediaGalleryApi\Api\Data\AssetInterface;
use Magento\MediaGalleryApi\Api\Data\AssetInterfaceFactory;
use Magento\MediaGalleryMetadataApi\Api\ExtractMetadataInterface;
-use Magento\MediaGallerySynchronization\Model\Filesystem\SplFileInfoFactory;
+use Magento\MediaGallerySynchronization\Model\Filesystem\GetFileInfo;
use Magento\MediaGallerySynchronization\Model\GetContentHash;
/**
@@ -24,11 +23,6 @@
*/
class CreateAssetFromFile
{
- /**
- * Date format
- */
- private const DATE_FORMAT = 'Y-m-d H:i:s';
-
/**
* @var Filesystem
*/
@@ -39,11 +33,6 @@ class CreateAssetFromFile
*/
private $driver;
- /**
- * @var TimezoneInterface;
- */
- private $date;
-
/**
* @var AssetInterfaceFactory
*/
@@ -60,35 +49,32 @@ class CreateAssetFromFile
private $extractMetadata;
/**
- * @var SplFileInfoFactory
+ * @var GetFileInfo
*/
- private $splFileInfoFactory;
+ private $getFileInfo;
/**
* @param Filesystem $filesystem
* @param File $driver
- * @param TimezoneInterface $date
* @param AssetInterfaceFactory $assetFactory
* @param GetContentHash $getContentHash
* @param ExtractMetadataInterface $extractMetadata
- * @param SplFileInfoFactory $splFileInfoFactory
+ * @param GetFileInfo $getFileInfo
*/
public function __construct(
Filesystem $filesystem,
File $driver,
- TimezoneInterface $date,
AssetInterfaceFactory $assetFactory,
GetContentHash $getContentHash,
ExtractMetadataInterface $extractMetadata,
- SplFileInfoFactory $splFileInfoFactory
+ GetFileInfo $getFileInfo
) {
$this->filesystem = $filesystem;
$this->driver = $driver;
- $this->date = $date;
$this->assetFactory = $assetFactory;
$this->getContentHash = $getContentHash;
$this->extractMetadata = $extractMetadata;
- $this->splFileInfoFactory = $splFileInfoFactory;
+ $this->getFileInfo = $getFileInfo;
}
/**
@@ -101,7 +87,7 @@ public function __construct(
public function execute(string $path): AssetInterface
{
$absolutePath = $this->getMediaDirectory()->getAbsolutePath($path);
- $file = $this->splFileInfoFactory->create($absolutePath);
+ $file = $this->getFileInfo->execute($absolutePath);
[$width, $height] = getimagesize($absolutePath);
$metadata = $this->extractMetadata->execute($absolutePath);
@@ -110,10 +96,8 @@ public function execute(string $path): AssetInterface
[
'id' => null,
'path' => $path,
- 'title' => $metadata->getTitle() ?: $file->getBasename('.' . $file->getExtension()),
+ 'title' => $metadata->getTitle() ?: $file->getBasename(),
'description' => $metadata->getDescription(),
- 'createdAt' => $this->date->date($file->getCTime())->format(self::DATE_FORMAT),
- 'updatedAt' => $this->date->date($file->getMTime())->format(self::DATE_FORMAT),
'width' => $width,
'height' => $height,
'hash' => $this->getHash($path),
diff --git a/app/code/Magento/MediaGallerySynchronization/Model/Filesystem/FileInfo.php b/app/code/Magento/MediaGallerySynchronization/Model/Filesystem/FileInfo.php
new file mode 100644
index 0000000000000..5e523fd0e905a
--- /dev/null
+++ b/app/code/Magento/MediaGallerySynchronization/Model/Filesystem/FileInfo.php
@@ -0,0 +1,148 @@
+path = $path;
+ $this->filename = $filename;
+ $this->extension = $extension;
+ $this->basename = $basename;
+ $this->size = $size;
+ $this->mTime = $mTime;
+ $this->cTime = $cTime;
+ }
+
+ /**
+ * Get path without filename.
+ *
+ * @return string
+ */
+ public function getPath(): string
+ {
+ return $this->path;
+ }
+
+ /**
+ * Get filename.
+ *
+ * @return string
+ */
+ public function getFilename(): string
+ {
+ return $this->filename;
+ }
+
+ /**
+ * Get file extension.
+ *
+ * @return string
+ */
+ public function getExtension(): string
+ {
+ return $this->extension;
+ }
+
+ /**
+ * Get file basename.
+ *
+ * @return string
+ */
+ public function getBasename(): string
+ {
+ return $this->basename;
+ }
+
+ /**
+ * Get file size.
+ *
+ * @return int
+ */
+ public function getSize(): int
+ {
+ return $this->size;
+ }
+
+ /**
+ * Get last modified time.
+ *
+ * @return int
+ */
+ public function getMTime(): int
+ {
+ return $this->mTime;
+ }
+
+ /**
+ * Get inode change time.
+ *
+ * @return int
+ */
+ public function getCTime(): int
+ {
+ return $this->cTime;
+ }
+}
diff --git a/app/code/Magento/MediaGallerySynchronization/Model/Filesystem/GetFileInfo.php b/app/code/Magento/MediaGallerySynchronization/Model/Filesystem/GetFileInfo.php
new file mode 100644
index 0000000000000..8f9080767d6e3
--- /dev/null
+++ b/app/code/Magento/MediaGallerySynchronization/Model/Filesystem/GetFileInfo.php
@@ -0,0 +1,52 @@
+fileInfoFactory = $fileInfoFactory;
+ }
+
+ /**
+ * Get file information based on path provided.
+ *
+ * @param string $path
+ * @return FileInfo
+ */
+ public function execute(string $path): FileInfo
+ {
+ $splFileInfo = new \SplFileInfo($path);
+
+ return $this->fileInfoFactory->create([
+ 'path' => $splFileInfo->getPath(),
+ 'filename' => $splFileInfo->getFilename(),
+ 'extension' => $splFileInfo->getExtension(),
+ 'basename' => $splFileInfo->getBasename('.' . $splFileInfo->getExtension()),
+ 'size' => $splFileInfo->getSize(),
+ 'mTime' => $splFileInfo->getMTime(),
+ 'cTime' => $splFileInfo->getCTime()
+ ]);
+ }
+}
diff --git a/app/code/Magento/MediaGallerySynchronization/Model/GetAssetFromPath.php b/app/code/Magento/MediaGallerySynchronization/Model/GetAssetFromPath.php
index 5e825d57c5ce7..533d814c9f1d0 100644
--- a/app/code/Magento/MediaGallerySynchronization/Model/GetAssetFromPath.php
+++ b/app/code/Magento/MediaGallerySynchronization/Model/GetAssetFromPath.php
@@ -12,7 +12,6 @@
use Magento\MediaGalleryApi\Api\Data\AssetInterface;
use Magento\MediaGalleryApi\Api\Data\AssetInterfaceFactory;
use Magento\MediaGalleryApi\Api\GetAssetsByPathsInterface;
-use Magento\MediaGallerySynchronization\Model\Filesystem\SplFileInfoFactory;
/**
* Create media asset object based on the file information
@@ -34,27 +33,19 @@ class GetAssetFromPath
*/
private $createAssetFromFile;
- /**
- * @var SplFileInfoFactory
- */
- private $splFileInfoFactory;
-
/**
* @param AssetInterfaceFactory $assetFactory
* @param GetAssetsByPathsInterface $getMediaGalleryAssetByPath
* @param CreateAssetFromFile $createAssetFromFile
- * @param SplFileInfoFactory $splFileInfoFactory
*/
public function __construct(
AssetInterfaceFactory $assetFactory,
GetAssetsByPathsInterface $getMediaGalleryAssetByPath,
- CreateAssetFromFile $createAssetFromFile,
- SplFileInfoFactory $splFileInfoFactory
+ CreateAssetFromFile $createAssetFromFile
) {
$this->assetFactory = $assetFactory;
$this->getAssetsByPaths = $getMediaGalleryAssetByPath;
$this->createAssetFromFile = $createAssetFromFile;
- $this->splFileInfoFactory= $splFileInfoFactory;
}
/**
diff --git a/app/code/Magento/MediaGallerySynchronization/Model/SynchronizeFiles.php b/app/code/Magento/MediaGallerySynchronization/Model/SynchronizeFiles.php
index 81e9629f703f3..eebb172e48202 100644
--- a/app/code/Magento/MediaGallerySynchronization/Model/SynchronizeFiles.php
+++ b/app/code/Magento/MediaGallerySynchronization/Model/SynchronizeFiles.php
@@ -16,7 +16,7 @@
use Magento\MediaGalleryApi\Api\GetAssetsByPathsInterface;
use Magento\MediaGallerySynchronizationApi\Model\ImportFilesInterface;
use Magento\MediaGallerySynchronizationApi\Api\SynchronizeFilesInterface;
-use Magento\MediaGallerySynchronization\Model\Filesystem\SplFileInfoFactory;
+use Magento\MediaGallerySynchronization\Model\Filesystem\GetFileInfo;
use Psr\Log\LoggerInterface;
/**
@@ -50,9 +50,9 @@ class SynchronizeFiles implements SynchronizeFilesInterface
private $driver;
/**
- * @var SplFileInfoFactory
+ * @var GetFileInfo
*/
- private $splFileInfoFactory;
+ private $getFileInfo;
/**
* @var ImportFilesInterface
@@ -69,7 +69,7 @@ class SynchronizeFiles implements SynchronizeFilesInterface
* @param Filesystem $filesystem
* @param DateTime $date
* @param LoggerInterface $log
- * @param SplFileInfoFactory $splFileInfoFactory
+ * @param GetFileInfo $getFileInfo
* @param GetAssetsByPathsInterface $getAssetsByPaths
* @param ImportFilesInterface $importFiles
*/
@@ -78,7 +78,7 @@ public function __construct(
Filesystem $filesystem,
DateTime $date,
LoggerInterface $log,
- SplFileInfoFactory $splFileInfoFactory,
+ GetFileInfo $getFileInfo,
GetAssetsByPathsInterface $getAssetsByPaths,
ImportFilesInterface $importFiles
) {
@@ -86,7 +86,7 @@ public function __construct(
$this->filesystem = $filesystem;
$this->date = $date;
$this->log = $log;
- $this->splFileInfoFactory = $splFileInfoFactory;
+ $this->getFileInfo = $getFileInfo;
$this->getAssetsByPaths = $getAssetsByPaths;
$this->importFiles = $importFiles;
}
@@ -150,7 +150,7 @@ private function getFileModificationTime(string $path): string
{
return $this->date->gmtDate(
self::DATE_FORMAT,
- $this->splFileInfoFactory->create($this->getMediaDirectory()->getAbsolutePath($path))->getMTime()
+ $this->getFileInfo->execute($this->getMediaDirectory()->getAbsolutePath($path))->getMTime()
);
}
diff --git a/app/code/Magento/MediaGallerySynchronization/Test/Integration/Model/Filesystem/GetFileInfoTest.php b/app/code/Magento/MediaGallerySynchronization/Test/Integration/Model/Filesystem/GetFileInfoTest.php
new file mode 100644
index 0000000000000..6b1e8a676d02b
--- /dev/null
+++ b/app/code/Magento/MediaGallerySynchronization/Test/Integration/Model/Filesystem/GetFileInfoTest.php
@@ -0,0 +1,89 @@
+getFileInfo = Bootstrap::getObjectManager()->get(GetFileInfo::class);
+ }
+
+ /**
+ * @dataProvider filesProvider
+ * @param string $file
+ */
+ public function testExecute(
+ string $file
+ ): void {
+
+ $path = $this->getImageFilePath($file);
+
+ $fileInfo = $this->getFileInfo->execute($path);
+ $expectedResult = new \SplFileInfo($path);
+ $this->assertEquals($expectedResult->getPath(), $fileInfo->getPath());
+ $this->assertEquals($expectedResult->getFilename(), $fileInfo->getFilename());
+ $this->assertEquals($expectedResult->getExtension(), $fileInfo->getExtension());
+ $this->assertEquals(
+ $expectedResult->getBasename('.' . $expectedResult->getExtension()),
+ $fileInfo->getBasename()
+ );
+ $this->assertEquals($expectedResult->getSize(), $fileInfo->getSize());
+ $this->assertEquals($expectedResult->getMTime(), $fileInfo->getMTime());
+ $this->assertEquals($expectedResult->getCTime(), $fileInfo->getCTime());
+ }
+
+ /**
+ * Data provider for testExecute
+ *
+ * @return array[]
+ */
+ public function filesProvider(): array
+ {
+ return [
+ [
+ 'magento.jpg',
+ 'magento_2.jpg'
+ ]
+ ];
+ }
+
+ /**
+ * Return image file path
+ *
+ * @param string $filename
+ * @return string
+ */
+ private function getImageFilePath(string $filename): string
+ {
+ return dirname(__DIR__, 2)
+ . DIRECTORY_SEPARATOR
+ . implode(
+ DIRECTORY_SEPARATOR,
+ [
+ '_files',
+ $filename
+ ]
+ );
+ }
+}
diff --git a/app/code/Magento/MediaGalleryUi/Controller/Adminhtml/Asset/Search.php b/app/code/Magento/MediaGalleryUi/Controller/Adminhtml/Asset/Search.php
index df13250eacb5f..9b6c08edbc86d 100644
--- a/app/code/Magento/MediaGalleryUi/Controller/Adminhtml/Asset/Search.php
+++ b/app/code/Magento/MediaGalleryUi/Controller/Adminhtml/Asset/Search.php
@@ -139,7 +139,7 @@ public function execute()
$responseContent['options'][] = [
'value' => (string) $asset->getId(),
'label' => $asset->getTitle(),
- 'path' => $this->storage->getThumbnailUrl($this->images->getStorageRoot() . $asset->getPath())
+ 'src' => $this->storage->getThumbnailUrl($this->images->getStorageRoot() . $asset->getPath())
];
$responseContent['total'] = count($responseContent['options']);
}
diff --git a/app/code/Magento/MediaGalleryUi/Model/Config/MediaGallery/Yesno.php b/app/code/Magento/MediaGalleryUi/Model/Config/MediaGallery/Yesno.php
new file mode 100644
index 0000000000000..40cf7630d9911
--- /dev/null
+++ b/app/code/Magento/MediaGalleryUi/Model/Config/MediaGallery/Yesno.php
@@ -0,0 +1,21 @@
+ 0, 'label' => __('Yes')], ['value' => 1, 'label' => __('No')]];
+ }
+}
diff --git a/app/code/Magento/MediaGalleryUi/Model/UpdateAsset.php b/app/code/Magento/MediaGalleryUi/Model/UpdateAsset.php
index ff82b990d2a01..85522c6b07e00 100644
--- a/app/code/Magento/MediaGalleryUi/Model/UpdateAsset.php
+++ b/app/code/Magento/MediaGalleryUi/Model/UpdateAsset.php
@@ -76,18 +76,16 @@ public function execute(int $id, MetadataInterface $data): void
$updatedAsset = $this->assetFactory->create(
[
+ 'id' => $asset->getId(),
'path' => $asset->getPath(),
- 'contentType' => $asset->getContentType(),
+ 'title' => $data->getTitle() ?? $asset->getTitle(),
+ 'description' => $data->getDescription() ?? $asset->getDescription(),
'width' => $asset->getWidth(),
'height' => $asset->getHeight(),
'size' => $asset->getSize(),
- 'id' => $asset->getId(),
- 'title' => $data->getTitle() ?? $asset->getTitle(),
- 'description' => $data->getDescription() ?? $asset->getDescription(),
- 'source' => $asset->getSource(),
'hash' => $asset->getHash(),
- 'created_at' => $asset->getCreatedAt(),
- 'updated_at' => $asset->getUpdatedAt()
+ 'contentType' => $asset->getContentType(),
+ 'source' => $asset->getSource()
]
);
diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminAssertMediaGalleryFilterPlaceholderActionGroup.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminAssertMediaGalleryFilterPlaceholderActionGroup.xml
new file mode 100644
index 0000000000000..db400ff151ae3
--- /dev/null
+++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminAssertMediaGalleryFilterPlaceholderActionGroup.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+ Assert asset filter placeholder value
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminMediaGalleryEditAssetRemoveKeywordActionGroup.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminMediaGalleryEditAssetRemoveKeywordActionGroup.xml
new file mode 100644
index 0000000000000..b2ce726b3bd6c
--- /dev/null
+++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminMediaGalleryEditAssetRemoveKeywordActionGroup.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+ Remove Keywords on the Edit Details panel
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AssertAdminEnhancedMediaGalleryImageCreatedAtNotEqualsUpdatedAtTimeActionGroup.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AssertAdminEnhancedMediaGalleryImageCreatedAtNotEqualsUpdatedAtTimeActionGroup.xml
new file mode 100644
index 0000000000000..9460d0b339ca4
--- /dev/null
+++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AssertAdminEnhancedMediaGalleryImageCreatedAtNotEqualsUpdatedAtTimeActionGroup.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+ Assert that created_at updated_at time NOT equals
+
+
+
+
+
+ grabCreatedTime
+ grabModifietTime
+
+
+
+
diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AssertAdminEnhancedMediaGalleryUploadedImageDateTimeEqualsActionGroup.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AssertAdminEnhancedMediaGalleryUploadedImageDateTimeEqualsActionGroup.xml
new file mode 100644
index 0000000000000..076885ddaf8b6
--- /dev/null
+++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AssertAdminEnhancedMediaGalleryUploadedImageDateTimeEqualsActionGroup.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+ Assert that created_at updated_at time are the same for newly uploaded image
+
+
+
+
+
+ grabCreatedTime
+ grabModifietTime
+
+
+
+
diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AssetAdminEnhancedMediaGalleryAssetDetailsKeywordsAbsentActionGroup.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AssetAdminEnhancedMediaGalleryAssetDetailsKeywordsAbsentActionGroup.xml
new file mode 100644
index 0000000000000..be9c7e939103d
--- /dev/null
+++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AssetAdminEnhancedMediaGalleryAssetDetailsKeywordsAbsentActionGroup.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+ Verifies that the passed comma-separated list of keywords are not present on the View Details panel
+
+
+
+
+
+
+
+ grabKeywords
+ {{keywords}}
+
+
+
diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryEditDetailsSection.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryEditDetailsSection.xml
index b8e2f698ccfe8..b0bed4563003e 100644
--- a/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryEditDetailsSection.xml
+++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryEditDetailsSection.xml
@@ -14,6 +14,7 @@
+
diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryFiltersSection.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryFiltersSection.xml
index 32b109f1e0483..da9f773d0f75e 100644
--- a/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryFiltersSection.xml
+++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryFiltersSection.xml
@@ -25,5 +25,6 @@
+
diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryViewDetailsSection.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryViewDetailsSection.xml
index 048739ed3f81d..e63429677fbae 100644
--- a/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryViewDetailsSection.xml
+++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryViewDetailsSection.xml
@@ -18,6 +18,8 @@
+
+
diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/Test/AdminEnhancedMediaGalleryVerifyUpdatedTagsTest.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/Test/AdminEnhancedMediaGalleryVerifyUpdatedTagsTest.xml
new file mode 100644
index 0000000000000..f47d6d9202c05
--- /dev/null
+++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/Test/AdminEnhancedMediaGalleryVerifyUpdatedTagsTest.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/Test/AdminStandaloneMediaGalleryEditImageDetailsTest.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/Test/AdminStandaloneMediaGalleryEditImageDetailsTest.xml
index ede3a452e4ca5..58c6f32b8d72f 100644
--- a/app/code/Magento/MediaGalleryUi/Test/Mftf/Test/AdminStandaloneMediaGalleryEditImageDetailsTest.xml
+++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/Test/AdminStandaloneMediaGalleryEditImageDetailsTest.xml
@@ -29,6 +29,10 @@
+
+
+
+
@@ -40,6 +44,7 @@
+
diff --git a/app/code/Magento/MediaGalleryUi/Ui/Component/Listing/Filters/Asset.php b/app/code/Magento/MediaGalleryUi/Ui/Component/Listing/Filters/Asset.php
index 273cf9e37554b..e8dc232584adb 100644
--- a/app/code/Magento/MediaGalleryUi/Ui/Component/Listing/Filters/Asset.php
+++ b/app/code/Magento/MediaGalleryUi/Ui/Component/Listing/Filters/Asset.php
@@ -15,9 +15,13 @@
use Magento\MediaContentApi\Api\GetContentByAssetIdsInterface;
use Magento\Ui\Component\Filters\FilterModifier;
use Magento\Ui\Component\Filters\Type\Select;
+use Magento\MediaGalleryApi\Api\GetAssetsByIdsInterface;
+use Magento\Cms\Helper\Wysiwyg\Images;
+use Magento\Cms\Model\Wysiwyg\Images\Storage;
+use Magento\Ui\Api\BookmarkManagementInterface;
/**
- * Asset filter
+ * Asset filter
*/
class Asset extends Select
{
@@ -27,14 +31,41 @@ class Asset extends Select
private $getContentIdentities;
/**
+ * @var GetAssetsByIdsInterface
+ */
+ private $getAssetsByIds;
+
+ /**
+ * @var Images
+ */
+ private $images;
+
+ /**
+ * @var Storage
+ */
+ private $storage;
+
+ /**
+ * @var BookmarkManagementInterface
+ */
+ private $bookmarkManagement;
+
+ /**
+ * Constructor
+ *
* @param ContextInterface $context
* @param UiComponentFactory $uiComponentFactory
* @param FilterBuilder $filterBuilder
* @param FilterModifier $filterModifier
* @param OptionSourceInterface $optionsProvider
* @param GetContentByAssetIdsInterface $getContentIdentities
+ * @param GetAssetsByIdsInterface $getAssetsByIds
+ * @param BookmarkManagementInterface $bookmarkManagement
+ * @param Images $images
+ * @param Storage $storage
* @param array $components
* @param array $data
+ * @SuppressWarnings(PHPMD.ExcessiveParameterList)
*/
public function __construct(
ContextInterface $context,
@@ -43,6 +74,10 @@ public function __construct(
FilterModifier $filterModifier,
OptionSourceInterface $optionsProvider = null,
GetContentByAssetIdsInterface $getContentIdentities,
+ GetAssetsByIdsInterface $getAssetsByIds,
+ BookmarkManagementInterface $bookmarkManagement,
+ Images $images,
+ Storage $storage,
array $components = [],
array $data = []
) {
@@ -58,6 +93,89 @@ public function __construct(
$data
);
$this->getContentIdentities = $getContentIdentities;
+ $this->getAssetsByIds = $getAssetsByIds;
+ $this->bookmarkManagement = $bookmarkManagement;
+ $this->images = $images;
+ $this->storage = $storage;
+ }
+
+ /**
+ * Prepare component configuration
+ *
+ * @return void
+ */
+ public function prepare()
+ {
+ $options = [];
+ $assetIds = $this->getAssetIds();
+
+ if (empty($assetIds)) {
+ parent::prepare();
+ return;
+ }
+
+ $assets = $this->getAssetsByIds->execute($assetIds);
+
+ foreach ($assets as $asset) {
+ $assetPath = $this->storage->getThumbnailUrl($this->images->getStorageRoot() . $asset->getPath());
+ $options[] = [
+ 'value' => (string) $asset->getId(),
+ 'label' => $asset->getTitle(),
+ 'src' => $assetPath
+ ];
+ }
+
+ $this->optionsProvider = $options;
+ parent::prepare();
+ }
+
+ /**
+ * Get asset ids from filterData or from bookmarks
+ */
+ private function getAssetIds(): array
+ {
+ $assetIds = [];
+
+ if (isset($this->filterData[$this->getName()])) {
+ $assetIds = $this->filterData[$this->getName()];
+
+ if (!is_array($assetIds)) {
+ $assetIds = $this->stringToArray($assetIds);
+ }
+
+ return $assetIds;
+ }
+
+ $bookmark = $this->bookmarkManagement->getByIdentifierNamespace(
+ 'current',
+ $this->context->getNameSpace()
+ );
+
+ if ($bookmark === null) {
+ return $assetIds;
+ }
+
+ $applied = $bookmark->getConfig()['current']['filters']['applied'];
+
+ if (isset($applied[$this->getName()])) {
+ $assetIds = $applied[$this->getName()];
+ }
+
+ if (!is_array($assetIds)) {
+ $assetIds = $this->stringToArray($assetIds);
+ }
+
+ return $assetIds;
+ }
+
+ /**
+ * Converts string array from url-applier to array
+ *
+ * @param string $string
+ */
+ private function stringToArray(string $string): array
+ {
+ return explode(',', str_replace(['[', ']'], '', $string));
}
/**
@@ -67,17 +185,20 @@ public function __construct(
*/
public function applyFilter()
{
- if (isset($this->filterData[$this->getName()])) {
- $ids = is_array($this->filterData[$this->getName()])
- ? $this->filterData[$this->getName()]
- : [$this->filterData[$this->getName()]];
- $filter = $this->filterBuilder->setConditionType('in')
- ->setField($this->_data['config']['identityColumn'])
- ->setValue($this->getEntityIdsByAsset($ids))
- ->create();
-
- $this->getContext()->getDataProvider()->addFilter($filter);
+ if (!isset($this->filterData[$this->getName()])) {
+ return;
}
+
+ $assetIds = $this->filterData[$this->getName()];
+ if (!is_array($assetIds)) {
+ $assetIds = $this->stringToArray($assetIds);
+ }
+
+ $filter = $this->filterBuilder->setConditionType('in')
+ ->setField($this->_data['config']['identityColumn'])
+ ->setValue($this->getEntityIdsByAsset($assetIds))
+ ->create();
+ $this->getContext()->getDataProvider()->addFilter($filter);
}
/**
diff --git a/app/code/Magento/MediaGalleryUi/etc/adminhtml/system.xml b/app/code/Magento/MediaGalleryUi/etc/adminhtml/system.xml
index 77544b42e899a..17aa08b5363ca 100644
--- a/app/code/Magento/MediaGalleryUi/etc/adminhtml/system.xml
+++ b/app/code/Magento/MediaGalleryUi/etc/adminhtml/system.xml
@@ -9,10 +9,10 @@
- Enhanced Media Gallery
+ Media Gallery
- Enabled
- Magento\Config\Model\Config\Source\Yesno
+ Enable Old Media Gallery
+ Magento\MediaGalleryUi\Model\Config\MediaGallery\Yesno
system/media_gallery/enabled
diff --git a/app/code/Magento/MediaGalleryUi/view/adminhtml/web/js/image/image-actions.js b/app/code/Magento/MediaGalleryUi/view/adminhtml/web/js/image/image-actions.js
index c7ca95bed863c..ea4de9e1feefa 100644
--- a/app/code/Magento/MediaGalleryUi/view/adminhtml/web/js/image/image-actions.js
+++ b/app/code/Magento/MediaGalleryUi/view/adminhtml/web/js/image/image-actions.js
@@ -51,6 +51,7 @@ define([
return;
}
+ this.mediaGalleryEditDetails().keywordsSelect().cacheOptions.plain = [];
modalElement.modal('closeModal');
},
@@ -86,7 +87,8 @@ define([
form = modalElement.find('#image-edit-details-form'),
imageId = this.imageModel().getSelected().id,
keywords = this.mediaGalleryEditDetails().selectedKeywords(),
- imageDetails = this.mediaGalleryImageDetails();
+ imageDetails = this.mediaGalleryImageDetails(),
+ imageEditDetails = this.mediaGalleryEditDetails();
if (form.validation('isValid')) {
saveDetails(
@@ -98,6 +100,7 @@ define([
this.closeModal();
this.imageModel().reloadGrid();
imageDetails.removeCached(imageId);
+ imageEditDetails.removeCached(imageId);
if (imageDetails.isActive()) {
imageDetails.showImageDetailsById(imageId);
diff --git a/app/code/Magento/MediaGalleryUi/view/adminhtml/web/js/image/image-edit.js b/app/code/Magento/MediaGalleryUi/view/adminhtml/web/js/image/image-edit.js
index c31bc848bdc70..e1404a16d7125 100644
--- a/app/code/Magento/MediaGalleryUi/view/adminhtml/web/js/image/image-edit.js
+++ b/app/code/Magento/MediaGalleryUi/view/adminhtml/web/js/image/image-edit.js
@@ -223,6 +223,15 @@ define([
}
return true;
+ },
+
+ /**
+ * Remove cached image details in edit form
+ *
+ * @param {String} id
+ */
+ removeCached: function (id) {
+ delete this.images[id];
}
});
});
diff --git a/app/code/Magento/MediaGalleryUi/view/adminhtml/web/template/grid/filters/elements/ui-select.html b/app/code/Magento/MediaGalleryUi/view/adminhtml/web/template/grid/filters/elements/ui-select.html
index cce859f331d9a..a0d21672eafdb 100644
--- a/app/code/Magento/MediaGalleryUi/view/adminhtml/web/template/grid/filters/elements/ui-select.html
+++ b/app/code/Magento/MediaGalleryUi/view/adminhtml/web/template/grid/filters/elements/ui-select.html
@@ -77,8 +77,7 @@
+
+
+
+ - web/url/use_store
+
+
+
+
+
+
diff --git a/app/code/Magento/StoreGraphQl/etc/schema.graphqls b/app/code/Magento/StoreGraphQl/etc/schema.graphqls
index d85bac7801f39..1106987cc72c1 100644
--- a/app/code/Magento/StoreGraphQl/etc/schema.graphqls
+++ b/app/code/Magento/StoreGraphQl/etc/schema.graphqls
@@ -2,7 +2,9 @@
# See COPYING.txt for license details.
type Query {
storeConfig : StoreConfig @resolver(class: "Magento\\StoreGraphQl\\Model\\Resolver\\StoreConfigResolver") @doc(description: "The store config query") @cache(cacheable: false)
- availableStores: [StoreConfig] @resolver(class: "Magento\\StoreGraphQl\\Model\\Resolver\\AvailableStoresResolver") @doc(description: "Get a list of available store views and their config information.")
+ availableStores(
+ useCurrentGroup: Boolean @doc(description: "Filter store views by current store group")
+ ): [StoreConfig] @resolver(class: "Magento\\StoreGraphQl\\Model\\Resolver\\AvailableStoresResolver") @doc(description: "Get a list of available store views and their config information.")
}
type Website @doc(description: "Website is deprecated because it is should not be used on storefront. The type contains information about a website") {
@@ -32,4 +34,5 @@ type StoreConfig @doc(description: "The type contains information about a store
secure_base_static_url : String @doc(description: "Secure base static URL for the store")
secure_base_media_url : String @doc(description: "Secure base media URL for the store")
store_name : String @doc(description: "Name of the store")
+ use_store_in_url: Boolean @doc(description: "The configuration determines if the store code should be used in the URL")
}
diff --git a/app/code/Magento/Ui/Component/Form/Element/DataType/Media/OpenDialogUrl.php b/app/code/Magento/Ui/Component/Form/Element/DataType/Media/OpenDialogUrl.php
index 27370cbfbd68c..9961fc41fc70d 100644
--- a/app/code/Magento/Ui/Component/Form/Element/DataType/Media/OpenDialogUrl.php
+++ b/app/code/Magento/Ui/Component/Form/Element/DataType/Media/OpenDialogUrl.php
@@ -8,10 +8,8 @@
namespace Magento\Ui\Component\Form\Element\DataType\Media;
-use Magento\Framework\DataObject;
-
/**
- * Basic configuration for OdenDialogUrl
+ * Basic configuration for OpenDialogUrl
*/
class OpenDialogUrl
{
@@ -23,11 +21,11 @@ class OpenDialogUrl
private $openDialogUrl;
/**
- * @param DataObject $url
+ * @param string $url
*/
- public function __construct(DataObject $url = null)
+ public function __construct(string $url = null)
{
- $this->openDialogUrl = $url;
+ $this->openDialogUrl = $url ?? self::DEFAULT_OPEN_DIALOG_URL;
}
/**
@@ -37,9 +35,6 @@ public function __construct(DataObject $url = null)
*/
public function get(): string
{
- if ($this->openDialogUrl) {
- return $this->openDialogUrl->getUrl();
- }
- return self::DEFAULT_OPEN_DIALOG_URL;
+ return $this->openDialogUrl;
}
}
diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_checkout-agreements.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_checkout-agreements.less
index ff4f07a983940..b8be2b33a4475 100644
--- a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_checkout-agreements.less
+++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_checkout-agreements.less
@@ -13,6 +13,30 @@
margin-bottom: @indent__base;
}
+ .checkout-agreement.field {
+ .lib-vendor-prefix-display();
+
+ &.required {
+ label:after {
+ content: none;
+ }
+
+ .action-show {
+ &:after {
+ content: '*';
+ .lib-typography(
+ @_font-size: @form-field-label-asterisk__font-size,
+ @_color: @form-field-label-asterisk__color,
+ @_font-family: @form-field-label-asterisk__font-family,
+ @_font-weight: @form-field-label-asterisk__font-weight,
+ @_line-height: @form-field-label-asterisk__line-height,
+ @_font-style: @form-field-label-asterisk__font-style
+ );
+ }
+ }
+ }
+ }
+
.action-show {
&:extend(.abs-action-button-as-link all);
vertical-align: baseline;
diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/Helper/CompareArraysRecursively.php b/dev/tests/api-functional/framework/Magento/TestFramework/Helper/CompareArraysRecursively.php
new file mode 100644
index 0000000000000..d8a88c721c9fe
--- /dev/null
+++ b/dev/tests/api-functional/framework/Magento/TestFramework/Helper/CompareArraysRecursively.php
@@ -0,0 +1,70 @@
+ [
+ * 'items' => [
+ * [
+ * 'sku' => 'bundle-product',
+ * 'type_id' => 'bundle',
+ * 'items' => [
+ * [
+ * 'title' => 'Bundle Product Items',
+ * 'sku' => 'bundle-product',
+ * 'options' => [
+ * [
+ * 'price' => 2.75,
+ * 'label' => 'Simple Product',
+ * 'product' => [
+ * 'name' => 'Simple Product',
+ * 'sku' => 'simple',
+ * ]
+ * ]
+ * ]
+ * ]
+ * ];
+ * ```
+ *
+ * @param array $expected
+ * @param array $actual
+ * @return array
+ */
+ public function execute(array $expected, array $actual): array
+ {
+ $diffResult = [];
+
+ foreach ($expected as $key => $value) {
+ if (array_key_exists($key, $actual)) {
+ if (is_array($value)) {
+ $recursiveDiff = $this->execute($value, $actual[$key]);
+ if (!empty($recursiveDiff)) {
+ $diffResult[$key] = $recursiveDiff;
+ }
+ } else {
+ if (!in_array($value, $actual, true)) {
+ $diffResult[$key] = $value;
+ }
+ }
+ } else {
+ $diffResult[$key] = $value;
+ }
+ }
+
+ return $diffResult;
+ }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CategoryManagementTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CategoryManagementTest.php
index bc3869df6a65b..1523bfe957901 100644
--- a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CategoryManagementTest.php
+++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CategoryManagementTest.php
@@ -9,6 +9,7 @@
use Magento\TestFramework\TestCase\WebapiAbstract;
use Magento\TestFramework\Helper\Bootstrap;
+use Magento\TestFramework\Helper\CompareArraysRecursively;
/**
* Tests CategoryManagement
@@ -19,6 +20,20 @@ class CategoryManagementTest extends WebapiAbstract
const SERVICE_NAME = 'catalogCategoryManagementV1';
+ /**
+ * @var CompareArraysRecursively
+ */
+ private $compareArraysRecursively;
+
+ /**
+ * @inheritDoc
+ */
+ protected function setUp(): void
+ {
+ $objectManager = Bootstrap::getObjectManager();
+ $this->compareArraysRecursively = $objectManager->create(CompareArraysRecursively::class);
+ }
+
/**
* Tests getTree operation
*
@@ -40,8 +55,8 @@ public function testTree($rootCategoryId, $depth, $expected)
]
];
$result = $this->_webApiCall($serviceInfo, $requestData);
- $expected = array_replace_recursive($result, $expected);
- $this->assertEquals($expected, $result);
+ $diff = $this->compareArraysRecursively->execute($expected, $result);
+ self::assertEquals([], $diff, "Actual categories response doesn't equal expected data");
}
/**
diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Store/AvailableStoreConfigTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Store/AvailableStoreConfigTest.php
index eaf76e4559557..d762462729234 100644
--- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Store/AvailableStoreConfigTest.php
+++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Store/AvailableStoreConfigTest.php
@@ -87,6 +87,7 @@ public function testDefaultWebsiteAvailableStoreConfigs(): void
secure_base_static_url,
secure_base_media_url,
store_name
+ use_store_in_url
}
}
QUERY;
@@ -126,6 +127,7 @@ public function testNonDefaultWebsiteAvailableStoreConfigs(): void
secure_base_static_url,
secure_base_media_url,
store_name
+ use_store_in_url
}
}
QUERY;
@@ -167,5 +169,99 @@ private function validateStoreConfig(StoreConfigInterface $storeConfig, array $r
$this->assertEquals($storeConfig->getSecureBaseStaticUrl(), $responseConfig['secure_base_static_url']);
$this->assertEquals($storeConfig->getSecureBaseMediaUrl(), $responseConfig['secure_base_media_url']);
$this->assertEquals($store->getName(), $responseConfig['store_name']);
+ $this->assertEquals($store->isUseStoreInUrl(), $responseConfig['use_store_in_url']);
+ }
+
+ /**
+ * @magentoApiDataFixture Magento/Store/_files/second_website_with_four_stores_divided_in_groups.php
+ * @magentoConfigFixture web/url/use_store 1
+ */
+ public function testAllStoreConfigsWithCodeInUrlEnabled(): void
+ {
+ $storeConfigs = $this->storeConfigManager->getStoreConfigs(
+ [
+ 'fixture_second_store',
+ 'fixture_third_store',
+ 'fixture_fourth_store',
+ 'fixture_fifth_store'
+ ]
+ );
+
+ $query
+ = << 'fixture_fifth_store'];
+ $response = $this->graphQlQuery($query, [], '', $headerMap);
+
+ $this->assertArrayHasKey('availableStores', $response);
+ $this->assertCount(4, $response['availableStores']);
+ foreach ($response['availableStores'] as $key => $responseConfig) {
+ $this->validateStoreConfig($storeConfigs[$key], $responseConfig);
+ $this->assertEquals(true, $responseConfig['use_store_in_url']);
+ }
+ }
+
+ /**
+ * @magentoApiDataFixture Magento/Store/_files/second_website_with_four_stores_divided_in_groups.php
+ */
+ public function testCurrentGroupStoreConfigs(): void
+ {
+ $storeConfigs = $this->storeConfigManager->getStoreConfigs(['fixture_fourth_store', 'fixture_fifth_store']);
+
+ $query
+ = << 'fixture_fifth_store'];
+ $response = $this->graphQlQuery($query, [], '', $headerMap);
+
+ $this->assertArrayHasKey('availableStores', $response);
+ $this->assertCount(2, $response['availableStores']);
+ foreach ($response['availableStores'] as $key => $responseConfig) {
+ $this->validateStoreConfig($storeConfigs[$key], $responseConfig);
+ }
}
}
diff --git a/dev/tests/integration/framework/Magento/TestFramework/Annotation/ConfigFixture.php b/dev/tests/integration/framework/Magento/TestFramework/Annotation/ConfigFixture.php
index 48b27c83ee6e3..dc3971d1896a1 100644
--- a/dev/tests/integration/framework/Magento/TestFramework/Annotation/ConfigFixture.php
+++ b/dev/tests/integration/framework/Magento/TestFramework/Annotation/ConfigFixture.php
@@ -158,9 +158,9 @@ protected function _assignConfigData(TestCase $test)
self::ANNOTATION
);
foreach ($testAnnotations as $configPathAndValue) {
- if (preg_match('/^.+?(?=_store\s)/', $configPathAndValue, $matches)) {
+ if (preg_match('/^[^\/]+?(?=_store\s)/', $configPathAndValue, $matches)) {
$this->setStoreConfigValue($matches ?? [], $configPathAndValue);
- } elseif (preg_match('/^.+?(?=_website\s)/', $configPathAndValue, $matches)) {
+ } elseif (preg_match('/^[^\/]+?(?=_website\s)/', $configPathAndValue, $matches)) {
$this->setWebsiteConfigValue($matches ?? [], $configPathAndValue);
} else {
$this->setGlobalConfigValue($configPathAndValue);
diff --git a/dev/tests/integration/testsuite/Magento/CustomerGraphQl/Model/Resolver/CreateCustomerTest.php b/dev/tests/integration/testsuite/Magento/CustomerGraphQl/Model/Resolver/CreateCustomerTest.php
new file mode 100644
index 0000000000000..11ac2695bd80c
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/CustomerGraphQl/Model/Resolver/CreateCustomerTest.php
@@ -0,0 +1,238 @@
+objectManager = Bootstrap::getObjectManager();
+ $this->graphQlRequest = $this->objectManager->create(GraphQlRequest::class);
+ $this->json = $this->objectManager->get(SerializerInterface::class);
+
+ $this->customerRepository = $this->objectManager->create(CustomerRepositoryInterface::class);
+ $this->storeRepository = $this->objectManager->create(StoreRepositoryInterface::class);
+ }
+
+ /**
+ * Test that creating a customer sends an email
+ */
+ public function testCreateCustomerSendsEmail()
+ {
+ $query
+ = <<graphQlRequest->send($query);
+ $responseData = $this->json->unserialize($response->getContent());
+
+ // Assert the response of the GraphQL request
+ $this->assertNull($responseData['data']['createCustomer']['customer']['id']);
+
+ // Verify the customer was created and has the correct data
+ $customer = $this->customerRepository->get('test@magento.com');
+ $this->assertEquals('Test', $customer->getFirstname());
+ $this->assertEquals('Magento', $customer->getLastname());
+
+ /** @var TransportBuilderMock $transportBuilderMock */
+ $transportBuilderMock = $this->objectManager->get(TransportBuilderMock::class);
+ $sentMessage = $transportBuilderMock->getSentMessage();
+
+ // Verify an email was dispatched to the correct user
+ $this->assertNotNull($sentMessage);
+ $this->assertEquals('Test Magento', $sentMessage->getTo()[0]->getName());
+ $this->assertEquals('test@magento.com', $sentMessage->getTo()[0]->getEmail());
+
+ // Assert the email contains the expected content
+ $this->assertEquals('Welcome to Main Website Store', $sentMessage->getSubject());
+ $messageRaw = $sentMessage->getBody()->getParts()[0]->getRawContent();
+ $this->assertStringContainsString('Welcome to Main Website Store.', $messageRaw);
+ }
+
+ /**
+ * Test that creating a customer on an alternative store sends an email
+ *
+ * @magentoDataFixture Magento/CustomerGraphQl/_files/website_store_with_store_view.php
+ */
+ public function testCreateCustomerForStoreSendsEmail()
+ {
+ $query
+ = <<graphQlRequest->send(
+ $query,
+ [],
+ '',
+ [
+ 'Store' => 'test_store_view'
+ ]
+ );
+ $responseData = $this->json->unserialize($response->getContent());
+
+ // Assert the response of the GraphQL request
+ $this->assertNull($responseData['data']['createCustomer']['customer']['id']);
+
+ // Verify the customer was created and has the correct data
+ $customer = $this->customerRepository->get('test@magento.com');
+ $this->assertEquals('Test', $customer->getFirstname());
+ $this->assertEquals('Magento', $customer->getLastname());
+ $this->assertEquals('Test Store View', $customer->getCreatedIn());
+
+ $store = $this->storeRepository->getById($customer->getStoreId());
+ $this->assertEquals('test_store_view', $store->getCode());
+
+ /** @var TransportBuilderMock $transportBuilderMock */
+ $transportBuilderMock = $this->objectManager->get(TransportBuilderMock::class);
+ $sentMessage = $transportBuilderMock->getSentMessage();
+
+ // Verify an email was dispatched to the correct user
+ $this->assertNotNull($sentMessage);
+ $this->assertEquals('Test Magento', $sentMessage->getTo()[0]->getName());
+ $this->assertEquals('test@magento.com', $sentMessage->getTo()[0]->getEmail());
+
+ // Assert the email contains the expected content
+ $this->assertEquals('Welcome to Test Group', $sentMessage->getSubject());
+ $messageRaw = $sentMessage->getBody()->getParts()[0]->getRawContent();
+ $this->assertStringContainsString('Welcome to Test Group.', $messageRaw);
+ }
+
+ /**
+ * Test that creating a customer on an alternative store sends an email in the translated language
+ *
+ * @magentoDataFixture Magento/CustomerGraphQl/_files/website_store_with_store_view.php
+ * @magentoConfigFixture test_store_view_store general/locale/code fr_FR
+ * @magentoComponentsDir Magento/CustomerGraphQl/_files
+ */
+ public function testCreateCustomerForStoreSendsTranslatedEmail()
+ {
+ $query
+ = <<graphQlRequest->send(
+ $query,
+ [],
+ '',
+ [
+ 'Store' => 'test_store_view'
+ ]
+ );
+ $responseData = $this->json->unserialize($response->getContent());
+
+ // Assert the response of the GraphQL request
+ $this->assertNull($responseData['data']['createCustomer']['customer']['id']);
+
+ // Verify the customer was created and has the correct data
+ $customer = $this->customerRepository->get('test@magento.com');
+ $this->assertEquals('Test', $customer->getFirstname());
+ $this->assertEquals('Magento', $customer->getLastname());
+ $this->assertEquals('Test Store View', $customer->getCreatedIn());
+
+ $store = $this->storeRepository->getById($customer->getStoreId());
+ $this->assertEquals('test_store_view', $store->getCode());
+
+ /** @var TransportBuilderMock $transportBuilderMock */
+ $transportBuilderMock = $this->objectManager->get(TransportBuilderMock::class);
+ $sentMessage = $transportBuilderMock->getSentMessage();
+
+ // Verify an email was dispatched to the correct user
+ $this->assertNotNull($sentMessage);
+ $this->assertEquals('Test Magento', $sentMessage->getTo()[0]->getName());
+ $this->assertEquals('test@magento.com', $sentMessage->getTo()[0]->getEmail());
+
+ // Assert the email contains the expected content
+ $this->assertEquals('Bienvenue sur Test Group', $sentMessage->getSubject());
+ $messageRaw = $sentMessage->getBody()->getParts()[0]->getRawContent();
+ $this->assertStringContainsString('Bienvenue sur Test Group.', $messageRaw);
+ }
+}
diff --git a/dev/tests/integration/testsuite/Magento/CustomerGraphQl/_files/french/fr_fr/1.csv b/dev/tests/integration/testsuite/Magento/CustomerGraphQl/_files/french/fr_fr/1.csv
new file mode 100644
index 0000000000000..4d4f9c48f7d40
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/CustomerGraphQl/_files/french/fr_fr/1.csv
@@ -0,0 +1,2 @@
+"Welcome to %store_name","Bienvenue sur %store_name"
+"Welcome to %store_name.","Bienvenue sur %store_name."
diff --git a/dev/tests/integration/testsuite/Magento/CustomerGraphQl/_files/french/fr_fr/language.xml b/dev/tests/integration/testsuite/Magento/CustomerGraphQl/_files/french/fr_fr/language.xml
new file mode 100644
index 0000000000000..9926a71910ebe
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/CustomerGraphQl/_files/french/fr_fr/language.xml
@@ -0,0 +1,13 @@
+
+
+
+ fr_FR
+ french
+ fr_fr
+ 0
+
diff --git a/dev/tests/integration/testsuite/Magento/CustomerGraphQl/_files/french/fr_fr/registration.php b/dev/tests/integration/testsuite/Magento/CustomerGraphQl/_files/french/fr_fr/registration.php
new file mode 100644
index 0000000000000..95acf0c1487c7
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/CustomerGraphQl/_files/french/fr_fr/registration.php
@@ -0,0 +1,9 @@
+get(StoreManagerInterface::class);
+/** @var WebsiteResource $websiteResource */
+$websiteResource = $objectManager->get(WebsiteResource::class);
+/** @var StoreResource $storeResource */
+$storeResource = $objectManager->get(StoreResource::class);
+/** @var GroupResource $groupResource */
+$groupResource = $objectManager->get(GroupResource::class);
+/** @var WebsiteInterface $website */
+$website = $objectManager->get(WebsiteInterfaceFactory::class)->create();
+$website->setCode('test_website')->setName('Test Website');
+$websiteResource->save($website);
+/** @var GroupInterface $storeGroup */
+$storeGroup = $objectManager->get(GroupInterfaceFactory::class)->create();
+$storeGroup->setCode('test_group')
+ ->setName('Test Group')
+ ->setWebsite($website);
+$groupResource->save($storeGroup);
+/* Refresh stores memory cache */
+$storeManager->reinitStores();
+
+/** @var StoreInterface $store */
+$store = $objectManager->get(StoreInterfaceFactory::class)->create();
+$store->setCode('test_store_view')
+ ->setWebsiteId($website->getId())
+ ->setGroupId($storeGroup->getId())
+ ->setName('Test Store View')
+ ->setSortOrder(10)
+ ->setIsActive(1);
+$storeResource->save($store);
diff --git a/dev/tests/integration/testsuite/Magento/CustomerGraphQl/_files/website_store_with_store_view_rollback.php b/dev/tests/integration/testsuite/Magento/CustomerGraphQl/_files/website_store_with_store_view_rollback.php
new file mode 100644
index 0000000000000..29f7fbd56c402
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/CustomerGraphQl/_files/website_store_with_store_view_rollback.php
@@ -0,0 +1,41 @@
+get(WebsiteResource::class);
+/** @var StoreResource $storeResource */
+$storeResource = $objectManager->get(StoreResource::class);
+/** @var Registry $registry */
+$registry = $objectManager->get(Registry::class);
+
+$registry->unregister('isSecureArea');
+$registry->register('isSecureArea', true);
+/** @var WebsiteInterface $website */
+$website = $objectManager->get(WebsiteInterfaceFactory::class)->create();
+$websiteResource->load($website, 'test_website', 'code');
+if ($website->getId()) {
+ $websiteResource->delete($website);
+}
+/** @var StoreInterface $store */
+$store = $objectManager->get(StoreInterfaceFactory::class)->create();
+$storeResource->load($store, 'test_store_view', 'code');
+if ($store->getId()) {
+ $storeResource->delete($store);
+}
+
+$registry->unregister('isSecureArea');
+$registry->register('isSecureArea', false);
diff --git a/dev/tests/integration/testsuite/Magento/Store/_files/second_website_with_four_stores_divided_in_groups.php b/dev/tests/integration/testsuite/Magento/Store/_files/second_website_with_four_stores_divided_in_groups.php
new file mode 100644
index 0000000000000..56507bcdd6287
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Store/_files/second_website_with_four_stores_divided_in_groups.php
@@ -0,0 +1,79 @@
+requireDataFixture('Magento/Store/_files/second_website_with_two_stores.php');
+$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+
+/** @var $website \Magento\Store\Model\Website */
+$website = $objectManager->create(\Magento\Store\Model\Website::class);
+$website->load('test', 'code')->getId();
+$websiteId = $website->getId();
+
+/** @var StoreManagerInterface $storeManager */
+$storeManager = $objectManager->get(StoreManagerInterface::class);
+/** @var DefaultCategory $defaultCategory */
+$defaultCategory = $objectManager->get(DefaultCategory::class);
+/** @var GroupInterface $storeGroup */
+$storeGroup = $objectManager->get(GroupInterfaceFactory::class)->create();
+$storeGroup->setCode('second_group')
+ ->setRootCategoryId($defaultCategory->getId())
+ ->setName('second store group')
+ ->setWebsite($website);
+$objectManager->get(GroupResource::class)->save($storeGroup);
+/* Refresh stores memory cache */
+$storeManager->reinitStores();
+
+$store = $objectManager->create(Store::class);
+if (!$store->load('fixture_fourth_store', 'code')->getId()) {
+ $store->setCode(
+ 'fixture_fourth_store'
+ )->setWebsiteId(
+ $websiteId
+ )->setGroupId(
+ $storeGroup->getId()
+ )->setName(
+ 'Fixture Fourth Store'
+ )->setSortOrder(
+ 6
+ )->setIsActive(
+ 1
+ );
+ $store->save();
+}
+
+$store = $objectManager->create(Store::class);
+if (!$store->load('fixture_fifth_store', 'code')->getId()) {
+ $store->setCode(
+ 'fixture_fifth_store'
+ )->setWebsiteId(
+ $websiteId
+ )->setGroupId(
+ $storeGroup->getId()
+ )->setName(
+ 'Fixture Fifth Store'
+ )->setSortOrder(
+ 5
+ )->setIsActive(
+ 1
+ );
+ $store->save();
+}
+
+/* Refresh CatalogSearch index */
+/** @var IndexerRegistry $indexerRegistry */
+$indexerRegistry = $objectManager->get(IndexerRegistry::class);
+$indexerRegistry->get(Fulltext::INDEXER_ID)->reindexAll();
diff --git a/dev/tests/integration/testsuite/Magento/Store/_files/second_website_with_four_stores_divided_in_groups_rollback.php b/dev/tests/integration/testsuite/Magento/Store/_files/second_website_with_four_stores_divided_in_groups_rollback.php
new file mode 100644
index 0000000000000..f4281549a0ac8
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Store/_files/second_website_with_four_stores_divided_in_groups_rollback.php
@@ -0,0 +1,29 @@
+get(\Magento\Framework\Registry::class);
+
+$registry->unregister('isSecureArea');
+$registry->register('isSecureArea', true);
+
+$store = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(\Magento\Store\Model\Store::class);
+if ($store->load('fixture_fourth_store', 'code')->getId()) {
+ $store->delete();
+}
+
+$store = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(\Magento\Store\Model\Store::class);
+if ($store->load('fixture_fifth_store', 'code')->getId()) {
+ $store->delete();
+}
+
+$registry->unregister('isSecureArea');
+$registry->register('isSecureArea', false);
+
+Resolver::getInstance()->requireDataFixture('Magento/Store/_files/second_website_with_two_stores_rollback.php');
diff --git a/lib/internal/Magento/Framework/Data/Form/Element/Time.php b/lib/internal/Magento/Framework/Data/Form/Element/Time.php
index 53d72d704483c..5f67ac4414e99 100644
--- a/lib/internal/Magento/Framework/Data/Form/Element/Time.php
+++ b/lib/internal/Magento/Framework/Data/Form/Element/Time.php
@@ -114,7 +114,7 @@ public function getElementHtml()
'style',
[],
<<