Skip to content

Commit 21e1ad0

Browse files
[Magento Community Engineering] Community Contributions - 2.4-develop
- merged latest code from mainline branch
2 parents 4109919 + a08fd19 commit 21e1ad0

File tree

32 files changed

+979
-62
lines changed

32 files changed

+979
-62
lines changed

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,19 @@ public function process($maxNumberOfMessages = null)
6969
$this->registry->register('isSecureArea', true, true);
7070

7171
$queue = $this->configuration->getQueue();
72+
$maxIdleTime = $this->configuration->getMaxIdleTime();
73+
$sleep = $this->configuration->getSleep();
7274

7375
if (!isset($maxNumberOfMessages)) {
7476
$queue->subscribe($this->getTransactionCallback($queue));
7577
} else {
76-
$this->invoker->invoke($queue, $maxNumberOfMessages, $this->getTransactionCallback($queue));
78+
$this->invoker->invoke(
79+
$queue,
80+
$maxNumberOfMessages,
81+
$this->getTransactionCallback($queue),
82+
$maxIdleTime,
83+
$sleep
84+
);
7785
}
7886

7987
$this->registry->unregister('isSecureArea');

app/code/Magento/Cms/Model/Wysiwyg/Images/Storage.php

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -628,8 +628,12 @@ public function resizeFile($source, $keepRatio = true)
628628
}
629629
$image = $this->_imageFactory->create();
630630
$image->open($source);
631+
631632
$image->keepAspectRatio($keepRatio);
632-
$image->resize($this->_resizeParameters['width'], $this->_resizeParameters['height']);
633+
634+
list($imageWidth, $imageHeight) = $this->getResizedParams($source);
635+
636+
$image->resize($imageWidth, $imageHeight);
633637
$dest = $targetDir . '/' . $this->ioFile->getPathInfo($source)['basename'];
634638
$image->save($dest);
635639
if ($this->_directory->isFile($this->_directory->getRelativePath($dest))) {
@@ -638,6 +642,29 @@ public function resizeFile($source, $keepRatio = true)
638642
return false;
639643
}
640644

645+
/**
646+
* Return width height for the image resizing.
647+
*
648+
* @param string $source
649+
* @return array
650+
*/
651+
private function getResizedParams(string $source): array
652+
{
653+
$configWidth = $this->_resizeParameters['width'];
654+
$configHeight = $this->_resizeParameters['height'];
655+
656+
//phpcs:ignore Generic.PHP.NoSilencedErrors
657+
list($imageWidth, $imageHeight) = @getimagesize($source);
658+
659+
if ($imageWidth && $imageHeight) {
660+
$imageWidth = $configWidth > $imageWidth ? $imageWidth : $configWidth;
661+
$imageHeight = $configHeight > $imageHeight ? $imageHeight : $configHeight;
662+
663+
return [$imageWidth, $imageHeight];
664+
}
665+
return [$configWidth, $configHeight];
666+
}
667+
641668
/**
642669
* Resize images on the fly in controller action
643670
*
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\MessageQueue\Model;
9+
10+
use Magento\Framework\MessageQueue\QueueRepository;
11+
12+
/**
13+
* Class CheckIsAvailableMessagesInQueue for checking messages available in queue
14+
*/
15+
class CheckIsAvailableMessagesInQueue
16+
{
17+
/**
18+
* @var QueueRepository
19+
*/
20+
private $queueRepository;
21+
22+
/**
23+
* Initialize dependencies.
24+
*
25+
* @param QueueRepository $queueRepository
26+
*/
27+
public function __construct(QueueRepository $queueRepository)
28+
{
29+
$this->queueRepository = $queueRepository;
30+
}
31+
32+
/**
33+
* Checks if there is available messages in the queue
34+
*
35+
* @param string $connectionName connection name
36+
* @param string $queueName queue name
37+
* @return bool
38+
* @throws \LogicException if queue is not available
39+
*/
40+
public function execute($connectionName, $queueName)
41+
{
42+
$queue = $this->queueRepository->get($connectionName, $queueName);
43+
$message = $queue->dequeue();
44+
if ($message) {
45+
$queue->reject($message);
46+
return true;
47+
}
48+
return false;
49+
}
50+
}

