Skip to content

Commit d652ac9

Browse files
merge magento/2.3-develop into magento-trigger/MC-17545
2 parents e695e09 + 40edf5c commit d652ac9

File tree

174 files changed

+5748
-342
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

174 files changed

+5748
-342
lines changed

app/code/Magento/AsynchronousOperations/Model/BulkStatus.php

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -87,22 +87,6 @@ public function getFailedOperationsByBulkId($bulkUuid, $failureType = null)
8787
*/
8888
public function getOperationsCountByBulkIdAndStatus($bulkUuid, $status)
8989
{
90-
if ($status === OperationInterface::STATUS_TYPE_OPEN) {
91-
/**
92-
* Total number of operations that has been scheduled within the given bulk
93-
*/
94-
$allOperationsQty = $this->getOperationCount($bulkUuid);
95-
96-
/**
97-
* Number of operations that has been processed (i.e. operations with any status but 'open')
98-
*/
99-
$allProcessedOperationsQty = (int)$this->operationCollectionFactory->create()
100-
->addFieldToFilter('bulk_uuid', $bulkUuid)
101-
->getSize();
102-
103-
return $allOperationsQty - $allProcessedOperationsQty;
104-
}
105-
10690
/** @var \Magento\AsynchronousOperations\Model\ResourceModel\Operation\Collection $collection */
10791
$collection = $this->operationCollectionFactory->create();
10892
return $collection->addFieldToFilter('bulk_uuid', $bulkUuid)

app/code/Magento/Bundle/view/adminhtml/templates/product/composite/fieldset/options/type/checkbox.phtml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
<?php $_selections = $_option->getSelections(); ?>
1111
<?php $_skipSaleableCheck = $this->helper(Magento\Catalog\Helper\Product::class)->getSkipSaleableCheck(); ?>
1212

13-
<div class="field admin__field options<?php if ($_option->getRequired()) { echo ' required _required'; } ?>">
13+
<div class="field admin__field options<?php if ($_option->getRequired()) { echo ' _required'; } ?>">
1414
<label class="label admin__field-label">
1515
<span><?= $block->escapeHtml($_option->getTitle()) ?></span>
1616
</label>

app/code/Magento/Bundle/view/adminhtml/templates/product/composite/fieldset/options/type/multi.phtml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
<?php $_option = $block->getOption(); ?>
1010
<?php $_selections = $_option->getSelections(); ?>
1111
<?php $_skipSaleableCheck = $this->helper(Magento\Catalog\Helper\Product::class)->getSkipSaleableCheck(); ?>
12-
<div class="field admin__field <?php if ($_option->getRequired()) { echo ' required'; } ?><?php if ($_option->getDecoratedIsLast()) :?> last<?php endif; ?>">
12+
<div class="field admin__field <?php if ($_option->getRequired()) { echo ' _required'; } ?><?php if ($_option->getDecoratedIsLast()) :?> last<?php endif; ?>">
1313
<label class="label admin__field-label"><span><?= $block->escapeHtml($_option->getTitle()) ?></span></label>
1414
<div class="control admin__field-control">
1515
<?php if (count($_selections) == 1 && $_option->getRequired()) : ?>

app/code/Magento/Bundle/view/adminhtml/templates/product/composite/fieldset/options/type/radio.phtml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
<?php $_skipSaleableCheck = $this->helper(Magento\Catalog\Helper\Product::class)->getSkipSaleableCheck(); ?>
1313
<?php list($_defaultQty, $_canChangeQty) = $block->getDefaultValues(); ?>
1414

15-
<div class="field admin__field options<?php if ($_option->getRequired()) { echo ' required'; } ?>">
15+
<div class="field admin__field options<?php if ($_option->getRequired()) { echo ' _required'; } ?>">
1616
<label class="label admin__field-label"><span><?= $block->escapeHtml($_option->getTitle()) ?></span></label>
1717
<div class="control admin__field-control">
1818
<div class="nested<?php if ($_option->getDecoratedIsLast()) :?> last<?php endif; ?>">
@@ -39,7 +39,7 @@
3939
<?php foreach ($_selections as $_selection) : ?>
4040
<div class="field choice admin__field admin__field-option">
4141
<input type="radio"
42-
class="radio admin__control-radio <?= $_option->getRequired() ? ' validate-one-required-by-name' : '' ?> change-container-classname"
42+
class="radio admin__control-radio <?= $_option->getRequired() ? ' required-entry' : '' ?> change-container-classname"
4343
id="bundle-option-<?= $block->escapeHtmlAttr($_option->getId()) ?>-<?= $block->escapeHtmlAttr($_selection->getSelectionId()) ?>"
4444
name="bundle_option[<?= $block->escapeHtmlAttr($_option->getId()) ?>]"
4545
<?php if ($block->isSelected($_selection)) { echo ' checked="checked"'; } ?>
@@ -66,7 +66,7 @@
6666
</label>
6767
<div class="control admin__field-control"><input <?php if (!$_canChangeQty) { echo ' disabled="disabled"'; } ?>
6868
id="bundle-option-<?= $block->escapeHtmlAttr($_option->getId()) ?>-qty-input"
69-
class="input-text admin__control-text qty<?php if (!$_canChangeQty) { echo ' qty-disabled'; } ?>"
69+
class="input-text admin__control-text qty validate-greater-than-zero<?php if (!$_canChangeQty) { echo ' qty-disabled'; } ?>"
7070
type="text"
7171
name="bundle_option_qty[<?= $block->escapeHtmlAttr($_option->getId()) ?>]"
7272
value="<?= $block->escapeHtmlAttr($_defaultQty) ?>" />

app/code/Magento/Bundle/view/adminhtml/templates/product/composite/fieldset/options/type/select.phtml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
<?php $_skipSaleableCheck = $this->helper(Magento\Catalog\Helper\Product::class)->getSkipSaleableCheck(); ?>
1313
<?php list($_defaultQty, $_canChangeQty) = $block->getDefaultValues(); ?>
1414

15-
<div class="field admin__field option<?php if ($_option->getDecoratedIsLast()) :?> last<?php endif; ?><?php if ($_option->getRequired()) { echo ' required _required'; } ?>">
15+
<div class="field admin__field option<?php if ($_option->getDecoratedIsLast()) :?> last<?php endif; ?><?php if ($_option->getRequired()) { echo ' _required'; } ?>">
1616
<label class="label admin__field-label"><span><?= $block->escapeHtml($_option->getTitle()) ?></span></label>
1717
<div class="control admin__field-control">
1818
<?php if ($block->showSingle()) : ?>
@@ -49,7 +49,7 @@
4949
<div class="control admin__field-control">
5050
<input <?php if (!$_canChangeQty) { echo ' disabled="disabled"'; } ?>
5151
id="bundle-option-<?= $block->escapeHtmlAttr($_option->getId()) ?>-qty-input"
52-
class="input-text admin__control-text qty<?php if (!$_canChangeQty) { echo ' qty-disabled'; } ?>"
52+
class="input-text admin__control-text qty validate-greater-than-zero<?php if (!$_canChangeQty) { echo ' qty-disabled'; } ?>"
5353
type="text"
5454
name="bundle_option_qty[<?= $block->escapeHtmlAttr($_option->getId()) ?>]"
5555
value="<?= $block->escapeHtmlAttr($_defaultQty) ?>" />
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
namespace Magento\Captcha\Test\Unit\CustomerData;
10+
11+
use Magento\Captcha\Helper\Data as CaptchaHelper;
12+
use Magento\Customer\Model\Session as CustomerSession;
13+
use Magento\Captcha\CustomerData\Captcha;
14+
use Magento\Captcha\Model\DefaultModel;
15+
use Magento\Customer\Api\Data\CustomerInterface as CustomerData;
16+
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper;
17+
use PHPUnit\Framework\TestCase;
18+
19+
class CaptchaTest extends TestCase
20+
{
21+
/**
22+
* @var CaptchaHelper|\PHPUnit_Framework_MockObject_MockObject
23+
*/
24+
private $helperMock;
25+
26+
/**
27+
* @var CustomerSession|\PHPUnit_Framework_MockObject_MockObject
28+
*/
29+
private $customerSessionMock;
30+
31+
/**
32+
* @var Captcha
33+
*/
34+
private $model;
35+
36+
/**
37+
* @var array
38+
*/
39+
private $formIds;
40+
41+
/**
42+
* @var ObjectManagerHelper
43+
*/
44+
protected $objectManagerHelper;
45+
46+
/**
47+
* Create mocks and model
48+
*/
49+
protected function setUp()
50+
{
51+
$this->helperMock = $this->createMock(CaptchaHelper::class);
52+
$this->customerSessionMock = $this->createMock(CustomerSession::class);
53+
$this->formIds = [
54+
'user_login'
55+
];
56+
$this->objectManagerHelper = new ObjectManagerHelper($this);
57+
$this->model = $this->objectManagerHelper->getObject(
58+
Captcha::class,
59+
[
60+
'helper' => $this->helperMock,
61+
'formIds' => $this->formIds,
62+
'customerSession' => $this->customerSessionMock
63+
]
64+
);
65+
}
66+
67+
/**
68+
* Test getSectionData() when user is login and require captcha
69+
*/
70+
public function testGetSectionDataWhenLoginAndRequireCaptcha()
71+
{
72+
$emailLogin = '[email protected]';
73+
74+
$userLoginModel = $this->createMock(DefaultModel::class);
75+
$userLoginModel->expects($this->any())->method('isRequired')->with($emailLogin)
76+
->willReturn(true);
77+
$this->helperMock->expects($this->any())->method('getCaptcha')->with('user_login')->willReturn($userLoginModel);
78+
79+
$this->customerSessionMock->expects($this->any())->method('isLoggedIn')
80+
->willReturn(true);
81+
82+
$customerDataMock = $this->createMock(CustomerData::class);
83+
$customerDataMock->expects($this->any())->method('getEmail')->willReturn($emailLogin);
84+
$this->customerSessionMock->expects($this->any())->method('getCustomerData')
85+
->willReturn($customerDataMock);
86+
87+
/* Assert to test */
88+
$this->assertEquals(
89+
[
90+
"user_login" => [
91+
"isRequired" => true,
92+
"timestamp" => time()
93+
]
94+
],
95+
$this->model->getSectionData()
96+
);
97+
}
98+
}

app/code/Magento/Catalog/Block/Adminhtml/Category/Tree.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,7 @@ protected function _getNodeJson($node, $level = 0)
407407
public function buildNodeName($node)
408408
{
409409
$result = $this->escapeHtml($node->getName());
410+
$result .= ' (ID: ' . $node->getId() . ')';
410411
if ($this->_withProductCount) {
411412
$result .= ' (' . $node->getProductCount() . ')';
412413
}

app/code/Magento/Catalog/Model/Indexer/Category/Product.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,10 +137,11 @@ protected function executeAction($ids)
137137

138138
/** @var Product\Action\Rows $action */
139139
$action = $this->rowsActionFactory->create();
140-
if ($indexer->isWorking()) {
140+
if ($indexer->isScheduled()) {
141141
$action->execute($ids, true);
142+
} else {
143+
$action->execute($ids);
142144
}
143-
$action->execute($ids);
144145

145146
return $this;
146147
}

app/code/Magento/Catalog/Model/Indexer/Category/Product/Action/Rows.php

Lines changed: 103 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,24 @@
55
*/
66
namespace Magento\Catalog\Model\Indexer\Category\Product\Action;
77

8+
use Magento\Framework\DB\Adapter\AdapterInterface;
9+
use Magento\Framework\Indexer\CacheContext;
10+
use Magento\Framework\Event\ManagerInterface as EventManagerInterface;
11+
use Magento\Framework\App\ObjectManager;
12+
use Magento\Framework\App\ResourceConnection;
13+
use Magento\Store\Model\StoreManagerInterface;
14+
use Magento\Framework\DB\Query\Generator as QueryGenerator;
15+
use Magento\Framework\EntityManager\MetadataPool;
16+
use Magento\Catalog\Model\Config;
17+
use Magento\Catalog\Model\Category;
18+
use Magento\Framework\Indexer\IndexerRegistry;
19+
use Magento\Catalog\Model\Indexer\Product\Category as ProductCategoryIndexer;
20+
821
/**
922
* Reindex multiple rows action.
1023
*
1124
* @package Magento\Catalog\Model\Indexer\Category\Product\Action
25+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
1226
*/
1327
class Rows extends \Magento\Catalog\Model\Indexer\Category\Product\AbstractAction
1428
{
@@ -19,12 +33,54 @@ class Rows extends \Magento\Catalog\Model\Indexer\Category\Product\AbstractActio
1933
*/
2034
protected $limitationByCategories;
2135

36+
/**
37+
* @var CacheContext
38+
*/
39+
private $cacheContext;
40+
41+
/**
42+
* @var EventManagerInterface|null
43+
*/
44+
private $eventManager;
45+
46+
/**
47+
* @var IndexerRegistry
48+
*/
49+
private $indexerRegistry;
50+
51+
/**
52+
* @param ResourceConnection $resource
53+
* @param StoreManagerInterface $storeManager
54+
* @param Config $config
55+
* @param QueryGenerator|null $queryGenerator
56+
* @param MetadataPool|null $metadataPool
57+
* @param CacheContext|null $cacheContext
58+
* @param EventManagerInterface|null $eventManager
59+
* @param IndexerRegistry|null $indexerRegistry
60+
*/
61+
public function __construct(
62+
ResourceConnection $resource,
63+
StoreManagerInterface $storeManager,
64+
Config $config,
65+
QueryGenerator $queryGenerator = null,
66+
MetadataPool $metadataPool = null,
67+
CacheContext $cacheContext = null,
68+
EventManagerInterface $eventManager = null,
69+
IndexerRegistry $indexerRegistry = null
70+
) {
71+
parent::__construct($resource, $storeManager, $config, $queryGenerator, $metadataPool);
72+
$this->cacheContext = $cacheContext ?: ObjectManager::getInstance()->get(CacheContext::class);
73+
$this->eventManager = $eventManager ?: ObjectManager::getInstance()->get(EventManagerInterface::class);
74+
$this->indexerRegistry = $indexerRegistry ?: ObjectManager::getInstance()->get(IndexerRegistry::class);
75+
}
76+
2277
/**
2378
* Refresh entities index
2479
*
2580
* @param int[] $entityIds
2681
* @param bool $useTempTable
2782
* @return $this
83+
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
2884
*/
2985
public function execute(array $entityIds = [], $useTempTable = false)
3086
{
@@ -40,12 +96,58 @@ public function execute(array $entityIds = [], $useTempTable = false)
4096
}
4197
$this->limitationByCategories = array_unique($this->limitationByCategories);
4298
$this->useTempTable = $useTempTable;
43-
$this->removeEntries();
99+
$indexer = $this->indexerRegistry->get(ProductCategoryIndexer::INDEXER_ID);
100+
$workingState = $indexer->isWorking();
101+
102+
if ($useTempTable && !$workingState && $indexer->isScheduled()) {
103+
foreach ($this->storeManager->getStores() as $store) {
104+
$this->connection->truncateTable($this->getIndexTable($store->getId()));
105+
}
106+
} else {
107+
$this->removeEntries();
108+
}
109+
44110
$this->reindex();
45111

112+
if ($useTempTable && !$workingState && $indexer->isScheduled()) {
113+
foreach ($this->storeManager->getStores() as $store) {
114+
$removalCategoryIds = array_diff($this->limitationByCategories, [$this->getRootCategoryId($store)]);
115+
$this->connection->delete(
116+
$this->tableMaintainer->getMainTable($store->getId()),
117+
['category_id IN (?)' => $removalCategoryIds]
118+
);
119+
$select = $this->connection->select()
120+
->from($this->tableMaintainer->getMainReplicaTable($store->getId()));
121+
$this->connection->query(
122+
$this->connection->insertFromSelect(
123+
$select,
124+
$this->tableMaintainer->getMainTable($store->getId()),
125+
[],
126+
AdapterInterface::INSERT_ON_DUPLICATE
127+
)
128+
);
129+
}
130+
}
131+
132+
$this->registerCategories($entityIds);
133+
$this->eventManager->dispatch('clean_cache_by_tags', ['object' => $this->cacheContext]);
134+
46135
return $this;
47136
}
48137

138+
/**
139+
* Register categories assigned to products
140+
*
141+
* @param array $categoryIds
142+
* @return void
143+
*/
144+
private function registerCategories(array $categoryIds)
145+
{
146+
if ($categoryIds) {
147+
$this->cacheContext->registerEntities(Category::CACHE_TAG, $categoryIds);
148+
}
149+
}
150+
49151
/**
50152
* Return array of all category root IDs + tree root ID
51153
*

0 commit comments

Comments
 (0)