Skip to content

Commit 7deeca2

Browse files
Merge pull request #2248 from magento-tango/2.3-PR-develop-1
Bugs: - MAGETWO-71536 Redundant indexers invalidation - RIATCS-340 - MAGETWO-73136 [GITHUB] Can't add to cart Bundle product with simple product option price as "zero" #8969 - MAGETWO-88212 Cron jobs incorrect behavior when running job terminated - MAGETWO-88973 [Forward port to 2.3] Zoom the image can't be closed by iPhone with Safari browser
2 parents 8e17718 + 6d383d8 commit 7deeca2

File tree

10 files changed

+195
-31
lines changed

10 files changed

+195
-31
lines changed

app/code/Magento/CatalogImportExport/Model/Indexer/Product/Flat/Plugin/Import.php

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,30 @@
55
*/
66
namespace Magento\CatalogImportExport\Model\Indexer\Product\Flat\Plugin;
77

8+
use Magento\Catalog\Model\Indexer\Product\Flat\State as FlatState;
9+
810
class Import
911
{
12+
/**
13+
* @var \Magento\Catalog\Model\Indexer\Product\Flat\State
14+
*/
15+
private $flatState;
16+
1017
/**
1118
* @var \Magento\Catalog\Model\Indexer\Product\Flat\Processor
1219
*/
1320
protected $_productFlatIndexerProcessor;
1421

1522
/**
1623
* @param \Magento\Catalog\Model\Indexer\Product\Flat\Processor $productFlatIndexerProcessor
24+
* @param \Magento\Catalog\Model\Indexer\Product\Flat\State $flatState
1725
*/
18-
public function __construct(\Magento\Catalog\Model\Indexer\Product\Flat\Processor $productFlatIndexerProcessor)
19-
{
26+
public function __construct(
27+
\Magento\Catalog\Model\Indexer\Product\Flat\Processor $productFlatIndexerProcessor,
28+
FlatState $flatState
29+
) {
2030
$this->_productFlatIndexerProcessor = $productFlatIndexerProcessor;
31+
$this->flatState = $flatState;
2132
}
2233

2334
/**
@@ -31,7 +42,10 @@ public function __construct(\Magento\Catalog\Model\Indexer\Product\Flat\Processo
3142
*/
3243
public function afterImportSource(\Magento\ImportExport\Model\Import $subject, $import)
3344
{
34-
$this->_productFlatIndexerProcessor->markIndexerAsInvalid();
45+
if ($this->flatState->isFlatEnabled() && !$this->_productFlatIndexerProcessor->isIndexerScheduled()) {
46+
$this->_productFlatIndexerProcessor->markIndexerAsInvalid();
47+
}
48+
3549
return $import;
3650
}
3751
}

app/code/Magento/CatalogImportExport/Test/Unit/Model/Indexer/Product/Flat/Plugin/ImportTest.php

Lines changed: 66 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,79 @@
55
*/
66
namespace Magento\CatalogImportExport\Test\Unit\Model\Indexer\Product\Flat\Plugin;
77

8+
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
9+
810
class ImportTest extends \PHPUnit\Framework\TestCase
911
{
10-
public function testAfterImportSource()
12+
/**
13+
* @var \Magento\Catalog\Model\Indexer\Product\Flat\Processor|\PHPUnit_Framework_MockObject_MockObject
14+
*/
15+
private $processorMock;
16+
17+
/**
18+
* @var \Magento\CatalogImportExport\Model\Indexer\Product\Flat\Plugin\Import
19+
*/
20+
private $model;
21+
22+
/**
23+
* @var \Magento\Catalog\Model\Indexer\Product\Flat\State|\PHPUnit_Framework_MockObject_MockObject
24+
*/
25+
private $flatStateMock;
26+
27+
/**
28+
* @var \Magento\ImportExport\Model\Import|\PHPUnit_Framework_MockObject_MockObject
29+
*/
30+
private $subjectMock;
31+
32+
protected function setUp()
1133
{
12-
/**
13-
* @var \Magento\Catalog\Model\Indexer\Product\Flat\Processor|
14-
* \PHPUnit_Framework_MockObject_MockObject $processorMock
15-
*/
16-
$processorMock = $this->createPartialMock(
17-
\Magento\Catalog\Model\Indexer\Product\Flat\Processor::class,
18-
['markIndexerAsInvalid']
34+
$this->processorMock = $this->getMockBuilder(\Magento\Catalog\Model\Indexer\Product\Flat\Processor::class)
35+
->disableOriginalConstructor()
36+
->setMethods(['markIndexerAsInvalid', 'isIndexerScheduled'])
37+
->getMock();
38+
39+
$this->flatStateMock = $this->getMockBuilder(\Magento\Catalog\Model\Indexer\Product\Flat\State::class)
40+
->disableOriginalConstructor()
41+
->setMethods(['isFlatEnabled'])
42+
->getMock();
43+
44+
$this->subjectMock = $this->getMockBuilder(\Magento\ImportExport\Model\Import::class)
45+
->disableOriginalConstructor()
46+
->getMock();
47+
48+
$this->model = (new ObjectManager($this))->getObject(
49+
\Magento\CatalogImportExport\Model\Indexer\Product\Flat\Plugin\Import::class,
50+
[
51+
'productFlatIndexerProcessor' => $this->processorMock,
52+
'flatState' => $this->flatStateMock
53+
]
1954
);
55+
}
2056

21-
$subjectMock = $this->createMock(\Magento\ImportExport\Model\Import::class);
22-
$processorMock->expects($this->once())->method('markIndexerAsInvalid');
57+
public function testAfterImportSourceWithFlatEnabledAndIndexerScheduledDisabled()
58+
{
59+
$this->flatStateMock->expects($this->once())->method('isFlatEnabled')->willReturn(true);
60+
$this->processorMock->expects($this->once())->method('isIndexerScheduled')->willReturn(false);
61+
$this->processorMock->expects($this->once())->method('markIndexerAsInvalid');
62+
$someData = [1, 2, 3];
63+
$this->assertEquals($someData, $this->model->afterImportSource($this->subjectMock, $someData));
64+
}
2365

66+
public function testAfterImportSourceWithFlatDisabledAndIndexerScheduledDisabled()
67+
{
68+
$this->flatStateMock->expects($this->once())->method('isFlatEnabled')->willReturn(false);
69+
$this->processorMock->expects($this->never())->method('isIndexerScheduled')->willReturn(false);
70+
$this->processorMock->expects($this->never())->method('markIndexerAsInvalid');
2471
$someData = [1, 2, 3];
72+
$this->assertEquals($someData, $this->model->afterImportSource($this->subjectMock, $someData));
73+
}
2574

26-
$model = new \Magento\CatalogImportExport\Model\Indexer\Product\Flat\Plugin\Import($processorMock);
27-
$this->assertEquals($someData, $model->afterImportSource($subjectMock, $someData));
75+
public function testAfterImportSourceWithFlatEnabledAndIndexerScheduledEnabled()
76+
{
77+
$this->flatStateMock->expects($this->once())->method('isFlatEnabled')->willReturn(true);
78+
$this->processorMock->expects($this->once())->method('isIndexerScheduled')->willReturn(true);
79+
$this->processorMock->expects($this->never())->method('markIndexerAsInvalid');
80+
$someData = [1, 2, 3];
81+
$this->assertEquals($someData, $this->model->afterImportSource($this->subjectMock, $someData));
2882
}
2983
}

app/code/Magento/Cron/Model/ResourceModel/Schedule.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,14 @@ public function trySetJobUniqueStatusAtomic($scheduleId, $newStatus, $currentSta
6666
{
6767
$connection = $this->getConnection();
6868

69-
$match = $connection->quoteInto('existing.job_code = current.job_code AND existing.status = ?', $newStatus);
69+
// this condition added to avoid cron jobs locking after incorrect termination of running job
70+
$match = $connection->quoteInto(
71+
'existing.job_code = current.job_code ' .
72+
'AND (existing.executed_at > UTC_TIMESTAMP() - INTERVAL 1 DAY OR existing.executed_at IS NULL) ' .
73+
'AND existing.status = ?',
74+
$newStatus
75+
);
76+
7077
$selectIfUnlocked = $connection->select()
7178
->joinLeft(
7279
['existing' => $this->getTable('cron_schedule')],
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Cron\Setup;
8+
9+
use Magento\Framework\Setup\InstallSchemaInterface;
10+
use Magento\Framework\Setup\ModuleContextInterface;
11+
use Magento\Framework\Setup\SchemaSetupInterface;
12+
13+
/**
14+
* Cron recurring setup
15+
*/
16+
class Recurring implements InstallSchemaInterface
17+
{
18+
/**
19+
* @var \Magento\Cron\Model\ResourceModel\Schedule
20+
*/
21+
private $schedule;
22+
23+
/**
24+
* Recurring constructor.
25+
* @param \Magento\Cron\Model\ResourceModel\Schedule $schedule
26+
*/
27+
public function __construct(
28+
\Magento\Cron\Model\ResourceModel\Schedule $schedule
29+
) {
30+
$this->schedule = $schedule;
31+
}
32+
33+
/**
34+
* {@inheritdoc}
35+
*/
36+
public function install(SchemaSetupInterface $setup, ModuleContextInterface $context)
37+
{
38+
$connection = $this->schedule->getConnection();
39+
$connection->update(
40+
$this->schedule->getMainTable(),
41+
[
42+
'status' => \Magento\Cron\Model\Schedule::STATUS_ERROR,
43+
'messages' => 'The job is terminated due to system upgrade'
44+
],
45+
$connection->quoteInto('status = ?', \Magento\Cron\Model\Schedule::STATUS_RUNNING)
46+
);
47+
}
48+
}

app/code/Magento/SalesRule/Model/Quote/Discount.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ protected function distributeDiscount(\Magento\Quote\Model\Quote\Item\AbstractIt
179179
$roundingDelta[$key] = 0.0000001;
180180
}
181181
foreach ($item->getChildren() as $child) {
182-
$ratio = $child->getBaseRowTotal() / $parentBaseRowTotal;
182+
$ratio = $parentBaseRowTotal != 0 ? $child->getBaseRowTotal() / $parentBaseRowTotal : 0;
183183
foreach ($keys as $key) {
184184
if (!$item->hasData($key)) {
185185
continue;

app/code/Magento/SalesRule/Test/Unit/Model/Quote/DiscountTest.php

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,30 @@ public function collectItemHasChildrenDataProvider()
229229
{
230230
$data = [
231231
// 3 items, each $100, testing that discount are distributed to item correctly
232-
'three_items' => [
232+
[
233+
'child_item_data' => [
234+
'item1' => [
235+
'base_row_total' => 0,
236+
]
237+
],
238+
'parent_item_data' => [
239+
'discount_amount' => 20,
240+
'base_discount_amount' => 10,
241+
'original_discount_amount' => 40,
242+
'base_original_discount_amount' => 20,
243+
'base_row_total' => 0,
244+
],
245+
'expected_child_item_data' => [
246+
'item1' => [
247+
'discount_amount' => 0,
248+
'base_discount_amount' => 0,
249+
'original_discount_amount' => 0,
250+
'base_original_discount_amount' => 0,
251+
]
252+
],
253+
],
254+
[
255+
// 3 items, each $100, testing that discount are distributed to item correctly
233256
'child_item_data' => [
234257
'item1' => [
235258
'base_row_total' => 100,

dev/tests/integration/testsuite/Magento/Cron/Model/ScheduleTest.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,27 @@ public function testTryLockJobAlreadyLockedFails()
5454
$this->assertFalse($schedule->tryLockJob());
5555
}
5656

57+
/**
58+
* If the job is already locked but lock time less than 1 day ago, attempting to lock it again should fail
59+
*/
60+
public function testTryLockJobAlreadyLockedSucceeds()
61+
{
62+
$offsetInThePast = 2*24*60*60;
63+
64+
$oldSchedule = $this->scheduleFactory->create()
65+
->setCronExpr("* * * * *")
66+
->setJobCode("test_job")
67+
->setStatus(Schedule::STATUS_RUNNING)
68+
->setCreatedAt(strftime('%Y-%m-%d %H:%M:%S', $this->dateTime->gmtTimestamp() - $offsetInThePast))
69+
->setScheduledAt(strftime('%Y-%m-%d %H:%M', $this->dateTime->gmtTimestamp() - $offsetInThePast + 60))
70+
->setExecutedAt(strftime('%Y-%m-%d %H:%M', $this->dateTime->gmtTimestamp() - $offsetInThePast + 61));
71+
$oldSchedule->save();
72+
73+
$schedule = $this->createSchedule("test_job", Schedule::STATUS_PENDING);
74+
75+
$this->assertTrue($schedule->tryLockJob());
76+
}
77+
5778
/**
5879
* If there's a job already locked, should not be able to lock another job
5980
*/

lib/internal/Magento/Framework/Session/SessionManager.php

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -504,18 +504,8 @@ public function regenerateId()
504504
return $this;
505505
}
506506

507-
//@see http://php.net/manual/en/function.session-regenerate-id.php#53480 workaround
508507
if ($this->isSessionExists()) {
509-
$oldSessionId = session_id();
510-
session_regenerate_id();
511-
$newSessionId = session_id();
512-
session_id($oldSessionId);
513-
session_destroy();
514-
515-
$oldSession = $_SESSION;
516-
session_id($newSessionId);
517-
session_start();
518-
$_SESSION = $oldSession;
508+
session_regenerate_id(true);
519509
} else {
520510
session_start();
521511
}

lib/web/fotorama/fotorama.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1218,6 +1218,14 @@ fotoramaVersion = '4.6.4';
12181218
}
12191219

12201220
function stubEvent($el, eventType) {
1221+
var isIOS = /ip(ad|hone|od)/i.test(window.navigator.userAgent);
1222+
1223+
if (isIOS && eventType === 'touchend') {
1224+
$el.on('touchend', function(e){
1225+
$DOCUMENT.trigger('mouseup', e);
1226+
})
1227+
}
1228+
12211229
$el.on(eventType, function (e) {
12221230
stopEvent(e, true);
12231231

lib/web/fotorama/fotorama.min.js

Lines changed: 1 addition & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)