app/code/Magento/MessageQueue/Model/Cron/ConsumersRunner.php

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Psr\Log\LoggerInterface;
1515
use Symfony\Component\Process\PhpExecutableFinder;
1616
use Magento\Framework\Lock\LockManagerInterface;
17+
use Magento\MessageQueue\Model\CheckIsAvailableMessagesInQueue;
1718

1819
/**
1920
* Class for running consumers processes by cron
@@ -65,6 +66,11 @@ class ConsumersRunner
6566
*/
6667
private $lockManager;
6768

69+
/**
70+
* @var CheckIsAvailableMessagesInQueue
71+
*/
72+
private $checkIsAvailableMessages;
73+
6874
/**
6975
* @param PhpExecutableFinder $phpExecutableFinder The executable finder specifically designed
7076
* for the PHP executable
@@ -74,6 +80,7 @@ class ConsumersRunner
7480
* @param LockManagerInterface $lockManager The lock manager
7581
* @param ConnectionTypeResolver $mqConnectionTypeResolver Consumer connection resolver
7682
* @param LoggerInterface $logger Logger
83+
* @param CheckIsAvailableMessagesInQueue $checkIsAvailableMessages
7784
*/
7885
public function __construct(
7986
PhpExecutableFinder $phpExecutableFinder,
@@ -82,7 +89,8 @@ public function __construct(
8289
ShellInterface $shellBackground,
8390
LockManagerInterface $lockManager,
8491
ConnectionTypeResolver $mqConnectionTypeResolver = null,
85-
LoggerInterface $logger = null
92+
LoggerInterface $logger = null,
93+
CheckIsAvailableMessagesInQueue $checkIsAvailableMessages = null
8694
) {
8795
$this->phpExecutableFinder = $phpExecutableFinder;
8896
$this->consumerConfig = $consumerConfig;
@@ -93,6 +101,8 @@ public function __construct(
93101
?: ObjectManager::getInstance()->get(ConnectionTypeResolver::class);
94102
$this->logger = $logger
95103
?: ObjectManager::getInstance()->get(LoggerInterface::class);
104+
$this->checkIsAvailableMessages = $checkIsAvailableMessages
105+
?: ObjectManager::getInstance()->get(CheckIsAvailableMessagesInQueue::class);
96106
}
97107

98108
/**
@@ -166,6 +176,25 @@ private function canBeRun(ConsumerConfigItemInterface $consumerConfig, array $al
166176
return false;
167177
}
168178

179+
if ($consumerConfig->getOnlySpawnWhenMessageAvailable()) {
180+
try {
181+
return $this->checkIsAvailableMessages->execute(
182+
$connectionName,
183+
$consumerConfig->getQueue()
184+
);
185+
} catch (\LogicException $e) {
186+
$this->logger->info(
187+
sprintf(
188+
'Consumer "%s" skipped as its related queue "%s" is not available. %s',
189+
$consumerName,
190+
$consumerConfig->getQueue(),
191+
$e->getMessage()
192+
)
193+
);
194+
return false;
195+
}
196+
}
197+
169198
return true;
170199
}
171200
}

app/code/Magento/MessageQueue/Test/Unit/Model/Cron/ConsumersRunnerTest.php

Lines changed: 104 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Magento\Framework\MessageQueue\Consumer\ConfigInterface as ConsumerConfigInterface;
1515
use Magento\Framework\ShellInterface;
1616
use Magento\MessageQueue\Model\Cron\ConsumersRunner;
17+
use Magento\MessageQueue\Model\CheckIsAvailableMessagesInQueue;
1718
use PHPUnit\Framework\MockObject\MockObject;
1819
use PHPUnit\Framework\TestCase;
1920
use Symfony\Component\Process\PhpExecutableFinder;
@@ -48,10 +49,15 @@ class ConsumersRunnerTest extends TestCase
4849
*/
4950
private $phpExecutableFinderMock;
5051

52+
/**
53+
* @var CheckIsAvailableMessagesInQueue|MockObject
54+
*/
55+
private $checkIsAvailableMessagesMock;
56+
5157
/**
5258
* @var ConnectionTypeResolver
5359
*/
54-
private $connectionTypeResover;
60+
private $connectionTypeResolver;
5561

5662
/**
5763
* @var ConsumersRunner
@@ -77,18 +83,21 @@ protected function setUp(): void
7783
$this->deploymentConfigMock = $this->getMockBuilder(DeploymentConfig::class)
7884
->disableOriginalConstructor()
7985
->getMock();
80-
$this->connectionTypeResover = $this->getMockBuilder(ConnectionTypeResolver::class)
86+
$this->checkIsAvailableMessagesMock = $this->createMock(CheckIsAvailableMessagesInQueue::class);
87+
$this->connectionTypeResolver = $this->getMockBuilder(ConnectionTypeResolver::class)
8188
->disableOriginalConstructor()
8289
->getMock();
83-
$this->connectionTypeResover->method('getConnectionType')->willReturn('something');
90+
$this->connectionTypeResolver->method('getConnectionType')->willReturn('something');
8491

8592
$this->consumersRunner = new ConsumersRunner(
8693
$this->phpExecutableFinderMock,
8794
$this->consumerConfigMock,
8895
$this->deploymentConfigMock,
8996
$this->shellBackgroundMock,
9097
$this->lockManagerMock,
91-
$this->connectionTypeResover
98+
$this->connectionTypeResolver,
99+
null,
100+
$this->checkIsAvailableMessagesMock
92101
);
93102
}
94103

@@ -262,4 +271,95 @@ public function runDataProvider()
262271
],
263272
];
264273
}
274+
275+
/**
276+
* @param boolean $onlySpawnWhenMessageAvailable
277+
* @param boolean $isMassagesAvailableInTheQueue
278+
* @param int $shellBackgroundExpects
279+
* @dataProvider runBasedOnOnlySpawnWhenMessageAvailableConsumerConfigurationDataProvider
280+
*/
281+
public function testRunBasedOnOnlySpawnWhenMessageAvailableConsumerConfiguration(
282+
$onlySpawnWhenMessageAvailable,
283+
$isMassagesAvailableInTheQueue,
284+
$shellBackgroundExpects
285+
) {
286+
$consumerName = 'consumerName';
287+
$connectionName = 'connectionName';
288+
$queueName = 'queueName';
289+
$this->deploymentConfigMock->expects($this->exactly(3))
290+
->method('get')
291+
->willReturnMap(
292+
[
293+
['cron_consumers_runner/cron_run', true, true],
294+
['cron_consumers_runner/max_messages', 10000, 1000],
295+
['cron_consumers_runner/consumers', [], []],
296+
]
297+
);
298+
299+
/** @var ConsumerConfigInterface|MockObject $firstCunsumer */
300+
$consumer = $this->getMockBuilder(ConsumerConfigItemInterface::class)
301+
->getMockForAbstractClass();
302+
$consumer->expects($this->any())
303+
->method('getName')
304+
->willReturn($consumerName);
305+
$consumer->expects($this->once())
306+
->method('getConnection')
307+
->willReturn($connectionName);
308+
$consumer->expects($this->any())
309+
->method('getQueue')
310+
->willReturn($queueName);
311+
$consumer->expects($this->once())
312+
->method('getOnlySpawnWhenMessageAvailable')
313+
->willReturn($onlySpawnWhenMessageAvailable);
314+
$this->consumerConfigMock->expects($this->once())
315+
->method('getConsumers')
316+
->willReturn([$consumer]);
317+
318+
$this->phpExecutableFinderMock->expects($this->once())
319+
->method('find')
320+
->willReturn('');
321+
322+
$this->lockManagerMock->expects($this->once())
323+
->method('isLocked')
324+
->willReturn(false);
325+
326+
$this->checkIsAvailableMessagesMock->expects($this->exactly((int)$onlySpawnWhenMessageAvailable))
327+
->method('execute')
328+
->willReturn($isMassagesAvailableInTheQueue);
329+
330+
$this->shellBackgroundMock->expects($this->exactly($shellBackgroundExpects))
331+
->method('execute');
332+
333+
$this->consumersRunner->run();
334+
}
335+
336+
/**
337+
* @return array
338+
*/
339+
public function runBasedOnOnlySpawnWhenMessageAvailableConsumerConfigurationDataProvider()
340+
{
341+
return [
342+
[
343+
'onlySpawnWhenMessageAvailable' => true,
344+
'isMassagesAvailableInTheQueue' => true,
345+
'shellBackgroundExpects' => 1
346+
],
347+
[
348+
'onlySpawnWhenMessageAvailable' => true,
349+
'isMassagesAvailableInTheQueue' => false,
350+
'shellBackgroundExpects' => 0
351+
],
352+
[
353+
'onlySpawnWhenMessageAvailable' => false,
354+
'isMassagesAvailableInTheQueue' => true,
355+
'shellBackgroundExpects' => 1
356+
],
357+
[
358+
'onlySpawnWhenMessageAvailable' => false,
359+
'isMassagesAvailableInTheQueue' => false,
360+
'shellBackgroundExpects' => 1
361+
],
362+
363+
];
364+
}
265365
}

dev/tests/integration/framework/Magento/TestFramework/Workaround/Cleanup/StaticProperties.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ class StaticProperties
4646
\Magento\TestFramework\Annotation\AppIsolation::class,
4747
\Magento\TestFramework\Workaround\Cleanup\StaticProperties::class,
4848
\Magento\Framework\Phrase::class,
49+
\Magento\TestFramework\Workaround\Override\Fixture\ResolverInterface::class,
50+
\Magento\TestFramework\Workaround\Override\ConfigInterface::class,
4951
];
5052

