Skip to content

Commit c6f24d4

Browse files
committed
Merge remote-tracking branch 'l3/ACP2E-2568' into Tier4-PR-Delivery-11-18-23
2 parents 9f431a7 + 599e242 commit c6f24d4

File tree

4 files changed

+440
-2
lines changed

4 files changed

+440
-2
lines changed

app/code/Magento/MediaGallery/Model/ResourceModel/DeleteAssetsByPaths.php

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ class DeleteAssetsByPaths implements DeleteAssetsByPathsInterface
2020
{
2121
private const TABLE_MEDIA_GALLERY_ASSET = 'media_gallery_asset';
2222
private const MEDIA_GALLERY_ASSET_PATH = 'path';
23+
private const MEDIA_GALLERY_ASSET_ID = 'id';
2324

2425
/**
2526
* @var ResourceConnection
@@ -78,13 +79,39 @@ public function execute(array $paths): void
7879
* Delete assets from database based on the first part (beginning) of the path
7980
*
8081
* @param string $path
82+
* @throws \Zend_Db_Statement_Exception
8183
*/
8284
private function deleteAssetsByDirectoryPath(string $path): void
85+
{
86+
/** @var AdapterInterface $connection */
87+
$connection = $this->resourceConnection->getConnection();
88+
89+
$select = $connection->select()
90+
->from($this->resourceConnection->getTableName(self::TABLE_MEDIA_GALLERY_ASSET))
91+
->where(self::MEDIA_GALLERY_ASSET_PATH . ' LIKE ?', $path . '%');
92+
93+
$assets = $connection->query($select)->fetchAll();
94+
95+
// Filter out assets with mixed case that doesn't match the paths
96+
foreach ($assets as $asset) {
97+
if (str_starts_with($asset[self::MEDIA_GALLERY_ASSET_PATH], $path)) {
98+
$this->deleteAssetById((int)$asset[self::MEDIA_GALLERY_ASSET_ID]);
99+
}
100+
}
101+
}
102+
103+
/**
104+
* Delete assets from database by asset id
105+
*
106+
* @param int $id
107+
* @return void
108+
*/
109+
private function deleteAssetById(int $id): void
83110
{
84111
/** @var AdapterInterface $connection */
85112
$connection = $this->resourceConnection->getConnection();
86113
$tableName = $this->resourceConnection->getTableName(self::TABLE_MEDIA_GALLERY_ASSET);
87-
$connection->delete($tableName, [self::MEDIA_GALLERY_ASSET_PATH . ' LIKE ?' => $path . '%']);
114+
$connection->delete($tableName, [self::MEDIA_GALLERY_ASSET_ID . ' = ?' => $id]);
88115
}
89116

90117
/**

app/code/Magento/MediaGallery/Model/ResourceModel/GetAssetsByPaths.php

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,29 @@ private function getAssetsData(array $paths): array
105105
$select = $connection->select()
106106
->from($this->resourceConnection->getTableName(self::TABLE_MEDIA_GALLERY_ASSET))
107107
->where(self::MEDIA_GALLERY_ASSET_PATH . ' IN (?)', $paths);
108-
return $connection->query($select)->fetchAll();
108+
$assets = $connection->query($select)->fetchAll();
109+
110+
return $this->filterCaseSensitiveAssets($assets, $paths);
111+
}
112+
113+
/**
114+
* Filter out assets with mixed case that doesn't match the paths
115+
*
116+
* @param array $assets
117+
* @param array $paths
118+
* @return array
119+
*/
120+
private function filterCaseSensitiveAssets(array $assets, array $paths): array
121+
{
122+
$filteredAssets = [];
123+
foreach ($assets as $asset) {
124+
foreach ($paths as $path) {
125+
if ($asset[self::MEDIA_GALLERY_ASSET_PATH] === $path) {
126+
$filteredAssets[] = $asset;
127+
}
128+
}
129+
}
130+
131+
return $filteredAssets;
109132
}
110133
}
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
<?php
2+
/**
3+
* Copyright 2023 Adobe
4+
* All Rights Reserved.
5+
*
6+
* NOTICE: All information contained herein is, and remains
7+
* the property of Adobe and its suppliers, if any. The intellectual
8+
* and technical concepts contained herein are proprietary to Adobe
9+
* and its suppliers and are protected by all applicable intellectual
10+
* property laws, including trade secret and copyright laws.
11+
* Dissemination of this information or reproduction of this material
12+
* is strictly forbidden unless prior written permission is obtained
13+
* from Adobe.
14+
*/
15+
declare(strict_types=1);
16+
17+
namespace Magento\MediaGallery\Test\Unit\Model\ResourceModel;
18+
19+
use Magento\Framework\App\ResourceConnection;
20+
use Magento\Framework\DB\Adapter\AdapterInterface;
21+
use Magento\Framework\DB\Select;
22+
use Magento\Framework\Exception\CouldNotDeleteException;
23+
use Magento\MediaGallery\Model\ResourceModel\DeleteAssetsByPaths;
24+
use PHPUnit\Framework\MockObject\MockObject;
25+
use PHPUnit\Framework\TestCase;
26+
use Psr\Log\LoggerInterface;
27+
28+
class DeleteAssetsByPathsTest extends TestCase
29+
{
30+
private const TABLE_NAME = 'media_gallery_asset';
31+
32+
/**
33+
* @var DeleteAssetsByPaths
34+
*/
35+
private $deleteAssetsByPaths;
36+
37+
/**
38+
* @var AdapterInterface|MockObject
39+
*/
40+
private $adapter;
41+
42+
/**
43+
* @var Select|MockObject
44+
*/
45+
private $select;
46+
47+
/**
48+
* @var \Zend_Db_Statement_Interface|MockObject
49+
*/
50+
private $statement;
51+
52+
/**
53+
* When deleting an asset by path with mixed case, the asset with exact same path should be deleted
54+
*
55+
* @dataProvider assetDeleteByPathDataProvider
56+
* @throws CouldNotDeleteException
57+
*/
58+
public function testDeleteCorrectAssetByPathWithCaseSensitiveMatches(
59+
array $assets,
60+
string $assetPathToDelete,
61+
int $assetIdToAssert
62+
): void {
63+
$this->adapter->expects($this->once())->method('select')->willReturn($this->select);
64+
$this->select->expects($this->once())->method('from')->willReturnSelf();
65+
$this->select->expects($this->once())->method('where')->willReturnSelf();
66+
$this->adapter
67+
->expects($this->once())
68+
->method('query')
69+
->with($this->select)
70+
->willReturn($this->statement);
71+
$this->statement->expects($this->once())->method('fetchAll')->willReturn($assets);
72+
73+
$this->adapter->expects($this->once())
74+
->method('delete')
75+
->with(self::TABLE_NAME, ['id = ?' => $assetIdToAssert]);
76+
77+
$this->deleteAssetsByPaths->execute([$assetPathToDelete]);
78+
}
79+
80+
protected function setUp(): void
81+
{
82+
$logger = $this->getMockForAbstractClass(LoggerInterface::class);
83+
$resourceConnection = $this->createMock(ResourceConnection::class);
84+
85+
$this->deleteAssetsByPaths = new DeleteAssetsByPaths(
86+
$resourceConnection,
87+
$logger
88+
);
89+
90+
$this->adapter = $this->getMockForAbstractClass(AdapterInterface::class);
91+
$this->select = $this->createMock(Select::class);
92+
$this->statement = $this->createMock(\Zend_Db_Statement_Interface::class);
93+
94+
$resourceConnection->expects($this->any())
95+
->method('getConnection')
96+
->willReturn($this->adapter);
97+
98+
$resourceConnection->expects($this->any())
99+
->method('getTableName')
100+
->willReturn(self::TABLE_NAME);
101+
}
102+
103+
public function assetDeleteByPathDataProvider(): array
104+
{
105+
return [
106+
[
107+
'assets' => $this->getAssets(),
108+
'pathToDelete' => 'catalog/category/folder/image.jpg',
109+
'assetIdToAssertDelete' => 1
110+
],
111+
[
112+
'assets' => $this->getAssets(),
113+
'pathToDelete' => 'catalog/category/folder/Image.jpg',
114+
'assetIdToAssertDelete' => 2
115+
],
116+
[
117+
'assets' => $this->getAssets(),
118+
'pathToDelete' => 'catalog/category/folder/IMAGE.JPG',
119+
'assetIdToAssertDelete' => 3
120+
],
121+
[
122+
'assets' => $this->getAssets(),
123+
'pathToDelete' => 'catalog/category/FOLDER',
124+
'assetIdToAssertDelete' => 4
125+
],
126+
];
127+
}
128+
129+
private function getAssets(): array
130+
{
131+
return [
132+
[
133+
'id' => '1',
134+
'path' => 'catalog/category/folder/image.jpg',
135+
'title' => 'image',
136+
'description' => null,
137+
'source' => 'Local',
138+
'hash' => '20b88741b3cfa5749d414a0312c8b909aefbaa1f',
139+
'content_type' => 'image/jpg',
140+
'width' => '1080',
141+
'height' => '1080',
142+
'size' => '53010',
143+
'created_at' => '2023-11-09 16:33:41',
144+
'updated_at' => '2023-11-09 16:33:41',
145+
],
146+
[
147+
'id' => '2',
148+
'path' => 'catalog/category/folder/Image.jpg',
149+
'title' => 'Image',
150+
'description' => null,
151+
'source' => 'Local',
152+
'hash' => '20b88741b3cfa5749d414a0312c8b909aefbaa1f',
153+
'content_type' => 'image/jpg',
154+
'width' => '1080',
155+
'height' => '1080',
156+
'size' => '53010',
157+
'created_at' => '2023-11-09 16:34:19',
158+
'updated_at' => '2023-11-09 16:34:19',
159+
],
160+
[
161+
'id' => '3',
162+
'path' => 'catalog/category/folder/IMAGE.JPG',
163+
'title' => 'IMAGE',
164+
'description' => null,
165+
'source' => 'Local',
166+
'hash' => '93a7c1f07373afafcd4918379dacf8e3de6a3eca',
167+
'content_type' => 'image/jpg',
168+
'width' => '1080',
169+
'height' => '1080',
170+
'size' => '101827',
171+
'created_at' => '2023-11-09 16:37:36',
172+
'updated_at' => '2023-11-09 16:37:36',
173+
],
174+
[
175+
'id' => '4',
176+
'path' => 'catalog/category/FOLDER/IMAGE.JPG',
177+
'title' => 'IMAGE',
178+
'description' => null,
179+
'source' => 'Local',
180+
'hash' => '93a7c1f07373afafcd4918379dacf8e3de6a3eca',
181+
'content_type' => 'image/jpg',
182+
'width' => '1080',
183+
'height' => '1080',
184+
'size' => '101827',
185+
'created_at' => '2023-11-09 16:37:36',
186+
'updated_at' => '2023-11-09 16:37:36',
187+
]
188+
];
189+
}
190+
}

0 commit comments

Comments
 (0)