diff --git a/app/code/Magento/Bundle/Model/Plugin/PriceBackend.php b/app/code/Magento/Bundle/Model/Plugin/PriceBackend.php index 1914d5b5146c3..c55500b8461f3 100644 --- a/app/code/Magento/Bundle/Model/Plugin/PriceBackend.php +++ b/app/code/Magento/Bundle/Model/Plugin/PriceBackend.php @@ -1,18 +1,21 @@ getTypeId() == Configurable::TYPE_CODE - ) { + if ($object instanceof ProductInterface && $object->getTypeId() === Configurable::TYPE_CODE) { return true; - } else { - return $proceed($object); } + + return $proceed($object); } } diff --git a/app/code/Magento/Cron/Observer/ProcessCronQueueObserver.php b/app/code/Magento/Cron/Observer/ProcessCronQueueObserver.php index 857e419fe93f3..14d9a599ae011 100644 --- a/app/code/Magento/Cron/Observer/ProcessCronQueueObserver.php +++ b/app/code/Magento/Cron/Observer/ProcessCronQueueObserver.php @@ -9,6 +9,7 @@ */ namespace Magento\Cron\Observer; +use Laminas\Http\PhpEnvironment\Request as Environment; use Exception; use Magento\Cron\Model\DeadlockRetrierInterface; use Magento\Cron\Model\ResourceModel\Schedule\Collection as ScheduleCollection; @@ -133,6 +134,16 @@ class ProcessCronQueueObserver implements ObserverInterface */ protected $dateTime; + /** + * @var Environment + */ + private Environment $environment; + + /** + * @var string + */ + private string $originalProcessTitle; + /** * @var \Symfony\Component\Process\PhpExecutableFinder */ @@ -189,6 +200,7 @@ class ProcessCronQueueObserver implements ObserverInterface * @param \Magento\Framework\Lock\LockManagerInterface $lockManager * @param \Magento\Framework\Event\ManagerInterface $eventManager * @param DeadlockRetrierInterface $retrier + * @param Environment $environment * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -206,7 +218,8 @@ public function __construct( StatFactory $statFactory, \Magento\Framework\Lock\LockManagerInterface $lockManager, \Magento\Framework\Event\ManagerInterface $eventManager, - DeadlockRetrierInterface $retrier + DeadlockRetrierInterface $retrier, + Environment $environment ) { $this->_objectManager = $objectManager; $this->_scheduleFactory = $scheduleFactory; @@ -216,6 +229,7 @@ public function __construct( $this->_request = $request; $this->_shell = $shell; $this->dateTime = $dateTime; + $this->environment = $environment; $this->phpExecutableFinder = $phpExecutableFinderFactory->create(); $this->logger = $logger; $this->state = $state; @@ -354,6 +368,8 @@ protected function _runJob($scheduledTime, $currentTime, $jobConfig, $schedule, ); } + $this->setProcessTitle($jobCode, $groupId); + $schedule->setExecutedAt(date('Y-m-d H:i:s', $this->dateTime->gmtTimestamp())); $this->retrier->execute( function () use ($schedule) { @@ -944,4 +960,24 @@ function () use ($scheduleResource, $where) { $scheduleResource->getConnection() ); } + + /** + * Set the process title to include the job code and group + * + * @param string $jobCode + * @param string $groupId + */ + private function setProcessTitle(string $jobCode, string $groupId): void + { + if (!isset($this->originalProcessTitle)) { + $this->originalProcessTitle = PHP_BINARY . ' ' . implode(' ', $this->environment->getServer('argv')); + } + + if (strpos($this->originalProcessTitle, " --group=$groupId ") !== false) { + // Group is already shown, so no need to include here in duplicate + cli_set_process_title($this->originalProcessTitle . " # job: $jobCode"); + } else { + cli_set_process_title($this->originalProcessTitle . " # group: $groupId, job: $jobCode"); + } + } } diff --git a/app/code/Magento/Cron/Test/Unit/Observer/ProcessCronQueueObserverTest.php b/app/code/Magento/Cron/Test/Unit/Observer/ProcessCronQueueObserverTest.php index 09e5b9ed8a694..5b91a7930bfa2 100644 --- a/app/code/Magento/Cron/Test/Unit/Observer/ProcessCronQueueObserverTest.php +++ b/app/code/Magento/Cron/Test/Unit/Observer/ProcessCronQueueObserverTest.php @@ -8,6 +8,7 @@ namespace Magento\Cron\Test\Unit\Observer; use Exception; +use Laminas\Http\PhpEnvironment\Request as Environment; use Magento\Cron\Model\Config; use Magento\Cron\Model\DeadlockRetrierInterface; use Magento\Cron\Model\ResourceModel\Schedule as ScheduleResourceModel; @@ -20,8 +21,8 @@ use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\App\Console\Request as ConsoleRequest; use Magento\Framework\App\ObjectManager; -use Magento\Framework\App\State; use Magento\Framework\App\State as AppState; +use Magento\Framework\App\State; use Magento\Framework\DataObject; use Magento\Framework\DB\Adapter\AdapterInterface; use Magento\Framework\Event\ManagerInterface; @@ -219,6 +220,14 @@ protected function setUp(): void $this->retrierMock = $this->getMockForAbstractClass(DeadlockRetrierInterface::class); + $environmentMock = $this->getMockBuilder(Environment::class) + ->disableOriginalConstructor() + ->getMock(); + $environmentMock->expects($this->any()) + ->method('getServer') + ->with('argv') + ->willReturn([]); + $this->cronQueueObserver = new ProcessCronQueueObserver( $this->objectManagerMock, $this->scheduleFactoryMock, @@ -234,7 +243,8 @@ protected function setUp(): void $this->statFactory, $this->lockManagerMock, $this->eventManager, - $this->retrierMock + $this->retrierMock, + $environmentMock ); } diff --git a/app/code/Magento/Store/Model/Store.php b/app/code/Magento/Store/Model/Store.php index 97df81ff6ab7e..b3f19954ab075 100644 --- a/app/code/Magento/Store/Model/Store.php +++ b/app/code/Magento/Store/Model/Store.php @@ -21,6 +21,7 @@ use Magento\Framework\Url\ScopeInterface as UrlScopeInterface; use Magento\Framework\UrlInterface; use Magento\Store\Api\Data\StoreInterface; +use Magento\Store\Model\StoreManager; /** * Store model @@ -760,6 +761,7 @@ protected function _updatePathUseStoreView($url) public function isUseStoreInUrl() { return !($this->hasDisableStoreInUrl() && $this->getDisableStoreInUrl()) + && !$this->getConfig(StoreManager::XML_PATH_SINGLE_STORE_MODE_ENABLED) && $this->getConfig(self::XML_PATH_STORE_IN_URL); } diff --git a/app/code/Magento/Store/Url/Plugin/SecurityInfo.php b/app/code/Magento/Store/Url/Plugin/SecurityInfo.php index bfca3e7341ef2..0de02564c83a4 100644 --- a/app/code/Magento/Store/Url/Plugin/SecurityInfo.php +++ b/app/code/Magento/Store/Url/Plugin/SecurityInfo.php @@ -3,10 +3,12 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Store\Url\Plugin; -use \Magento\Store\Model\Store; -use \Magento\Store\Model\ScopeInterface as StoreScopeInterface; +use Magento\Store\Model\ScopeInterface as StoreScopeInterface; +use Magento\Store\Model\Store; /** * Plugin for \Magento\Framework\Url\SecurityInfo @@ -39,8 +41,8 @@ public function aroundIsSecure(\Magento\Framework\Url\SecurityInfo $subject, \Cl { if ($this->scopeConfig->getValue(Store::XML_PATH_SECURE_IN_FRONTEND, StoreScopeInterface::SCOPE_STORE)) { return $proceed($url); - } else { - return false; } + + return false; } } diff --git a/app/code/Magento/Swatches/Helper/Data.php b/app/code/Magento/Swatches/Helper/Data.php index dd257de331b91..ede204a5e21b8 100644 --- a/app/code/Magento/Swatches/Helper/Data.php +++ b/app/code/Magento/Swatches/Helper/Data.php @@ -6,9 +6,9 @@ namespace Magento\Swatches\Helper; use Magento\Catalog\Api\Data\ProductAttributeMediaGalleryEntryInterface; -use Magento\Catalog\Api\Data\ProductInterface as Product; +use Magento\Catalog\Api\Data\ProductInterface; use Magento\Catalog\Api\ProductRepositoryInterface; -use Magento\Catalog\Model\Product as ModelProduct; +use Magento\Catalog\Model\Product; use Magento\Catalog\Model\Product\Image\UrlBuilder; use Magento\Catalog\Model\ResourceModel\Eav\Attribute; use Magento\Catalog\Model\ResourceModel\Product\Collection as ProductCollection; @@ -23,8 +23,6 @@ use Magento\Swatches\Model\SwatchAttributeType; /** - * Class Helper Data - * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class Data @@ -32,12 +30,12 @@ class Data /** * When we init media gallery empty image types contain this value. */ - const EMPTY_IMAGE_VALUE = 'no_selection'; + public const EMPTY_IMAGE_VALUE = 'no_selection'; /** * The int value of the Default store ID */ - const DEFAULT_STORE_ID = 0; + public const DEFAULT_STORE_ID = 0; /** * @var CollectionFactory @@ -83,8 +81,11 @@ class Data ]; /** - * Serializer to/from JSON. - * + * @var array + */ + private $swatchesCache = []; + + /** * @var Json */ private $serializer; @@ -106,7 +107,7 @@ class Data * @param SwatchCollectionFactory $swatchCollectionFactory * @param UrlBuilder $urlBuilder * @param Json|null $serializer - * @param SwatchAttributesProvider $swatchAttributesProvider + * @param SwatchAttributesProvider|null $swatchAttributesProvider * @param SwatchAttributeType|null $swatchTypeChecker */ public function __construct( @@ -123,12 +124,12 @@ public function __construct( $this->productRepository = $productRepository; $this->storeManager = $storeManager; $this->swatchCollectionFactory = $swatchCollectionFactory; + $this->imageUrlBuilder = $urlBuilder; $this->serializer = $serializer ?: ObjectManager::getInstance()->create(Json::class); $this->swatchAttributesProvider = $swatchAttributesProvider ?: ObjectManager::getInstance()->get(SwatchAttributesProvider::class); $this->swatchTypeChecker = $swatchTypeChecker ?: ObjectManager::getInstance()->create(SwatchAttributeType::class); - $this->imageUrlBuilder = $urlBuilder; } /** @@ -163,11 +164,11 @@ public function assembleAdditionalDataEavAttribute(Attribute $attribute) /** * Check is media attribute available * - * @param ModelProduct $product + * @param Product $product * @param string $attributeCode * @return bool */ - private function isMediaAvailable(ModelProduct $product, string $attributeCode): bool + private function isMediaAvailable(Product $product, string $attributeCode): bool { $isAvailable = false; @@ -186,11 +187,11 @@ private function isMediaAvailable(ModelProduct $product, string $attributeCode): * Load first variation * * @param string $attributeCode swatch_image|image - * @param ModelProduct $configurableProduct + * @param Product $configurableProduct * @param array $requiredAttributes - * @return bool|Product + * @return bool|ProductInterface */ - private function loadFirstVariation($attributeCode, ModelProduct $configurableProduct, array $requiredAttributes) + private function loadFirstVariation($attributeCode, Product $configurableProduct, array $requiredAttributes) { if ($this->isProductHasSwatch($configurableProduct)) { $usedProducts = $configurableProduct->getTypeInstance()->getUsedProducts($configurableProduct); @@ -210,11 +211,11 @@ private function loadFirstVariation($attributeCode, ModelProduct $configurablePr /** * Load first variation with swatch image * - * @param Product $configurableProduct + * @param ProductInterface|Product $configurableProduct * @param array $requiredAttributes - * @return bool|Product + * @return bool|ProductInterface */ - public function loadFirstVariationWithSwatchImage(Product $configurableProduct, array $requiredAttributes) + public function loadFirstVariationWithSwatchImage(ProductInterface $configurableProduct, array $requiredAttributes) { return $this->loadFirstVariation('swatch_image', $configurableProduct, $requiredAttributes); } @@ -222,11 +223,11 @@ public function loadFirstVariationWithSwatchImage(Product $configurableProduct, /** * Load first variation with image * - * @param Product $configurableProduct + * @param ProductInterface|Product $configurableProduct * @param array $requiredAttributes - * @return bool|Product + * @return bool|ProductInterface */ - public function loadFirstVariationWithImage(Product $configurableProduct, array $requiredAttributes) + public function loadFirstVariationWithImage(ProductInterface $configurableProduct, array $requiredAttributes) { return $this->loadFirstVariation('image', $configurableProduct, $requiredAttributes); } @@ -234,11 +235,11 @@ public function loadFirstVariationWithImage(Product $configurableProduct, array /** * Load Variation Product using fallback * - * @param Product $parentProduct + * @param ProductInterface $parentProduct * @param array $attributes - * @return bool|Product + * @return bool|ProductInterface */ - public function loadVariationByFallback(Product $parentProduct, array $attributes) + public function loadVariationByFallback(ProductInterface $parentProduct, array $attributes) { if (!$this->isProductHasSwatch($parentProduct)) { return false; @@ -318,12 +319,12 @@ private function addFilterByParent(ProductCollection $productCollection, $parent * ] * ] * - * @param ModelProduct $product + * @param Product $product * * @return array * @throws \Magento\Framework\Exception\LocalizedException */ - public function getProductMediaGallery(ModelProduct $product): array + public function getProductMediaGallery(Product $product): array { $baseImage = null; $gallery = []; @@ -394,22 +395,21 @@ private function getAllSizeImages($imageFile) /** * Retrieve collection of Swatch attributes * - * @param Product $product + * @param ProductInterface|Product $product * @return \Magento\Catalog\Model\ResourceModel\Eav\Attribute[] */ - private function getSwatchAttributes(Product $product) + private function getSwatchAttributes(ProductInterface $product) { - $swatchAttributes = $this->swatchAttributesProvider->provide($product); - return $swatchAttributes; + return $this->swatchAttributesProvider->provide($product); } /** * Retrieve collection of Eav Attributes from Configurable product * - * @param Product $product + * @param ProductInterface|Product $product * @return \Magento\Catalog\Model\ResourceModel\Eav\Attribute[] */ - public function getAttributesFromConfigurable(Product $product) + public function getAttributesFromConfigurable(ProductInterface $product) { $result = []; $typeInstance = $product->getTypeInstance(); @@ -428,10 +428,10 @@ public function getAttributesFromConfigurable(Product $product) /** * Retrieve all visible Swatch attributes for current product. * - * @param Product $product + * @param ProductInterface $product * @return array */ - public function getSwatchAttributesAsArray(Product $product) + public function getSwatchAttributesAsArray(ProductInterface $product) { $result = []; $swatchAttributes = $this->getSwatchAttributes($product); @@ -447,11 +447,6 @@ public function getSwatchAttributesAsArray(Product $product) return $result; } - /** - * @var array - */ - private $swatchesCache = []; - /** * Get swatch options by option id's according to fallback logic * @@ -511,7 +506,7 @@ private function getCachedSwatches(array $optionIds) private function setCachedSwatches(array $optionIds, array $swatches) { foreach ($optionIds as $optionId) { - $this->swatchesCache[$optionId] = isset($swatches[$optionId]) ? $swatches[$optionId] : null; + $this->swatchesCache[$optionId] = $swatches[$optionId] ?? null; } } @@ -543,10 +538,10 @@ private function addFallbackOptions(array $fallbackValues, array $swatches) /** * Check if the Product has Swatch attributes * - * @param Product $product + * @param ProductInterface $product * @return bool */ - public function isProductHasSwatch(Product $product) + public function isProductHasSwatch(ProductInterface $product) { return !empty($this->getSwatchAttributes($product)); } diff --git a/app/code/Magento/Webapi/Model/Plugin/GuestAuthorization.php b/app/code/Magento/Webapi/Model/Plugin/GuestAuthorization.php index 78082fab8bd9c..31a941ebfea19 100644 --- a/app/code/Magento/Webapi/Model/Plugin/GuestAuthorization.php +++ b/app/code/Magento/Webapi/Model/Plugin/GuestAuthorization.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); namespace Magento\Webapi\Model\Plugin; @@ -11,7 +12,7 @@ /** * Plugin around \Magento\Framework\Authorization::isAllowed * - * Plugin to allow guest users to access resources with anonymous permission + * Allow guest users to access resources with "anonymous" resource */ class GuestAuthorization { @@ -22,8 +23,7 @@ class GuestAuthorization * @param \Closure $proceed * @param string $resource * @param string $privilege - * @return bool true If resource permission is anonymous, - * to allow any user access without further checks in parent method + * @return bool Is resource permission "anonymous", to allow any user access without further checks in parent method * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function aroundIsAllowed( @@ -32,10 +32,10 @@ public function aroundIsAllowed( $resource, $privilege = null ) { - if ($resource == AuthorizationService::PERMISSION_ANONYMOUS) { + if ($resource === AuthorizationService::PERMISSION_ANONYMOUS) { return true; - } else { - return $proceed($resource, $privilege); } + + return $proceed($resource, $privilege); } } diff --git a/app/code/Magento/Widget/Model/ResourceModel/Layout/Plugin.php b/app/code/Magento/Widget/Model/ResourceModel/Layout/Plugin.php index 5525520fa1da0..7a5bd777efe6b 100644 --- a/app/code/Magento/Widget/Model/ResourceModel/Layout/Plugin.php +++ b/app/code/Magento/Widget/Model/ResourceModel/Layout/Plugin.php @@ -1,31 +1,30 @@ update = $update; } /** - * Around getDbUpdateString + * Around update * * @param \Magento\Framework\View\Model\Layout\Merge $subject * @param callable $proceed diff --git a/dev/tests/integration/testsuite/Magento/Store/Model/StoreTest.php b/dev/tests/integration/testsuite/Magento/Store/Model/StoreTest.php index d81a6fa52ea48..bd83561a8a324 100644 --- a/dev/tests/integration/testsuite/Magento/Store/Model/StoreTest.php +++ b/dev/tests/integration/testsuite/Magento/Store/Model/StoreTest.php @@ -446,10 +446,11 @@ public function saveValidationDataProvider() /** * @param $storeInUrl * @param $disableStoreInUrl + * @param $singleStoreModeEnabled * @param $expectedResult * @dataProvider isUseStoreInUrlDataProvider */ - public function testIsUseStoreInUrl($storeInUrl, $disableStoreInUrl, $expectedResult) + public function testIsUseStoreInUrl($storeInUrl, $disableStoreInUrl, $singleStoreModeEnabled, $expectedResult) { $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); $configMock = $this->createMock(\Magento\Framework\App\Config\ReinitableConfigInterface::class); @@ -459,10 +460,13 @@ public function testIsUseStoreInUrl($storeInUrl, $disableStoreInUrl, $expectedRe $params['context'] = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() ->create(\Magento\Framework\Model\Context::class, ['appState' => $appStateMock]); - $configMock->expects($this->any()) + $configMock ->method('getValue') - ->with($this->stringContains(Store::XML_PATH_STORE_IN_URL)) - ->willReturn($storeInUrl); + ->withConsecutive( + [$this->stringContains(StoreManager::XML_PATH_SINGLE_STORE_MODE_ENABLED)], + [$this->stringContains(Store::XML_PATH_STORE_IN_URL)] + ) + ->willReturnOnConsecutiveCalls($singleStoreModeEnabled, $storeInUrl); $params['config'] = $configMock; $model = $objectManager->create(\Magento\Store\Model\Store::class, $params); @@ -477,10 +481,14 @@ public function testIsUseStoreInUrl($storeInUrl, $disableStoreInUrl, $expectedRe public function isUseStoreInUrlDataProvider() { return [ - [true, null, true], - [false, null, false], - [true, true, false], - [true, false, true] + [true, null, false, true], + [false, null, false, false], + [true, true, false, false], + [true, false, false, true], + [true, null, true, false], + [false, null, true, false], + [true, true, true, false], + [true, false, true, false] ]; } diff --git a/lib/internal/Magento/Framework/MessageQueue/Test/Unit/Topology/Config/QueueConfigItem/DataMapperTest.php b/lib/internal/Magento/Framework/MessageQueue/Test/Unit/Topology/Config/QueueConfigItem/DataMapperTest.php index 46ea82b887db6..80987d762152b 100644 --- a/lib/internal/Magento/Framework/MessageQueue/Test/Unit/Topology/Config/QueueConfigItem/DataMapperTest.php +++ b/lib/internal/Magento/Framework/MessageQueue/Test/Unit/Topology/Config/QueueConfigItem/DataMapperTest.php @@ -14,6 +14,7 @@ use Magento\Framework\MessageQueue\Rpc\ResponseQueueNameBuilder; use Magento\Framework\MessageQueue\Topology\Config\Data; use Magento\Framework\MessageQueue\Topology\Config\QueueConfigItem\DataMapper; +use Magento\Framework\Phrase; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; @@ -289,4 +290,46 @@ public function testGetMappedDataForWildcard(): void ]; $this->assertEquals($expectedResult, $actualResult); } + + /** + * @return void + */ + public function testTopicIsSynchronousException(): void + { + $topicName = 'topic01'; + $data = [ + 'ex01' => [ + 'name' => 'ex01', + 'type' => 'topic', + 'connection' => 'amqp', + 'durable' => true, + 'internal' => false, + 'autoDelete' => false, + 'arguments' => ['some' => 'argument'], + 'bindings' => [ + 'bind01' => [ + 'id' => 'bind01', + 'topic' => $topicName, + 'destinationType' => 'queue', + 'destination' => 'some.queue', + 'disabled' => false, + 'arguments' => ['some' => 'arguments'], + ], + ], + ], + ]; + + $this->communicationConfigMock->expects($this->exactly(1)) + ->method('getTopic') + ->willThrowException(new LocalizedException( + new Phrase('Topic "%topic" is not configured.', ['topic' => $topicName]) + )); + + $this->configDataMock->expects($this->once())->method('get')->willReturn($data); + + $this->expectException(LocalizedException::class); + $this->expectExceptionMessage(sprintf('Error while checking if topic "%s" is synchronous', $topicName)); + + $this->model->getMappedData(); + } } diff --git a/lib/internal/Magento/Framework/MessageQueue/Topology/Config/QueueConfigItem/DataMapper.php b/lib/internal/Magento/Framework/MessageQueue/Topology/Config/QueueConfigItem/DataMapper.php index 912aa4a6b0fb1..8e17c45587ee5 100644 --- a/lib/internal/Magento/Framework/MessageQueue/Topology/Config/QueueConfigItem/DataMapper.php +++ b/lib/internal/Magento/Framework/MessageQueue/Topology/Config/QueueConfigItem/DataMapper.php @@ -145,7 +145,9 @@ private function isSynchronousTopic(string $topicName): bool $topic = $this->communicationConfig->getTopic($topicName); return (bool)$topic[CommunicationConfig::TOPIC_IS_SYNCHRONOUS]; } catch (LocalizedException $exception) { - throw new LocalizedException(new Phrase('Error while checking if topic is synchronous')); + throw new LocalizedException( + new Phrase('Error while checking if topic "%topic" is synchronous', ['topic' => $topicName]) + ); } } diff --git a/lib/internal/Magento/Framework/View/Layout/etc/elements.xsd b/lib/internal/Magento/Framework/View/Layout/etc/elements.xsd index e1bdfb81fd732..fd674063efca7 100644 --- a/lib/internal/Magento/Framework/View/Layout/etc/elements.xsd +++ b/lib/internal/Magento/Framework/View/Layout/etc/elements.xsd @@ -119,7 +119,7 @@ - +