5153
private const CACHE_NAME = 'integration_test_static_properties';
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+
declare(strict_types=1);
7+
8+
use Magento\Catalog\Api\Data\ProductInterface;
9+
use Magento\Catalog\Api\Data\ProductInterfaceFactory;
10+
use Magento\Catalog\Api\ProductRepositoryInterface;
11+
use Magento\Catalog\Helper\DefaultCategory;
12+
use Magento\Catalog\Model\Product\Attribute\Source\Status;
13+
use Magento\Catalog\Model\Product\Type;
14+
use Magento\Catalog\Model\Product\Visibility;
15+
use Magento\Store\Api\WebsiteRepositoryInterface;
16+
use Magento\TestFramework\Helper\Bootstrap;
17+
18+
$objectManager = Bootstrap::getObjectManager();
19+
/** @var WebsiteRepositoryInterface $websiteRepository */
20+
$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class);
21+
$defaultWebsiteId = $websiteRepository->get('base')->getId();
22+
/** @var DefaultCategory $defaultCategory */
23+
$defaultCategory = $objectManager->get(DefaultCategory::class);
24+
/** @var ProductRepositoryInterface $productRepository */
25+
$productRepository = $objectManager->get(ProductRepositoryInterface::class);
26+
/** @var ProductInterfaceFactory $productFactory */
27+
$productFactory = $objectManager->get(ProductInterfaceFactory::class);
28+
$product = $productFactory->create();
29+
$productData = [
30+
ProductInterface::TYPE_ID => Type::TYPE_SIMPLE,
31+
ProductInterface::ATTRIBUTE_SET_ID => $product->getDefaultAttributeSetId(),
32+
ProductInterface::SKU => 'product_disabled',
33+
ProductInterface::NAME => 'Product with category',
34+
ProductInterface::PRICE => 10,
35+
ProductInterface::VISIBILITY => Visibility::VISIBILITY_BOTH,
36+
ProductInterface::STATUS => Status::STATUS_DISABLED,
37+
'website_ids' => [$defaultWebsiteId],
38+
'stock_data' => [
39+
'use_config_manage_stock' => 1,
40+
'qty' => 100,
41+
'is_qty_decimal' => 0,
42+
'is_in_stock' => 1,
43+
],
44+
'category_ids' => [$defaultCategory->getId()],
45+
];
46+
$product->setData($productData);
47+
48+
$productRepository->save($product);

0 commit comments

Comments
 (0)