diff --git a/app/code/Magento/AdminAnalytics/Test/Mftf/Test/TrackingScriptTest.xml b/app/code/Magento/AdminAnalytics/Test/Mftf/Test/TrackingScriptTest.xml
deleted file mode 100644
index e02c34fd8868e..0000000000000
--- a/app/code/Magento/AdminAnalytics/Test/Mftf/Test/TrackingScriptTest.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Category/AggregateCount.php b/app/code/Magento/Catalog/Model/ResourceModel/Category/AggregateCount.php
index fab2441db26c9..939f9d354af85 100644
--- a/app/code/Magento/Catalog/Model/ResourceModel/Category/AggregateCount.php
+++ b/app/code/Magento/Catalog/Model/ResourceModel/Category/AggregateCount.php
@@ -8,11 +8,15 @@
use Magento\Catalog\Model\Category;
/**
+ * Aggregate count for parent category after deleting child category
+ *
* Class AggregateCount
*/
class AggregateCount
{
/**
+ * Reduces children count for parent categories
+ *
* @param Category $category
* @return void
*/
@@ -25,9 +29,7 @@ public function processDelete(Category $category)
*/
$parentIds = $category->getParentIds();
if ($parentIds) {
- $childDecrease = $category->getChildrenCount() + 1;
- // +1 is itself
- $data = ['children_count' => new \Zend_Db_Expr('children_count - ' . $childDecrease)];
+ $data = ['children_count' => new \Zend_Db_Expr('children_count - 1')];
$where = ['entity_id IN(?)' => $parentIds];
$resourceModel->getConnection()->update($resourceModel->getEntityTable(), $data, $where);
}
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Category/AggregateCountTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Category/AggregateCountTest.php
new file mode 100644
index 0000000000000..c73e02fb7ecbf
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Category/AggregateCountTest.php
@@ -0,0 +1,91 @@
+categoryMock = $this->createMock(Category::class);
+ $this->resourceCategoryMock = $this->createMock(ResourceCategory::class);
+ $this->connectionMock = $this->getMockBuilder(AdapterInterface::class)
+ ->getMockForAbstractClass();
+ $this->objectManagerHelper = new ObjectManagerHelper($this);
+ $this->aggregateCount = $this->objectManagerHelper->getObject(AggregateCount::class);
+ }
+
+ /**
+ * @return void
+ */
+ public function testProcessDelete(): void
+ {
+ $parentIds = 3;
+ $table = 'catalog_category_entity';
+
+ $this->categoryMock->expects($this->once())
+ ->method('getResource')
+ ->willReturn($this->resourceCategoryMock);
+ $this->categoryMock->expects($this->once())
+ ->method('getParentIds')
+ ->willReturn($parentIds);
+ $this->resourceCategoryMock->expects($this->any())
+ ->method('getEntityTable')
+ ->willReturn($table);
+ $this->resourceCategoryMock->expects($this->once())
+ ->method('getConnection')
+ ->willReturn($this->connectionMock);
+ $this->connectionMock->expects($this->once())
+ ->method('update')
+ ->with(
+ $table,
+ ['children_count' => new \Zend_Db_Expr('children_count - 1')],
+ ['entity_id IN(?)' => $parentIds]
+ );
+ $this->aggregateCount->processDelete($this->categoryMock);
+ }
+}
diff --git a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/CategoriesTest.php b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/CategoriesTest.php
index 254d893d24584..17318d4207841 100644
--- a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/CategoriesTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/CategoriesTest.php
@@ -7,13 +7,16 @@
namespace Magento\Catalog\Test\Unit\Ui\DataProvider\Product\Form\Modifier;
-use Magento\Catalog\Model\ResourceModel\Category\Collection as CategoryCollection;
-use Magento\Catalog\Model\ResourceModel\Category\CollectionFactory as CategoryCollectionFactory;
use Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\Categories;
+use Magento\Catalog\Model\ResourceModel\Category\CollectionFactory as CategoryCollectionFactory;
+use Magento\Catalog\Model\ResourceModel\Category\Collection as CategoryCollection;
use Magento\Framework\AuthorizationInterface;
use Magento\Framework\DB\Helper as DbHelper;
use Magento\Framework\UrlInterface;
use Magento\Store\Model\Store;
+use Magento\Backend\Model\Auth\Session;
+use Magento\Authorization\Model\Role;
+use Magento\User\Model\User;
use PHPUnit\Framework\MockObject\MockObject;
/**
@@ -51,6 +54,11 @@ class CategoriesTest extends AbstractModifierTest
*/
private $authorizationMock;
+ /**
+ * @var Session|MockObject
+ */
+ private $sessionMock;
+
protected function setUp(): void
{
parent::setUp();
@@ -72,7 +80,10 @@ protected function setUp(): void
$this->authorizationMock = $this->getMockBuilder(AuthorizationInterface::class)
->disableOriginalConstructor()
->getMockForAbstractClass();
-
+ $this->sessionMock = $this->getMockBuilder(Session::class)
+ ->setMethods(['getUser'])
+ ->disableOriginalConstructor()
+ ->getMock();
$this->categoryCollectionFactoryMock->expects($this->any())
->method('create')
->willReturn($this->categoryCollectionMock);
@@ -88,6 +99,26 @@ protected function setUp(): void
$this->categoryCollectionMock->expects($this->any())
->method('getIterator')
->willReturn(new \ArrayIterator([]));
+
+ $roleAdmin = $this->getMockBuilder(Role::class)
+ ->setMethods(['getId'])
+ ->disableOriginalConstructor()
+ ->getMock();
+ $roleAdmin->expects($this->any())
+ ->method('getId')
+ ->willReturn(0);
+
+ $userAdmin = $this->getMockBuilder(User::class)
+ ->setMethods(['getRole'])
+ ->disableOriginalConstructor()
+ ->getMock();
+ $userAdmin->expects($this->any())
+ ->method('getRole')
+ ->willReturn($roleAdmin);
+
+ $this->sessionMock->expects($this->any())
+ ->method('getUser')
+ ->willReturn($userAdmin);
}
/**
@@ -101,11 +132,28 @@ protected function createModel()
'locator' => $this->locatorMock,
'categoryCollectionFactory' => $this->categoryCollectionFactoryMock,
'arrayManager' => $this->arrayManagerMock,
- 'authorization' => $this->authorizationMock
+ 'authorization' => $this->authorizationMock,
+ 'session' => $this->sessionMock
]
);
}
+ /**
+ * @param object $object
+ * @param string $method
+ * @param array $args
+ * @return mixed
+ * @throws \ReflectionException
+ */
+ private function invokeMethod($object, $method, $args = [])
+ {
+ $class = new \ReflectionClass(Categories::class);
+ $method = $class->getMethod($method);
+ $method->setAccessible(true);
+
+ return $method->invokeArgs($object, $args);
+ }
+
public function testModifyData()
{
$this->assertSame([], $this->getModel()->modifyData([]));
@@ -176,4 +224,44 @@ public function modifyMetaLockedDataProvider()
{
return [[true], [false]];
}
+
+ /**
+ * Asserts that a user with an ACL role ID of 0 and a user with an ACL role ID of 1 do not have the same cache IDs
+ * Assumes a store ID of 0
+ *
+ * @throws \ReflectionException
+ */
+ public function testAclCacheIds()
+ {
+ $categoriesAdmin = $this->createModel();
+ $cacheIdAdmin = $this->invokeMethod($categoriesAdmin, 'getCategoriesTreeCacheId', [0]);
+
+ $roleAclUser = $this->getMockBuilder(Role::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $roleAclUser->expects($this->any())
+ ->method('getId')
+ ->willReturn(1);
+
+ $userAclUser = $this->getMockBuilder(User::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $userAclUser->expects($this->any())
+ ->method('getRole')
+ ->will($this->returnValue($roleAclUser));
+
+ $this->sessionMock = $this->getMockBuilder(Session::class)
+ ->setMethods(['getUser'])
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->sessionMock->expects($this->any())
+ ->method('getUser')
+ ->will($this->returnValue($userAclUser));
+
+ $categoriesAclUser = $this->createModel();
+ $cacheIdAclUser = $this->invokeMethod($categoriesAclUser, 'getCategoriesTreeCacheId', [0]);
+
+ $this->assertNotEquals($cacheIdAdmin, $cacheIdAclUser);
+ }
}
diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Categories.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Categories.php
index 7608173c8edfc..c0d5f0a1af3b8 100644
--- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Categories.php
+++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Categories.php
@@ -18,12 +18,14 @@
use Magento\Framework\UrlInterface;
use Magento\Framework\Stdlib\ArrayManager;
use Magento\Framework\AuthorizationInterface;
+use Magento\Backend\Model\Auth\Session;
/**
* Data provider for categories field of product page
*
* @api
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ * @SuppressWarnings(PHPMD.CookieAndSessionMisuse)
* @since 101.0.0
*/
class Categories extends AbstractModifier
@@ -86,6 +88,11 @@ class Categories extends AbstractModifier
*/
private $authorization;
+ /**
+ * @var Session
+ */
+ private $session;
+
/**
* @param LocatorInterface $locator
* @param CategoryCollectionFactory $categoryCollectionFactory
@@ -94,6 +101,7 @@ class Categories extends AbstractModifier
* @param ArrayManager $arrayManager
* @param SerializerInterface $serializer
* @param AuthorizationInterface $authorization
+ * @param Session $session
*/
public function __construct(
LocatorInterface $locator,
@@ -102,7 +110,8 @@ public function __construct(
UrlInterface $urlBuilder,
ArrayManager $arrayManager,
SerializerInterface $serializer = null,
- AuthorizationInterface $authorization = null
+ AuthorizationInterface $authorization = null,
+ Session $session = null
) {
$this->locator = $locator;
$this->categoryCollectionFactory = $categoryCollectionFactory;
@@ -111,6 +120,7 @@ public function __construct(
$this->arrayManager = $arrayManager;
$this->serializer = $serializer ?: ObjectManager::getInstance()->get(SerializerInterface::class);
$this->authorization = $authorization ?: ObjectManager::getInstance()->get(AuthorizationInterface::class);
+ $this->session = $session ?: ObjectManager::getInstance()->get(Session::class);
}
/**
@@ -370,10 +380,16 @@ protected function getCategoriesTree($filter = null)
* @param string $filter
* @return string
*/
- private function getCategoriesTreeCacheId(int $storeId, string $filter = '') : string
+ private function getCategoriesTreeCacheId(int $storeId, string $filter = ''): string
{
+ if ($this->session->getUser() !== null) {
+ return self::CATEGORY_TREE_ID
+ . '_' . (string)$storeId
+ . '_' . $this->session->getUser()->getAclRole()
+ . '_' . $filter;
+ }
return self::CATEGORY_TREE_ID
- . '_' . (string) $storeId
+ . '_' . (string)$storeId
. '_' . $filter;
}
diff --git a/app/code/Magento/CmsUrlRewrite/Plugin/Cms/Model/Store/View.php b/app/code/Magento/CmsUrlRewrite/Plugin/Cms/Model/Store/View.php
index 257f8ba9bfe53..9e360481e8eb3 100644
--- a/app/code/Magento/CmsUrlRewrite/Plugin/Cms/Model/Store/View.php
+++ b/app/code/Magento/CmsUrlRewrite/Plugin/Cms/Model/Store/View.php
@@ -7,6 +7,7 @@
namespace Magento\CmsUrlRewrite\Plugin\Cms\Model\Store;
+use Magento\Cms\Api\Data\PageInterface;
use Magento\Cms\Api\PageRepositoryInterface;
use Magento\CmsUrlRewrite\Model\CmsPageUrlRewriteGenerator;
use Magento\Framework\Api\SearchCriteriaBuilder;
@@ -21,6 +22,8 @@
*/
class View
{
+ private const ALL_STORE_VIEWS = '0';
+
/**
* @var UrlPersistInterface
*/
@@ -89,9 +92,8 @@ private function generateCmsPagesUrls(int $storeId): array
{
$rewrites = [];
$urls = [];
- $searchCriteria = $this->searchCriteriaBuilder->create();
- $cmsPagesCollection = $this->pageRepository->getList($searchCriteria)->getItems();
- foreach ($cmsPagesCollection as $page) {
+
+ foreach ($this->getCmsPageItems() as $page) {
$page->setStoreId($storeId);
$rewrites[] = $this->cmsPageUrlRewriteGenerator->generate($page);
}
@@ -99,4 +101,18 @@ private function generateCmsPagesUrls(int $storeId): array
return $urls;
}
+
+ /**
+ * Return cms page items for all store view
+ *
+ * @return PageInterface[]
+ */
+ private function getCmsPageItems(): array
+ {
+ $searchCriteria = $this->searchCriteriaBuilder->addFilter('store_id', self::ALL_STORE_VIEWS)
+ ->create();
+ $list = $this->pageRepository->getList($searchCriteria);
+
+ return $list->getItems();
+ }
}
diff --git a/app/code/Magento/Customer/Block/DataProviders/AddressAttributeData.php b/app/code/Magento/Customer/Block/DataProviders/AddressAttributeData.php
index 2be340c8ccca4..b4c737f6600bf 100644
--- a/app/code/Magento/Customer/Block/DataProviders/AddressAttributeData.php
+++ b/app/code/Magento/Customer/Block/DataProviders/AddressAttributeData.php
@@ -52,7 +52,7 @@ public function getFrontendLabel(string $attributeCode): string
{
try {
$attribute = $this->addressMetadata->getAttributeMetadata($attributeCode);
- $frontendLabel = $attribute->getFrontendLabel();
+ $frontendLabel = $attribute->getStoreLabel() ?: $attribute->getFrontendLabel();
} catch (NoSuchEntityException $e) {
$frontendLabel = '';
}
diff --git a/app/code/Magento/Customer/Model/Plugin/CustomerAuthorization.php b/app/code/Magento/Customer/Model/Plugin/CustomerAuthorization.php
index 9eb9ffb806c9f..b877b2cca67a5 100644
--- a/app/code/Magento/Customer/Model/Plugin/CustomerAuthorization.php
+++ b/app/code/Magento/Customer/Model/Plugin/CustomerAuthorization.php
@@ -7,7 +7,10 @@
namespace Magento\Customer\Model\Plugin;
use Magento\Authorization\Model\UserContextInterface;
+use Magento\Customer\Model\CustomerFactory;
+use Magento\Customer\Model\ResourceModel\Customer as CustomerResource;
use Magento\Integration\Api\AuthorizationServiceInterface as AuthorizationService;
+use Magento\Store\Model\StoreManagerInterface;
/**
* Plugin around \Magento\Framework\Authorization::isAllowed
@@ -19,16 +22,41 @@ class CustomerAuthorization
/**
* @var UserContextInterface
*/
- protected $userContext;
+ private $userContext;
+
+ /**
+ * @var CustomerFactory
+ */
+ private $customerFactory;
+
+ /**
+ * @var CustomerResource
+ */
+ private $customerResource;
+
+ /**
+ * @var StoreManagerInterface
+ */
+ private $storeManager;
/**
* Inject dependencies.
*
* @param UserContextInterface $userContext
+ * @param CustomerFactory $customerFactory
+ * @param CustomerResource $customerResource
+ * @param StoreManagerInterface $storeManager
*/
- public function __construct(UserContextInterface $userContext)
- {
+ public function __construct(
+ UserContextInterface $userContext,
+ CustomerFactory $customerFactory,
+ CustomerResource $customerResource,
+ StoreManagerInterface $storeManager
+ ) {
$this->userContext = $userContext;
+ $this->customerFactory = $customerFactory;
+ $this->customerResource = $customerResource;
+ $this->storeManager = $storeManager;
}
/**
@@ -53,9 +81,15 @@ public function aroundIsAllowed(
&& $this->userContext->getUserId()
&& $this->userContext->getUserType() === UserContextInterface::USER_TYPE_CUSTOMER
) {
- return true;
- } else {
- return $proceed($resource, $privilege);
+ $customer = $this->customerFactory->create();
+ $this->customerResource->load($customer, $this->userContext->getUserId());
+ $currentStoreId = $this->storeManager->getStore()->getId();
+ $sharedStoreIds = $customer->getSharedStoreIds();
+ if (in_array($currentStoreId, $sharedStoreIds)) {
+ return true;
+ }
}
+
+ return $proceed($resource, $privilege);
}
}
diff --git a/app/code/Magento/Developer/Console/Command/patch_template.php.dist b/app/code/Magento/Developer/Console/Command/patch_template.php.dist
index f4fc25abcb29a..8e14b24bdc933 100644
--- a/app/code/Magento/Developer/Console/Command/patch_template.php.dist
+++ b/app/code/Magento/Developer/Console/Command/patch_template.php.dist
@@ -3,6 +3,7 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
+declare(strict_types=1);
namespace %moduleName%\Setup\Patch\%patchType%;
@@ -36,7 +37,7 @@ class %class% implements %implementsInterfaces%
}
%revertFunction%
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function getAliases()
{
@@ -44,12 +45,10 @@ class %class% implements %implementsInterfaces%
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public static function getDependencies()
{
- return [
-
- ];
+ return [];
}
}
diff --git a/app/code/Magento/ImportExport/Model/Export/Adapter/Csv.php b/app/code/Magento/ImportExport/Model/Export/Adapter/Csv.php
index 09b17371ae4e8..f5b62df9aea2c 100644
--- a/app/code/Magento/ImportExport/Model/Export/Adapter/Csv.php
+++ b/app/code/Magento/ImportExport/Model/Export/Adapter/Csv.php
@@ -54,6 +54,19 @@ public function destruct()
{
if (is_object($this->_fileHandler)) {
$this->_fileHandler->close();
+ $this->resolveDestination();
+ }
+ }
+
+ /**
+ * Remove temporary destination
+ *
+ * @return void
+ */
+ private function resolveDestination(): void
+ {
+ // only temporary file located directly in var folder
+ if (strpos($this->_destination, '/') === false) {
$this->_directoryHandle->delete($this->_destination);
}
}
diff --git a/app/code/Magento/MediaContentCatalog/Observer/CategoryDelete.php b/app/code/Magento/MediaContentCatalog/Observer/CategoryDelete.php
new file mode 100644
index 0000000000000..1565d455cc43f
--- /dev/null
+++ b/app/code/Magento/MediaContentCatalog/Observer/CategoryDelete.php
@@ -0,0 +1,120 @@
+extractAssetsFromContent = $extractAssetsFromContent;
+ $this->getContent = $getContent;
+ $this->deleteContentAssetLinks = $deleteContentAssetLinks;
+ $this->contentAssetLinkFactory = $contentAssetLinkFactory;
+ $this->contentIdentityFactory = $contentIdentityFactory;
+ $this->fields = $fields;
+ }
+
+ /**
+ * Retrieve the deleted category and remove relation betwen category and asset
+ *
+ * @param Observer $observer
+ * @throws \Exception
+ */
+ public function execute(Observer $observer): void
+ {
+ $category = $observer->getEvent()->getData('category');
+ $contentAssetLinks = [];
+
+ if ($category instanceof CatalogCategory) {
+ foreach ($this->fields as $field) {
+ $contentIdentity = $this->contentIdentityFactory->create(
+ [
+ self::TYPE => self::CONTENT_TYPE,
+ self::FIELD => $field,
+ self::ENTITY_ID => (string) $category->getEntityId(),
+ ]
+ );
+ $content = implode(PHP_EOL, $this->getContent->execute($contentIdentity));
+ $assets = $this->extractAssetsFromContent->execute($content);
+
+ foreach ($assets as $asset) {
+ $contentAssetLinks[] = $this->contentAssetLinkFactory->create(
+ [
+ 'assetId' => $asset->getId(),
+ 'contentIdentity' => $contentIdentity
+ ]
+ );
+ }
+ }
+ if (!empty($contentAssetLinks)) {
+ $this->deleteContentAssetLinks->execute($contentAssetLinks);
+ }
+ }
+ }
+}
diff --git a/app/code/Magento/MediaContentCatalog/Observer/ProductDelete.php b/app/code/Magento/MediaContentCatalog/Observer/ProductDelete.php
new file mode 100644
index 0000000000000..421bb5a33fa1d
--- /dev/null
+++ b/app/code/Magento/MediaContentCatalog/Observer/ProductDelete.php
@@ -0,0 +1,120 @@
+extractAssetsFromContent = $extractAssetsFromContent;
+ $this->getContent = $getContent;
+ $this->deleteContentAssetLinks = $deleteContentAssetLinks;
+ $this->contentAssetLinkFactory = $contentAssetLinkFactory;
+ $this->contentIdentityFactory = $contentIdentityFactory;
+ $this->fields = $fields;
+ }
+
+ /**
+ * Retrieve the deleted product and remove relation betwen product and asset
+ *
+ * @param Observer $observer
+ * @throws \Exception
+ */
+ public function execute(Observer $observer): void
+ {
+ $product = $observer->getEvent()->getData('product');
+ $contentAssetLinks = [];
+
+ if ($product instanceof CatalogProduct) {
+ foreach ($this->fields as $field) {
+ $contentIdentity = $this->contentIdentityFactory->create(
+ [
+ self::TYPE => self::CONTENT_TYPE,
+ self::FIELD => $field,
+ self::ENTITY_ID => (string) $product->getEntityId(),
+ ]
+ );
+ $productContent = implode(PHP_EOL, $this->getContent->execute($contentIdentity));
+ $assets = $this->extractAssetsFromContent->execute($productContent);
+
+ foreach ($assets as $asset) {
+ $contentAssetLinks[] = $this->contentAssetLinkFactory->create(
+ [
+ 'assetId' => $asset->getId(),
+ 'contentIdentity' => $contentIdentity
+ ]
+ );
+ }
+ }
+ if (!empty($contentAssetLinks)) {
+ $this->deleteContentAssetLinks->execute($contentAssetLinks);
+ }
+ }
+ }
+}
diff --git a/app/code/Magento/MediaContentCatalog/etc/di.xml b/app/code/Magento/MediaContentCatalog/etc/di.xml
index a2d300a2bb208..6b0ee83b30788 100644
--- a/app/code/Magento/MediaContentCatalog/etc/di.xml
+++ b/app/code/Magento/MediaContentCatalog/etc/di.xml
@@ -14,6 +14,22 @@
+
+
+
+ - description
+ - short_description
+
+
+
+
+
+
+ - image
+ - description
+
+
+
diff --git a/app/code/Magento/MediaContentCatalog/etc/events.xml b/app/code/Magento/MediaContentCatalog/etc/events.xml
index f68d66eb3cc40..8ec7a30b961ba 100644
--- a/app/code/Magento/MediaContentCatalog/etc/events.xml
+++ b/app/code/Magento/MediaContentCatalog/etc/events.xml
@@ -9,6 +9,12 @@
+
+
+
+
+
+
diff --git a/app/code/Magento/MediaContentCms/Observer/BlockDelete.php b/app/code/Magento/MediaContentCms/Observer/BlockDelete.php
new file mode 100644
index 0000000000000..582f0a9ec6701
--- /dev/null
+++ b/app/code/Magento/MediaContentCms/Observer/BlockDelete.php
@@ -0,0 +1,119 @@
+extractAssetsFromContent = $extractAssetsFromContent;
+ $this->getContent = $getContent;
+ $this->deleteContentAssetLinks = $deleteContentAssetLinks;
+ $this->contentAssetLinkFactory = $contentAssetLinkFactory;
+ $this->contentIdentityFactory = $contentIdentityFactory;
+ $this->fields = $fields;
+ }
+
+ /**
+ * Retrieve the deleted category and remove relation betwen category and asset
+ *
+ * @param Observer $observer
+ * @throws \Exception
+ */
+ public function execute(Observer $observer): void
+ {
+ $block = $observer->getEvent()->getData('object');
+ $contentAssetLinks = [];
+
+ if ($block instanceof CmsBlock) {
+ foreach ($this->fields as $field) {
+ $contentIdentity = $this->contentIdentityFactory->create(
+ [
+ self::TYPE => self::CONTENT_TYPE,
+ self::FIELD => $field,
+ self::ENTITY_ID => (string) $block->getId(),
+ ]
+ );
+ $assets = $this->extractAssetsFromContent->execute((string) $block->getData($field));
+
+ foreach ($assets as $asset) {
+ $contentAssetLinks[] = $this->contentAssetLinkFactory->create(
+ [
+ 'assetId' => $asset->getId(),
+ 'contentIdentity' => $contentIdentity
+ ]
+ );
+ }
+ }
+ if (!empty($contentAssetLinks)) {
+ $this->deleteContentAssetLinks->execute($contentAssetLinks);
+ }
+ }
+ }
+}
diff --git a/app/code/Magento/MediaContentCms/Observer/PageDelete.php b/app/code/Magento/MediaContentCms/Observer/PageDelete.php
new file mode 100644
index 0000000000000..96d2bf89873bd
--- /dev/null
+++ b/app/code/Magento/MediaContentCms/Observer/PageDelete.php
@@ -0,0 +1,120 @@
+extractAssetsFromContent = $extractAssetsFromContent;
+ $this->getContent = $getContent;
+ $this->deleteContentAssetLinks = $deleteContentAssetLinks;
+ $this->contentAssetLinkFactory = $contentAssetLinkFactory;
+ $this->contentIdentityFactory = $contentIdentityFactory;
+ $this->fields = $fields;
+ }
+
+ /**
+ * Retrieve the deleted category and remove relation betwen category and asset
+ *
+ * @param Observer $observer
+ * @throws \Exception
+ */
+ public function execute(Observer $observer): void
+ {
+ $page = $observer->getEvent()->getData('object');
+ $contentAssetLinks = [];
+
+ if ($page instanceof CmsPage) {
+ foreach ($this->fields as $field) {
+ $contentIdentity = $this->contentIdentityFactory->create(
+ [
+ self::TYPE => self::CONTENT_TYPE,
+ self::FIELD => $field,
+ self::ENTITY_ID => (string) $page->getId(),
+ ]
+ );
+
+ $assets = $this->extractAssetsFromContent->execute((string) $page->getData($field));
+
+ foreach ($assets as $asset) {
+ $contentAssetLinks[] = $this->contentAssetLinkFactory->create(
+ [
+ 'assetId' => $asset->getId(),
+ 'contentIdentity' => $contentIdentity
+ ]
+ );
+ }
+ }
+ if (!empty($contentAssetLinks)) {
+ $this->deleteContentAssetLinks->execute($contentAssetLinks);
+ }
+ }
+ }
+}
diff --git a/app/code/Magento/MediaContentCms/etc/di.xml b/app/code/Magento/MediaContentCms/etc/di.xml
index f980936465faf..6f196889540af 100644
--- a/app/code/Magento/MediaContentCms/etc/di.xml
+++ b/app/code/Magento/MediaContentCms/etc/di.xml
@@ -20,4 +20,18 @@
+
+
+
+ - content
+
+
+
+
+
+
+ - content
+
+
+
diff --git a/app/code/Magento/MediaContentCms/etc/events.xml b/app/code/Magento/MediaContentCms/etc/events.xml
index 7e9abe3bf19c4..94f963f40be15 100644
--- a/app/code/Magento/MediaContentCms/etc/events.xml
+++ b/app/code/Magento/MediaContentCms/etc/events.xml
@@ -6,8 +6,14 @@
*/
-->
+
+
+
+
+
+
diff --git a/app/code/Magento/Sales/Model/Order/Pdf/Items/Invoice/DefaultInvoice.php b/app/code/Magento/Sales/Model/Order/Pdf/Items/Invoice/DefaultInvoice.php
index 253dbd43fa580..6ddbce49829eb 100644
--- a/app/code/Magento/Sales/Model/Order/Pdf/Items/Invoice/DefaultInvoice.php
+++ b/app/code/Magento/Sales/Model/Order/Pdf/Items/Invoice/DefaultInvoice.php
@@ -80,11 +80,9 @@ public function draw()
$lines = [];
// draw Product name
- $lines[0] = [
- [
+ $lines[0][] = [
'text' => $this->string->split($this->prepareText((string)$item->getName()), 35, true, true),
'feed' => 35
- ]
];
// draw SKU
diff --git a/app/code/Magento/Store/etc/di.xml b/app/code/Magento/Store/etc/di.xml
index 5bd8f6e2349fc..2da9e91e1fddd 100644
--- a/app/code/Magento/Store/etc/di.xml
+++ b/app/code/Magento/Store/etc/di.xml
@@ -65,7 +65,6 @@
-
diff --git a/lib/internal/Magento/Framework/App/Action/Plugin/LoadDesignPlugin.php b/app/code/Magento/Theme/Plugin/LoadDesignPlugin.php
similarity index 88%
rename from lib/internal/Magento/Framework/App/Action/Plugin/LoadDesignPlugin.php
rename to app/code/Magento/Theme/Plugin/LoadDesignPlugin.php
index 2cda49c43c2ce..c4f8d3a905d0f 100644
--- a/lib/internal/Magento/Framework/App/Action/Plugin/LoadDesignPlugin.php
+++ b/app/code/Magento/Theme/Plugin/LoadDesignPlugin.php
@@ -4,7 +4,7 @@
* See COPYING.txt for license details.
*/
-namespace Magento\Framework\App\Action\Plugin;
+namespace Magento\Theme\Plugin;
use Magento\Framework\App\ActionInterface;
use Magento\Framework\Config\Dom\ValidationException;
@@ -21,12 +21,12 @@ class LoadDesignPlugin
/**
* @var DesignLoader
*/
- protected $_designLoader;
+ private $designLoader;
/**
* @var MessageManagerInterface
*/
- protected $messageManager;
+ private $messageManager;
/**
* @param DesignLoader $designLoader
@@ -36,7 +36,7 @@ public function __construct(
DesignLoader $designLoader,
MessageManagerInterface $messageManager
) {
- $this->_designLoader = $designLoader;
+ $this->designLoader = $designLoader;
$this->messageManager = $messageManager;
}
@@ -50,7 +50,7 @@ public function __construct(
public function beforeExecute(ActionInterface $subject)
{
try {
- $this->_designLoader->load();
+ $this->designLoader->load();
} catch (LocalizedException $e) {
if ($e->getPrevious() instanceof ValidationException) {
/** @var MessageInterface $message */
diff --git a/lib/internal/Magento/Framework/App/Test/Unit/Action/Plugin/LoadDesignPluginTest.php b/app/code/Magento/Theme/Test/Unit/Plugin/LoadDesignPluginTest.php
similarity index 80%
rename from lib/internal/Magento/Framework/App/Test/Unit/Action/Plugin/LoadDesignPluginTest.php
rename to app/code/Magento/Theme/Test/Unit/Plugin/LoadDesignPluginTest.php
index 549d45a986cf0..4efcc584986d1 100644
--- a/lib/internal/Magento/Framework/App/Test/Unit/Action/Plugin/LoadDesignPluginTest.php
+++ b/app/code/Magento/Theme/Test/Unit/Plugin/LoadDesignPluginTest.php
@@ -3,15 +3,13 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-declare(strict_types=1);
-
-namespace Magento\Framework\App\Test\Unit\Action\Plugin;
+namespace Magento\Theme\Test\Unit\Plugin;
use Magento\Framework\App\Action\Action;
-use Magento\Framework\App\Action\Plugin\LoadDesignPlugin;
use Magento\Framework\App\ActionInterface;
use Magento\Framework\Message\ManagerInterface;
use Magento\Framework\View\DesignLoader;
+use Magento\Theme\Plugin\LoadDesignPlugin;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
@@ -26,7 +24,7 @@ public function testBeforeExecute()
$designLoaderMock = $this->createMock(DesignLoader::class);
/** @var MockObject|ManagerInterface $messageManagerMock */
- $messageManagerMock = $this->getMockForAbstractClass(ManagerInterface::class);
+ $messageManagerMock = $this->createMock(ManagerInterface::class);
$plugin = new LoadDesignPlugin($designLoaderMock, $messageManagerMock);
diff --git a/app/code/Magento/Theme/etc/di.xml b/app/code/Magento/Theme/etc/di.xml
index c4da1f860870e..15107adb931c9 100644
--- a/app/code/Magento/Theme/etc/di.xml
+++ b/app/code/Magento/Theme/etc/di.xml
@@ -105,6 +105,9 @@
Magento\Store\Model\ScopeInterface::SCOPE_STORE
+
+
+
diff --git a/app/code/Magento/Theme/view/frontend/templates/js/calendar.phtml b/app/code/Magento/Theme/view/frontend/templates/js/calendar.phtml
index 55798169cdf75..b42cabde6cd85 100644
--- a/app/code/Magento/Theme/view/frontend/templates/js/calendar.phtml
+++ b/app/code/Magento/Theme/view/frontend/templates/js/calendar.phtml
@@ -14,7 +14,6 @@