diff --git a/.github/actions/composer-cache/action.yml b/.github/actions/composer-cache/action.yml new file mode 100644 index 0000000..df3be3f --- /dev/null +++ b/.github/actions/composer-cache/action.yml @@ -0,0 +1,11 @@ +name: 'Cache Composer packages' +runs: + using: 'composite' + steps: + - id: composer-cache + uses: actions/cache@v3 + with: + path: vendor + key: ${{ inputs.runner-os }}-php-${{ hashFiles('**/composer.lock') }} + restore-keys: | + ${{ inputs.runner-os }}-php- \ No newline at end of file diff --git a/.github/workflows/test_extension.yml b/.github/workflows/test_extension.yml new file mode 100644 index 0000000..3a97907 --- /dev/null +++ b/.github/workflows/test_extension.yml @@ -0,0 +1,91 @@ +name: Test Extension + +on: + push: + branches: [ "master", "develop" ] + pull_request: + branches: [ "master", "develop" ] + +permissions: + contents: read + +jobs: + validate-composer: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Validate composer.json and composer.lock + run: composer validate + + build: + + runs-on: ubuntu-latest + + needs: validate-composer + + steps: + - uses: actions/checkout@v3 + - uses: ./.github/actions/composer-cache + + - name: Install dependencies + run: composer install --prefer-dist --no-progress + + PHP-Compatibility: + runs-on: ubuntu-latest + + needs: build + + steps: + - uses: actions/checkout@v3 + - uses: ./.github/actions/composer-cache + + - name: PHP 8.1 compatibility + run: composer sniffer:php8.1 + + Static-tests: + runs-on: ubuntu-latest + + needs: build + + steps: + - uses: actions/checkout@v3 + - uses: ./.github/actions/composer-cache + + - name: phpstan + run: composer phpstan + + - name: sniffer + run: composer sniffer + + - name: mess-detector + run: composer mess-detector + + PHP-Unit: + runs-on: ubuntu-latest + + needs: build + + steps: + - uses: actions/checkout@v3 + - uses: ./.github/actions/composer-cache + + - name: Setup PHP with Xdebug + uses: shivammathur/setup-php@v2 + with: + php-version: '8.1' + coverage: xdebug + + - name: PHP Unit + run: composer test + + - name: phpunit-coverage-badge + uses: timkrase/phpunit-coverage-badge@v1.2.1 + with: + report: reports/test-reports/clover.xml + coverage_badge_path: output/coverage.svg + push_badge: true + commit_message: "Update coverage badge" + repo_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/README.md b/README.md index 42a5afb..c31c092 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,8 @@ +![Magento 2](https://img.shields.io/badge/Magento-2.5.*-orange) +![PHP](https://img.shields.io/badge/php-8.1-blue) +![packagist](https://img.shields.io/badge/packagist-f28d1a) +![build](https://github.com/run-as-root/magento2-message-queue-retry/actions/workflows/test_extension.yml/badge.svg) + # run-as-root/magento2-message-queue-retry It gives the possibility to process the same queue message more than once, diff --git a/composer.json b/composer.json index c474bd5..ceeb80e 100644 --- a/composer.json +++ b/composer.json @@ -22,13 +22,14 @@ "require-dev": { "phpunit/phpunit": "~9.5.20", "phpmd/phpmd": "^2.13", - "phpstan/phpstan": "^1.6.8", + "phpstan/phpstan": "^1.10", "squizlabs/php_codesniffer": "~3.7.0", "magento/magento-coding-standard": "*", "phpcompatibility/php-compatibility": "^9.3", "slevomat/coding-standard": "^8.8", "sebastian/phpcpd": "^6.0", - "pdepend/pdepend": "^2.13" + "pdepend/pdepend": "^2.13", + "bitexpert/phpstan-magento": "^0.29.0" }, "repositories": [ { @@ -62,6 +63,6 @@ "sniffer": "vendor/bin/phpcs --colors -p ./src --standard=phpcs-ruleset.xml", "fix-style": "vendor/bin/phpcbf --colors -p ./src --standard=phpcs-ruleset.xml", "sniffer:php8.1": "vendor/bin/phpcs -p ./src --standard=vendor/phpcompatibility/php-compatibility/PHPCompatibility --runtime-set testVersion 8.1", - "mess-detector": "vendor/bin/phpmd src html phpmd-ruleset.xml --exclude \"Test\" --strict --reportfile reports/phpmd/phpmd.html" + "mess-detector": "vendor/bin/phpmd src html phpmd-ruleset.xml --exclude \"Test,src/Queue/Consumer.php\" --strict --reportfile reports/phpmd/phpmd.html" } } diff --git a/composer.lock b/composer.lock index e68e6cb..c119f77 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "9d78691ad78f31608f0b6c41d8d9416a", + "content-hash": "9e3b0053939f6607c5999f9e95a97981", "packages": [ { "name": "brick/math", @@ -1920,16 +1920,16 @@ }, { "name": "laminas/laminas-i18n", - "version": "2.22.0", + "version": "2.22.1", "source": { "type": "git", "url": "https://github.com/laminas/laminas-i18n.git", - "reference": "fc13d1314941bd9acda3861883cd9139d747f98f" + "reference": "075bec49f777698c6fc229eecefbe7a2364cd18e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-i18n/zipball/fc13d1314941bd9acda3861883cd9139d747f98f", - "reference": "fc13d1314941bd9acda3861883cd9139d747f98f", + "url": "https://api.github.com/repos/laminas/laminas-i18n/zipball/075bec49f777698c6fc229eecefbe7a2364cd18e", + "reference": "075bec49f777698c6fc229eecefbe7a2364cd18e", "shasum": "" }, "require": { @@ -2002,7 +2002,7 @@ "type": "community_bridge" } ], - "time": "2023-03-12T01:03:50+00:00" + "time": "2023-03-31T12:31:38+00:00" }, { "name": "laminas/laminas-loader", @@ -6681,16 +6681,16 @@ }, { "name": "symfony/console", - "version": "v5.4.21", + "version": "v5.4.22", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "c77433ddc6cdc689caf48065d9ea22ca0853fbd9" + "reference": "3cd51fd2e6c461ca678f84d419461281bd87a0a8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/c77433ddc6cdc689caf48065d9ea22ca0853fbd9", - "reference": "c77433ddc6cdc689caf48065d9ea22ca0853fbd9", + "url": "https://api.github.com/repos/symfony/console/zipball/3cd51fd2e6c461ca678f84d419461281bd87a0a8", + "reference": "3cd51fd2e6c461ca678f84d419461281bd87a0a8", "shasum": "" }, "require": { @@ -6755,12 +6755,12 @@ "homepage": "https://symfony.com", "keywords": [ "cli", - "command line", + "command-line", "console", "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v5.4.21" + "source": "https://github.com/symfony/console/tree/v5.4.22" }, "funding": [ { @@ -6776,7 +6776,7 @@ "type": "tidelift" } ], - "time": "2023-02-25T16:59:41+00:00" + "time": "2023-03-25T09:27:28+00:00" }, { "name": "symfony/deprecation-contracts", @@ -6974,16 +6974,16 @@ }, { "name": "symfony/intl", - "version": "v5.4.21", + "version": "v5.4.22", "source": { "type": "git", "url": "https://github.com/symfony/intl.git", - "reference": "32c2d958b88f5c7f0b080774d7d15d4c87769bc8" + "reference": "8afe56b8472888d749ef8955acdc9d38578775d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/intl/zipball/32c2d958b88f5c7f0b080774d7d15d4c87769bc8", - "reference": "32c2d958b88f5c7f0b080774d7d15d4c87769bc8", + "url": "https://api.github.com/repos/symfony/intl/zipball/8afe56b8472888d749ef8955acdc9d38578775d7", + "reference": "8afe56b8472888d749ef8955acdc9d38578775d7", "shasum": "" }, "require": { @@ -7042,7 +7042,7 @@ "localization" ], "support": { - "source": "https://github.com/symfony/intl/tree/v5.4.21" + "source": "https://github.com/symfony/intl/tree/v5.4.22" }, "funding": [ { @@ -7058,7 +7058,7 @@ "type": "tidelift" } ], - "time": "2023-02-17T21:35:35+00:00" + "time": "2023-03-10T09:58:14+00:00" }, { "name": "symfony/polyfill-ctype", @@ -7796,16 +7796,16 @@ }, { "name": "symfony/process", - "version": "v5.4.21", + "version": "v5.4.22", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "d4ce417ebcb0b7d090b4c178ed6d3accc518e8bd" + "reference": "4b850da0cc3a2a9181c1ed407adbca4733dc839b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/d4ce417ebcb0b7d090b4c178ed6d3accc518e8bd", - "reference": "d4ce417ebcb0b7d090b4c178ed6d3accc518e8bd", + "url": "https://api.github.com/repos/symfony/process/zipball/4b850da0cc3a2a9181c1ed407adbca4733dc839b", + "reference": "4b850da0cc3a2a9181c1ed407adbca4733dc839b", "shasum": "" }, "require": { @@ -7838,7 +7838,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v5.4.21" + "source": "https://github.com/symfony/process/tree/v5.4.22" }, "funding": [ { @@ -7854,7 +7854,7 @@ "type": "tidelift" } ], - "time": "2023-02-21T19:46:44+00:00" + "time": "2023-03-06T21:29:33+00:00" }, { "name": "symfony/service-contracts", @@ -7941,16 +7941,16 @@ }, { "name": "symfony/string", - "version": "v6.2.7", + "version": "v6.2.8", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "67b8c1eec78296b85dc1c7d9743830160218993d" + "reference": "193e83bbd6617d6b2151c37fff10fa7168ebddef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/67b8c1eec78296b85dc1c7d9743830160218993d", - "reference": "67b8c1eec78296b85dc1c7d9743830160218993d", + "url": "https://api.github.com/repos/symfony/string/zipball/193e83bbd6617d6b2151c37fff10fa7168ebddef", + "reference": "193e83bbd6617d6b2151c37fff10fa7168ebddef", "shasum": "" }, "require": { @@ -8007,7 +8007,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.2.7" + "source": "https://github.com/symfony/string/tree/v6.2.8" }, "funding": [ { @@ -8023,7 +8023,7 @@ "type": "tidelift" } ], - "time": "2023-02-24T10:42:00+00:00" + "time": "2023-03-20T16:06:02+00:00" }, { "name": "tedivm/jshrink", @@ -8293,6 +8293,76 @@ } ], "packages-dev": [ + { + "name": "bitexpert/phpstan-magento", + "version": "v0.29.0", + "source": { + "type": "git", + "url": "https://github.com/bitExpert/phpstan-magento.git", + "reference": "61a22ddc30e6149957315dceb3a13396f76e1612" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/bitExpert/phpstan-magento/zipball/61a22ddc30e6149957315dceb3a13396f76e1612", + "reference": "61a22ddc30e6149957315dceb3a13396f76e1612", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "laminas/laminas-code": "~3.3.0 || ~3.4.1 || ~3.5.1 || ^4.5", + "php": "^7.2.0 || ^8.1.0", + "phpstan/phpstan": "~1.10.3", + "symfony/finder": "^3.0 || ^4.0 || ^5.0 || ^6.0" + }, + "conflict": { + "magento/framework": "<102.0.0" + }, + "require-dev": { + "captainhook/captainhook": "^5.10.9", + "captainhook/plugin-composer": "^5.3.3", + "league/commonmark": "^2.3.1", + "madewithlove/license-checker": "^0.10.0 || ^1.4", + "magento/framework": ">=102.0.0", + "mikey179/vfsstream": "^1.6.10", + "nette/neon": "^3.3.3", + "nikic/php-parser": "^4.13.2", + "phpstan/extension-installer": "^1.1.0", + "phpstan/phpstan-phpunit": "^1.1.1", + "phpstan/phpstan-strict-rules": "^1.2.3", + "phpunit/phpunit": "^9.5.20", + "squizlabs/php_codesniffer": "^3.6.2" + }, + "type": "phpstan-extension", + "extra": { + "phpstan": { + "includes": [ + "extension.neon" + ] + } + }, + "autoload": { + "psr-4": { + "bitExpert\\PHPStan\\": "src/bitExpert/PHPStan" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Stephan Hochdörfer", + "email": "S.Hochdoerfer@bitExpert.de", + "homepage": "http://www.bitExpert.de" + } + ], + "description": "PHPStan Magento Extension", + "support": { + "issues": "https://github.com/bitExpert/phpstan-magento/issues", + "source": "https://github.com/bitExpert/phpstan-magento/tree/v0.29.0" + }, + "time": "2023-02-28T07:41:16+00:00" + }, { "name": "dealerdirect/phpcodesniffer-composer-installer", "version": "v1.0.0", @@ -10732,16 +10802,16 @@ }, { "name": "symfony/dependency-injection", - "version": "v6.2.7", + "version": "v6.2.8", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "83369dd4ec84bba9673524d25b79dfbde9e6e84c" + "reference": "b6195feacceb88fc58a02b69522b569e4c6188ac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/83369dd4ec84bba9673524d25b79dfbde9e6e84c", - "reference": "83369dd4ec84bba9673524d25b79dfbde9e6e84c", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/b6195feacceb88fc58a02b69522b569e4c6188ac", + "reference": "b6195feacceb88fc58a02b69522b569e4c6188ac", "shasum": "" }, "require": { @@ -10799,7 +10869,7 @@ "description": "Allows you to standardize and centralize the way objects are constructed in your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dependency-injection/tree/v6.2.7" + "source": "https://github.com/symfony/dependency-injection/tree/v6.2.8" }, "funding": [ { @@ -10815,20 +10885,20 @@ "type": "tidelift" } ], - "time": "2023-02-16T14:11:02+00:00" + "time": "2023-03-30T13:35:57+00:00" }, { "name": "symfony/var-exporter", - "version": "v6.2.7", + "version": "v6.2.8", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "86062dd0103530e151588c8f60f5b85a139f1442" + "reference": "8302bb670204500d492c6b8c595ee9a27da62cd6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/86062dd0103530e151588c8f60f5b85a139f1442", - "reference": "86062dd0103530e151588c8f60f5b85a139f1442", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/8302bb670204500d492c6b8c595ee9a27da62cd6", + "reference": "8302bb670204500d492c6b8c595ee9a27da62cd6", "shasum": "" }, "require": { @@ -10868,12 +10938,12 @@ "export", "hydrate", "instantiate", - "lazy loading", + "lazy-loading", "proxy", "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v6.2.7" + "source": "https://github.com/symfony/var-exporter/tree/v6.2.8" }, "funding": [ { @@ -10889,7 +10959,7 @@ "type": "tidelift" } ], - "time": "2023-02-24T10:42:00+00:00" + "time": "2023-03-14T15:48:45+00:00" }, { "name": "theseer/tokenizer", diff --git a/phpcs-ruleset.xml b/phpcs-ruleset.xml index f51a79a..b450c63 100644 --- a/phpcs-ruleset.xml +++ b/phpcs-ruleset.xml @@ -4,6 +4,7 @@ */Test/* */Tests/* + src/Queue/Consumer.php diff --git a/phpstan.neon.dist b/phpstan.neon.dist index a56b1e2..efd7f43 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -1,7 +1,13 @@ parameters: - level: 5 + level: 8 paths: - src excludePaths: analyseAndScan: - src/Test + - src/Queue/Consumer.php + ignoreErrors: + - '#Method .*construct\(\) has parameter \$data with no value type specified in iterable type array#' + +includes: + - vendor/bitexpert/phpstan-magento/extension.neon diff --git a/src/Controller/Adminhtml/Index/Index.php b/src/Controller/Adminhtml/Index/Index.php index dec7e54..daac323 100644 --- a/src/Controller/Adminhtml/Index/Index.php +++ b/src/Controller/Adminhtml/Index/Index.php @@ -22,9 +22,11 @@ public function __construct( public function execute(): Page { + /** @var \Magento\Backend\Model\View\Result\Page $resultPage */ $resultPage = $this->resultPageFactory->create(); - $resultPage->getConfig()->getTitle()->prepend(__('Messages')); - $resultPage->setActiveMenu(self::ADMIN_RESOURCE); + $resultPage->getConfig()->getTitle()->prepend(__('Messages')->render()); + $resultPage->setActiveMenu('RunAsRoot_MessageQueueRetry::message_queue_retry'); + return $resultPage; } } diff --git a/src/Controller/Adminhtml/Message/MassDelete.php b/src/Controller/Adminhtml/Message/MassDelete.php index 9b4731f..6428f9a 100644 --- a/src/Controller/Adminhtml/Message/MassDelete.php +++ b/src/Controller/Adminhtml/Message/MassDelete.php @@ -9,7 +9,8 @@ use Magento\Framework\Controller\Result\Redirect; use Magento\Framework\Controller\Result\RedirectFactory; use Magento\Ui\Component\MassAction\Filter; -use RunAsRoot\MessageQueueRetry\Model\ResourceModel\Message\CollectionFactory; +use RunAsRoot\MessageQueueRetry\Model\Message; +use RunAsRoot\MessageQueueRetry\Model\ResourceModel\Message\MessageCollectionFactory; use RunAsRoot\MessageQueueRetry\Repository\MessageRepository; class MassDelete extends Action @@ -20,7 +21,7 @@ public function __construct( Context $context, private MessageRepository $messageRepository, private RedirectFactory $redirectFactory, - private CollectionFactory $collectionFactory, + private MessageCollectionFactory $collectionFactory, private Filter $filter ) { parent::__construct($context); @@ -34,13 +35,17 @@ public function execute(): Redirect $collection = $this->filter->getCollection($this->collectionFactory->create()); foreach ($collection->getItems() as $message) { + if (!$message instanceof Message) { + continue; + } + $this->messageRepository->delete($message); } - $this->messageManager->addSuccessMessage(__('The messages have been successfully deleted')); + $this->messageManager->addSuccessMessage(__('The messages have been successfully deleted')->render()); } catch (\Exception $e) { $this->messageManager->addErrorMessage( - __('An error occurred while trying to delete the messages: %1', $e->getMessage()) + __('An error occurred while trying to delete the messages: %1', $e->getMessage())->render() ); } diff --git a/src/Controller/Adminhtml/Message/MassRequeue.php b/src/Controller/Adminhtml/Message/MassRequeue.php index 404e191..fe47589 100644 --- a/src/Controller/Adminhtml/Message/MassRequeue.php +++ b/src/Controller/Adminhtml/Message/MassRequeue.php @@ -9,7 +9,8 @@ use Magento\Framework\Controller\Result\Redirect; use Magento\Framework\Controller\Result\RedirectFactory; use Magento\Ui\Component\MassAction\Filter; -use RunAsRoot\MessageQueueRetry\Model\ResourceModel\Message\CollectionFactory; +use RunAsRoot\MessageQueueRetry\Model\Message; +use RunAsRoot\MessageQueueRetry\Model\ResourceModel\Message\MessageCollectionFactory; use RunAsRoot\MessageQueueRetry\Service\PublishMessageToQueueService; class MassRequeue extends Action @@ -20,7 +21,7 @@ public function __construct( Context $context, private PublishMessageToQueueService $publishMessageToQueueService, private RedirectFactory $redirectFactory, - private CollectionFactory $collectionFactory, + private MessageCollectionFactory $collectionFactory, private Filter $filter ) { parent::__construct($context); @@ -34,13 +35,17 @@ public function execute(): Redirect $collection = $this->filter->getCollection($this->collectionFactory->create()); foreach ($collection->getItems() as $message) { + if (!$message instanceof Message) { + continue; + } + $this->publishMessageToQueueService->executeByMessage($message); } - $this->messageManager->addSuccessMessage(__('Messages queued successfully')); + $this->messageManager->addSuccessMessage(__('Messages queued successfully')->render()); } catch (\Exception $e) { $this->messageManager->addErrorMessage( - __('An error occurred while trying to requeue the message: %1', $e->getMessage()) + __('An error occurred while trying to requeue the message: %1', $e->getMessage())->render() ); } diff --git a/src/Controller/Adminhtml/Message/Requeue.php b/src/Controller/Adminhtml/Message/Requeue.php index 38ef7c4..329a7c4 100644 --- a/src/Controller/Adminhtml/Message/Requeue.php +++ b/src/Controller/Adminhtml/Message/Requeue.php @@ -29,16 +29,16 @@ public function execute(): Redirect $redirect->setPath('message_queue_retry/index/index'); if (!$messageId) { - $this->messageManager->addErrorMessage(__('Invalid message id provided in the request params')); + $this->messageManager->addErrorMessage(__('Invalid message id provided in the request params')->render()); return $redirect; } try { $this->publishMessageToQueueService->executeById($messageId); - $this->messageManager->addSuccessMessage(__('Message queued successfully')); + $this->messageManager->addSuccessMessage(__('Message queued successfully')->render()); } catch (\Exception $e) { $this->messageManager->addErrorMessage( - __('An error occurred while trying to requeue the message: %1', $e->getMessage()) + __('An error occurred while trying to requeue the message: %1', $e->getMessage())->render() ); } diff --git a/src/Exception/InvalidMessageQueueConnectionTypeException.php b/src/Exception/InvalidQueueConnectionTypeException.php similarity index 64% rename from src/Exception/InvalidMessageQueueConnectionTypeException.php rename to src/Exception/InvalidQueueConnectionTypeException.php index f0954ed..c00649d 100644 --- a/src/Exception/InvalidMessageQueueConnectionTypeException.php +++ b/src/Exception/InvalidQueueConnectionTypeException.php @@ -6,6 +6,6 @@ use Magento\Framework\Exception\LocalizedException; -class InvalidMessageQueueConnectionTypeException extends LocalizedException +class InvalidQueueConnectionTypeException extends LocalizedException { } diff --git a/src/Mapper/MessageToRawResponseMapper.php b/src/Mapper/MessageToRawResponseMapper.php index 34cf43a..a9508b2 100644 --- a/src/Mapper/MessageToRawResponseMapper.php +++ b/src/Mapper/MessageToRawResponseMapper.php @@ -34,7 +34,7 @@ public function map(Message $message, RawResponse $rawResponse): RawResponse $rawResponse->setHeader('Pragma', 'public', true); $rawResponse->setHeader('Cache-Control', 'must-revalidate, post-check=0, pre-check=0', true); $rawResponse->setHeader('Content-type', 'application/json', true); - $rawResponse->setHeader('Content-Length', $contentLength, true); + $rawResponse->setHeader('Content-Length', (string)$contentLength, true); $rawResponse->setHeader('Content-Disposition', 'attachment; filename="' . $fileName . '"', true); $rawResponse->setContents($messageBody); diff --git a/src/Model/Config/Backend/QueuesConfig.php b/src/Model/Config/Backend/QueuesConfig.php index 4d2544d..f76b703 100644 --- a/src/Model/Config/Backend/QueuesConfig.php +++ b/src/Model/Config/Backend/QueuesConfig.php @@ -45,6 +45,7 @@ public function __construct( */ public function beforeSave(): self { + /** @var string|array $value */ $value = $this->getValue(); if (!is_array($value)) { diff --git a/src/Model/Message.php b/src/Model/Message.php index 9219f28..a5091b4 100644 --- a/src/Model/Message.php +++ b/src/Model/Message.php @@ -11,12 +11,6 @@ class Message extends AbstractModel implements MessageInterface { - protected function _construct(): void - { - $this->_init(MessageResource::class); - $this->_collectionName = MessageCollection::class; - } - public function getTopicName(): string { return $this->getData(self::TOPIC_NAME); @@ -76,4 +70,10 @@ public function setCreatedAt(string $value): void { $this->setData(self::CREATED_AT, $value); } + + protected function _construct(): void + { + $this->_init(MessageResource::class); + $this->_collectionName = MessageCollection::class; + } } diff --git a/src/Queue/Publisher.php b/src/Queue/Publisher.php index 174728a..2d42044 100644 --- a/src/Queue/Publisher.php +++ b/src/Queue/Publisher.php @@ -8,8 +8,8 @@ use Magento\Framework\MessageQueue\ExchangeRepository; use Magento\Framework\MessageQueue\Publisher\ConfigInterface as PublisherConfig; use Magento\Framework\Phrase; -use RunAsRoot\MessageQueueRetry\Exception\InvalidMessageQueueConnectionTypeException; use RunAsRoot\MessageQueueRetry\Exception\InvalidPublisherConfigurationException; +use RunAsRoot\MessageQueueRetry\Exception\InvalidQueueConnectionTypeException; class Publisher { @@ -22,7 +22,7 @@ public function __construct( /** * @throws InvalidPublisherConfigurationException - * @throws InvalidMessageQueueConnectionTypeException + * @throws InvalidQueueConnectionTypeException */ public function publish(string $topicName, string $data): void { @@ -32,12 +32,12 @@ public function publish(string $topicName, string $data): void try { $connectionName = $this->publisherConfig->getPublisher($topicName)->getConnection()->getName(); } catch (\Exception $e) { - $exceptionMessage = $e->getMessage() instanceof Phrase ? $e->getMessage() : new Phrase($e->getMessage()); + $exceptionMessage = new Phrase($e->getMessage()); throw new InvalidPublisherConfigurationException($exceptionMessage, $e, $e->getCode()); } if ($connectionName !== 'amqp') { - throw new InvalidMessageQueueConnectionTypeException(__('Only AMQP connection is supported.')); + throw new InvalidQueueConnectionTypeException(__('Only AMQP connection is supported.')); } $exchange = $this->exchangeRepository->getByConnectionName($connectionName); @@ -45,6 +45,9 @@ public function publish(string $topicName, string $data): void $exchange->enqueue($topicName, $envelope); } + /** + * @return array + */ private function getEnvelopeData(string $topicName, string $data): array { return [ diff --git a/src/Service/HandleQueueFailureService.php b/src/Service/HandleQueueFailureService.php index 1a5ab0b..802a2ac 100644 --- a/src/Service/HandleQueueFailureService.php +++ b/src/Service/HandleQueueFailureService.php @@ -7,7 +7,7 @@ use Exception; use JsonException; use Magento\Framework\MessageQueue\ConnectionLostException; -use Magento\Framework\MessageQueue\Envelope; +use Magento\Framework\MessageQueue\EnvelopeInterface; use Magento\Framework\MessageQueue\QueueInterface; use PhpAmqpLib\Wire\AMQPTable; use RunAsRoot\MessageQueueRetry\Exception\MessageCouldNotBeCreatedException; @@ -29,7 +29,7 @@ public function __construct( * @throws ConnectionLostException * @throws MessageCouldNotBeCreatedException */ - public function execute(QueueInterface $queue, Envelope $message, Exception $exception): void + public function execute(QueueInterface $queue, EnvelopeInterface $message, Exception $exception): void { if (!$this->messageQueueRetryConfig->isDelayQueueEnabled()) { $queue->reject($message, false, $exception->getMessage()); @@ -94,6 +94,7 @@ private function getTotalRetries(AMQPTable $applicationHeaders): int /** * @throws JsonException + * @return array|null */ private function getQueueConfiguration(string $topicName): ?array { diff --git a/src/Service/PublishMessageToQueueService.php b/src/Service/PublishMessageToQueueService.php index 57743e7..876947f 100644 --- a/src/Service/PublishMessageToQueueService.php +++ b/src/Service/PublishMessageToQueueService.php @@ -4,8 +4,8 @@ namespace RunAsRoot\MessageQueueRetry\Service; -use RunAsRoot\MessageQueueRetry\Exception\InvalidMessageQueueConnectionTypeException; use RunAsRoot\MessageQueueRetry\Exception\InvalidPublisherConfigurationException; +use RunAsRoot\MessageQueueRetry\Exception\InvalidQueueConnectionTypeException; use RunAsRoot\MessageQueueRetry\Exception\MessageCouldNotBeDeletedException; use RunAsRoot\MessageQueueRetry\Exception\MessageNotFoundException; use RunAsRoot\MessageQueueRetry\Model\Message; @@ -23,7 +23,7 @@ public function __construct( /** * @throws MessageCouldNotBeDeletedException * @throws MessageNotFoundException - * @throws InvalidMessageQueueConnectionTypeException + * @throws InvalidQueueConnectionTypeException * @throws InvalidPublisherConfigurationException */ public function executeById(int $messageId): void @@ -36,7 +36,7 @@ public function executeById(int $messageId): void /** * @throws MessageCouldNotBeDeletedException * @throws MessageNotFoundException - * @throws InvalidMessageQueueConnectionTypeException + * @throws InvalidQueueConnectionTypeException * @throws InvalidPublisherConfigurationException */ public function executeByMessage(Message $message): void diff --git a/src/System/Config/MessageQueueRetryConfig.php b/src/System/Config/MessageQueueRetryConfig.php index d33842c..9d9bff6 100644 --- a/src/System/Config/MessageQueueRetryConfig.php +++ b/src/System/Config/MessageQueueRetryConfig.php @@ -25,6 +25,7 @@ public function isDelayQueueEnabled(): bool } /** + * @return array> * @throws JsonException */ public function getDelayQueues(): array @@ -41,10 +42,11 @@ public function getDelayQueues(): array foreach ($configValues as $configValue) { $mainTopicName = $configValue[self::MAIN_TOPIC_NAME] ?? null; + $retryLimit = isset($configValue[self::RETRY_LIMIT]) ? (int)$configValue[self::RETRY_LIMIT] : null; $result[$mainTopicName] = [ self::MAIN_TOPIC_NAME => $mainTopicName, self::DELAY_TOPIC_NAME => $configValue[self::DELAY_TOPIC_NAME] ?? null, - self::RETRY_LIMIT => (int)$configValue[self::RETRY_LIMIT] ?? null, + self::RETRY_LIMIT => $retryLimit, ]; } diff --git a/src/Test/Unit/Controller/Adminhtml/Index/IndexTest.php b/src/Test/Unit/Controller/Adminhtml/Index/IndexTest.php index 54493fb..e23ab7c 100644 --- a/src/Test/Unit/Controller/Adminhtml/Index/IndexTest.php +++ b/src/Test/Unit/Controller/Adminhtml/Index/IndexTest.php @@ -40,7 +40,8 @@ public function testExecute(): void $pageTitleMock = $this->createMock(Title::class); $pageConfigMock->expects($this->once())->method('getTitle')->willReturn($pageTitleMock); $pageTitleMock->expects($this->once())->method('prepend')->with(__('Messages')); - $pageMock->expects($this->once())->method('setActiveMenu')->with('RunAsRoot_MessageQueueRetry::listing'); + $pageMock->expects($this->once())->method('setActiveMenu') + ->with('RunAsRoot_MessageQueueRetry::message_queue_retry'); $result = $this->sut->execute(); diff --git a/src/Test/Unit/Controller/Adminhtml/Message/MassDeleteTest.php b/src/Test/Unit/Controller/Adminhtml/Message/MassDeleteTest.php index 8e6f06e..97be75f 100644 --- a/src/Test/Unit/Controller/Adminhtml/Message/MassDeleteTest.php +++ b/src/Test/Unit/Controller/Adminhtml/Message/MassDeleteTest.php @@ -14,7 +14,7 @@ use RunAsRoot\MessageQueueRetry\Controller\Adminhtml\Message\MassDelete; use RunAsRoot\MessageQueueRetry\Model\Message; use RunAsRoot\MessageQueueRetry\Model\ResourceModel\Message\MessageCollection; -use RunAsRoot\MessageQueueRetry\Model\ResourceModel\Message\CollectionFactory; +use RunAsRoot\MessageQueueRetry\Model\ResourceModel\Message\MessageCollectionFactory; use RunAsRoot\MessageQueueRetry\Repository\MessageRepository; final class MassDeleteTest extends TestCase @@ -22,7 +22,7 @@ final class MassDeleteTest extends TestCase private MassDelete $sut; private RedirectFactory|MockObject $redirectFactoryMock; private MessageRepository|MockObject $messageRepositoryMock; - private CollectionFactory|MockObject $collectionFactoryMock; + private MessageCollectionFactory|MockObject $collectionFactoryMock; private Filter|MockObject $filterMock; private MessageManagerInterface|MockObject $messageManagerMock; @@ -33,7 +33,7 @@ protected function setUp(): void $contextMock->expects($this->once())->method('getMessageManager')->willReturn($this->messageManagerMock); $this->redirectFactoryMock = $this->createMock(RedirectFactory::class); $this->messageRepositoryMock = $this->createMock(MessageRepository::class); - $this->collectionFactoryMock = $this->createMock(CollectionFactory::class); + $this->collectionFactoryMock = $this->createMock(MessageCollectionFactory::class); $this->filterMock = $this->createMock(Filter::class); $this->sut = new MassDelete( diff --git a/src/Test/Unit/Controller/Adminhtml/Message/MassRequeueTest.php b/src/Test/Unit/Controller/Adminhtml/Message/MassRequeueTest.php index 8e21de7..1d4f5d0 100644 --- a/src/Test/Unit/Controller/Adminhtml/Message/MassRequeueTest.php +++ b/src/Test/Unit/Controller/Adminhtml/Message/MassRequeueTest.php @@ -11,12 +11,10 @@ use Magento\Ui\Component\MassAction\Filter; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use RunAsRoot\MessageQueueRetry\Controller\Adminhtml\Message\MassDelete; use RunAsRoot\MessageQueueRetry\Controller\Adminhtml\Message\MassRequeue; use RunAsRoot\MessageQueueRetry\Model\Message; use RunAsRoot\MessageQueueRetry\Model\ResourceModel\Message\MessageCollection; -use RunAsRoot\MessageQueueRetry\Model\ResourceModel\Message\CollectionFactory; -use RunAsRoot\MessageQueueRetry\Repository\MessageRepository; +use RunAsRoot\MessageQueueRetry\Model\ResourceModel\Message\MessageCollectionFactory; use RunAsRoot\MessageQueueRetry\Service\PublishMessageToQueueService; final class MassRequeueTest extends TestCase @@ -24,7 +22,7 @@ final class MassRequeueTest extends TestCase private MassRequeue $sut; private RedirectFactory|MockObject $redirectFactoryMock; private PublishMessageToQueueService|MockObject $publishMessageToQueueServiceMock; - private CollectionFactory|MockObject $collectionFactoryMock; + private MessageCollectionFactory|MockObject $collectionFactoryMock; private Filter|MockObject $filterMock; private MessageManagerInterface|MockObject $messageManagerMock; @@ -35,7 +33,7 @@ protected function setUp(): void $contextMock->expects($this->once())->method('getMessageManager')->willReturn($this->messageManagerMock); $this->redirectFactoryMock = $this->createMock(RedirectFactory::class); $this->publishMessageToQueueServiceMock = $this->createMock(PublishMessageToQueueService::class); - $this->collectionFactoryMock = $this->createMock(CollectionFactory::class); + $this->collectionFactoryMock = $this->createMock(MessageCollectionFactory::class); $this->filterMock = $this->createMock(Filter::class); $this->sut = new MassRequeue( diff --git a/src/Test/Unit/Queue/PublisherTest.php b/src/Test/Unit/Queue/PublisherTest.php index 2975c01..ba960db 100644 --- a/src/Test/Unit/Queue/PublisherTest.php +++ b/src/Test/Unit/Queue/PublisherTest.php @@ -13,7 +13,7 @@ use Magento\Framework\MessageQueue\Publisher\ConfigInterface as PublisherConfig; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use RunAsRoot\MessageQueueRetry\Exception\InvalidMessageQueueConnectionTypeException; +use RunAsRoot\MessageQueueRetry\Exception\InvalidQueueConnectionTypeException; use RunAsRoot\MessageQueueRetry\Exception\InvalidPublisherConfigurationException; use RunAsRoot\MessageQueueRetry\Queue\Publisher; @@ -76,7 +76,7 @@ public function testPublishWithInvalidMessageQueueConnectionType(): void $topicName = 'topic.name'; $data = '{"foo": "bar"}'; - $this->expectException(InvalidMessageQueueConnectionTypeException::class); + $this->expectException(InvalidQueueConnectionTypeException::class); $publisherConfigItemMock = $this->createMock(PublisherConfigItemInterface::class); $this->publisherConfigMock->expects($this->once())->method('getPublisher')->willReturn($publisherConfigItemMock); diff --git a/src/Ui/Component/Listing/Columns/Actions.php b/src/Ui/Component/Listing/Columns/Actions.php index 3562fc2..a4361f3 100644 --- a/src/Ui/Component/Listing/Columns/Actions.php +++ b/src/Ui/Component/Listing/Columns/Actions.php @@ -8,6 +8,10 @@ class Actions extends Column { + /** + * @param array $dataSource + * @return array + */ public function prepareDataSource(array $dataSource): array { $dataSource = parent::prepareDataSource($dataSource); diff --git a/src/Ui/Component/Listing/Columns/MessageBody.php b/src/Ui/Component/Listing/Columns/MessageBody.php index 4057bf1..17eae78 100644 --- a/src/Ui/Component/Listing/Columns/MessageBody.php +++ b/src/Ui/Component/Listing/Columns/MessageBody.php @@ -8,6 +8,10 @@ class MessageBody extends Column { + /** + * @param array $dataSource + * @return array + */ public function prepareDataSource(array $dataSource): array { if (isset($dataSource['data']['items'])) { diff --git a/src/Validator/QueueConfigurationValidator.php b/src/Validator/QueueConfigurationValidator.php index abe5f53..d543bd7 100644 --- a/src/Validator/QueueConfigurationValidator.php +++ b/src/Validator/QueueConfigurationValidator.php @@ -11,6 +11,7 @@ class QueueConfigurationValidator { /** + * @param array $configValues * @throws InvalidQueueConfigurationException */ public function validate(array $configValues): bool @@ -40,6 +41,7 @@ public function validate(array $configValues): bool } /** + * @param array $configValues * @throws InvalidQueueConfigurationException */ private function performUniqueValidation(array $configValues, string $field, string $name): void