Skip to content

Commit fdf2462

Browse files
committed
MAGETWO-90331: [Magento Cloud] Custom URL rewrites of a product get deleted in multi store views
1 parent 65eb999 commit fdf2462

File tree

2 files changed

+79
-88
lines changed

2 files changed

+79
-88
lines changed

app/code/Magento/UrlRewrite/Model/Storage/DbStorage.php

Lines changed: 55 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
use Magento\Framework\Api\DataObjectHelper;
99
use Magento\Framework\App\ResourceConnection;
10+
use Magento\Framework\DB\Select;
1011
use Magento\UrlRewrite\Model\OptionProvider;
1112
use Magento\UrlRewrite\Service\V1\Data\UrlRewrite;
1213
use Magento\UrlRewrite\Service\V1\Data\UrlRewriteFactory;
@@ -141,17 +142,61 @@ protected function doFindOneByData(array $data)
141142
}
142143

143144
/**
144-
* {@inheritdoc}
145+
* Delete old URLs from DB.
146+
*
147+
* @param UrlRewrite[] $urls
148+
* @return void
145149
*/
146-
protected function doReplace(array $urls)
150+
private function deleteOldUrls(array $urls): void
147151
{
148-
foreach ($this->createFilterDataBasedOnUrls($urls) as $type => $urlData) {
149-
$urlData[UrlRewrite::ENTITY_TYPE] = $type;
150-
// prevent query locking in a case when nothing to delete
151-
if ($this->connection->fetchRow($this->prepareSelect($urlData))) {
152-
$this->deleteByData($urlData);
153-
}
152+
$oldUrlsSelect = $this->connection->select();
153+
$oldUrlsSelect->from(
154+
$this->resource->getTableName(self::TABLE_NAME)
155+
);
156+
/** @var UrlRewrite $url */
157+
foreach ($urls as $url) {
158+
$oldUrlsSelect->orWhere(
159+
$this->connection->quoteIdentifier(
160+
UrlRewrite::ENTITY_TYPE
161+
) . ' = ?',
162+
$url->getEntityType()
163+
);
164+
$oldUrlsSelect->where(
165+
$this->connection->quoteIdentifier(
166+
UrlRewrite::ENTITY_ID
167+
) . ' = ?',
168+
$url->getEntityId()
169+
);
170+
$oldUrlsSelect->where(
171+
$this->connection->quoteIdentifier(
172+
UrlRewrite::STORE_ID
173+
) . ' = ?',
174+
$url->getStoreId()
175+
);
176+
}
177+
178+
// prevent query locking in a case when nothing to delete
179+
$checkOldUrlsSelect = clone $oldUrlsSelect;
180+
$checkOldUrlsSelect->reset(Select::COLUMNS);
181+
$checkOldUrlsSelect->columns('count(*)');
182+
$hasOldUrls = (bool)$this->connection->fetchOne($checkOldUrlsSelect);
183+
184+
if ($hasOldUrls) {
185+
$this->connection->query(
186+
$oldUrlsSelect->deleteFromSelect(
187+
$this->resource->getTableName(self::TABLE_NAME)
188+
)
189+
);
154190
}
191+
}
192+
193+
/**
194+
* @inheritDoc
195+
*/
196+
protected function doReplace(array $urls)
197+
{
198+
$this->deleteOldUrls($urls);
199+
155200
$data = [];
156201
foreach ($urls as $url) {
157202
$data[] = $url->toArray();
@@ -165,7 +210,7 @@ protected function doReplace(array $urls)
165210
$urlFound = $this->doFindOneByData(
166211
[
167212
UrlRewriteData::REQUEST_PATH => $url->getRequestPath(),
168-
UrlRewriteData::STORE_ID => $url->getStoreId()
213+
UrlRewriteData::STORE_ID => $url->getStoreId(),
169214
]
170215
);
171216
if (isset($urlFound[UrlRewriteData::URL_REWRITE_ID])) {
@@ -217,6 +262,7 @@ protected function insertMultiple($data)
217262
*
218263
* @param UrlRewrite[] $urls
219264
* @return array
265+
* @deprecated Not used anymore.
220266
*/
221267
protected function createFilterDataBasedOnUrls($urls)
222268
{

app/code/Magento/UrlRewrite/Test/Unit/Model/Storage/DbStorageTest.php

Lines changed: 24 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
namespace Magento\UrlRewrite\Test\Unit\Model\Storage;
88

9+
use Magento\Framework\DB\Select;
910
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
1011
use Magento\UrlRewrite\Model\Storage\DbStorage;
1112
use Magento\UrlRewrite\Service\V1\Data\UrlRewrite;
@@ -49,10 +50,9 @@ protected function setUp()
4950
->disableOriginalConstructor()->getMock();
5051
$this->dataObjectHelper = $this->createMock(\Magento\Framework\Api\DataObjectHelper::class);
5152
$this->connectionMock = $this->createMock(\Magento\Framework\DB\Adapter\AdapterInterface::class);
52-
$this->select = $this->createPartialMock(
53-
\Magento\Framework\DB\Select::class,
54-
['from', 'where', 'deleteFromSelect']
55-
);
53+
$this->select = $this->getMockBuilder(Select::class)
54+
->disableOriginalConstructor()
55+
->getMock();
5656
$this->resource = $this->createMock(\Magento\Framework\App\ResourceConnection::class);
5757

5858
$this->resource->expects($this->any())
@@ -447,87 +447,32 @@ public function testReplace()
447447
// delete
448448

449449
$urlFirst->expects($this->any())
450-
->method('getByKey')
451-
->will($this->returnValueMap([
452-
[UrlRewrite::ENTITY_TYPE, 'product'],
453-
[UrlRewrite::ENTITY_ID, 'entity_1'],
454-
[UrlRewrite::STORE_ID, 'store_id_1'],
455-
]));
456-
$urlFirst->expects($this->any())->method('getEntityType')->willReturn('product');
450+
->method('getEntityType')
451+
->willReturn('product');
452+
$urlFirst->expects($this->any())
453+
->method('getEntityId')
454+
->willReturn('entity_1');
455+
$urlFirst->expects($this->any())
456+
->method('getStoreId')
457+
->willReturn('store_id_1');
458+
459+
$urlSecond->expects($this->any())
460+
->method('getEntityType')
461+
->willReturn('category');
462+
$urlSecond->expects($this->any())
463+
->method('getEntityId')
464+
->willReturn('entity_2');
457465
$urlSecond->expects($this->any())
458-
->method('getByKey')
459-
->will($this->returnValueMap([
460-
[UrlRewrite::ENTITY_TYPE, 'category'],
461-
[UrlRewrite::ENTITY_ID, 'entity_2'],
462-
[UrlRewrite::STORE_ID, 'store_id_2'],
463-
]));
464-
$urlSecond->expects($this->any())->method('getEntityType')->willReturn('category');
466+
->method('getStoreId')
467+
->willReturn('store_id_2');
465468

466469
$this->connectionMock->expects($this->any())
467470
->method('quoteIdentifier')
468471
->will($this->returnArgument(0));
469472

470-
$this->select->expects($this->at(1))
471-
->method('where')
472-
->with('entity_id IN (?)', ['entity_1']);
473-
474-
$this->select->expects($this->at(2))
475-
->method('where')
476-
->with('store_id IN (?)', ['store_id_1']);
477-
478-
$this->select->expects($this->at(3))
479-
->method('where')
480-
->with('entity_type IN (?)', 'product');
481-
482-
$this->select->expects($this->at(5))
483-
->method('where')
484-
->with('entity_id IN (?)', ['entity_1']);
485-
486-
$this->select->expects($this->at(6))
487-
->method('where')
488-
->with('store_id IN (?)', ['store_id_1']);
489-
490-
$this->select->expects($this->at(7))
491-
->method('where')
492-
->with('entity_type IN (?)', 'product');
493-
494-
$this->connectionMock->expects($this->any())
495-
->method('fetchRow')
496-
->willReturn(['some-data']);
497-
498-
$this->select->expects($this->at(8))
499-
->method('deleteFromSelect')
500-
->with('table_name')
501-
->will($this->returnValue('sql delete query'));
502-
503-
$this->select->expects($this->at(10))
504-
->method('where')
505-
->with('entity_id IN (?)', ['entity_2']);
506-
507-
$this->select->expects($this->at(11))
508-
->method('where')
509-
->with('store_id IN (?)', ['store_id_2']);
510-
511-
$this->select->expects($this->at(12))
512-
->method('where')
513-
->with('entity_type IN (?)', 'category');
514-
515-
$this->select->expects($this->at(14))
516-
->method('where')
517-
->with('entity_id IN (?)', ['entity_2']);
518-
519-
$this->select->expects($this->at(15))
520-
->method('where')
521-
->with('store_id IN (?)', ['store_id_2']);
522-
523-
$this->select->expects($this->at(16))
524-
->method('where')
525-
->with('entity_type IN (?)', 'category');
526-
527-
$this->select->expects($this->at(17))
528-
->method('deleteFromSelect')
529-
->with('table_name')
530-
->will($this->returnValue('sql delete query'));
473+
$this->select->expects($this->any())
474+
->method($this->anything())
475+
->willReturnSelf();
531476

532477
$this->resource->expects($this->any())
533478
->method('getTableName')

0 commit comments

Comments
 (0)