From 1b07b0a0100518f2d0623929e1041380583a6411 Mon Sep 17 00:00:00 2001 From: "lee.5151" <lee.5151@osu.edu> Date: Mon, 13 Mar 2023 13:06:22 -0400 Subject: [PATCH] Upgrading drupal/queue_mail (1.4.0 => 1.5.0) --- composer.lock | 52 +++++++-------- vendor/composer/ClassLoader.php | 12 ++-- vendor/composer/autoload_real.php | 6 +- vendor/composer/installed.json | 64 +++++++++---------- vendor/composer/installed.php | 32 +++++----- .../symfony/string/AbstractUnicodeString.php | 4 +- vendor/symfony/string/LICENSE | 2 +- vendor/symfony/var-dumper/Caster/Caster.php | 2 +- .../var-dumper/Caster/ReflectionCaster.php | 2 +- vendor/symfony/var-dumper/LICENSE | 2 +- vendor/symfony/var-exporter/LICENSE | 2 +- vendor/symfony/var-exporter/VarExporter.php | 2 +- web/modules/queue_mail/composer.json | 2 +- .../queue_mail_language.info.yml | 8 +-- .../LanguageAwareSendMailQueueWorker.php | 5 +- .../src/QueueMailLanguageNegotiator.php | 1 - web/modules/queue_mail/queue_mail.info.yml | 8 +-- .../src/Form/QueueMailSettingsForm.php | 10 ++- .../QueueWorker/SendMailQueueWorker.php | 47 +++++++++----- .../queue_mail_test/queue_mail_test.info.yml | 8 +-- .../Functional/QueueMailConfigurationTest.php | 44 ++++++++++--- .../Functional/QueueMailFunctionalTest.php | 63 ++++++++++++++++++ 22 files changed, 247 insertions(+), 131 deletions(-) diff --git a/composer.lock b/composer.lock index a6c2f36a09..b747b53f95 100644 --- a/composer.lock +++ b/composer.lock @@ -6317,26 +6317,26 @@ }, { "name": "drupal/queue_mail", - "version": "1.4.0", + "version": "1.5.0", "source": { "type": "git", "url": "https://git.drupalcode.org/project/queue_mail.git", - "reference": "8.x-1.4" + "reference": "8.x-1.5" }, "dist": { "type": "zip", - "url": "https://ftp.drupal.org/files/projects/queue_mail-8.x-1.4.zip", - "reference": "8.x-1.4", - "shasum": "ccc3603d084017ec4d3aa67fa60da171ef8d63b8" + "url": "https://ftp.drupal.org/files/projects/queue_mail-8.x-1.5.zip", + "reference": "8.x-1.5", + "shasum": "8ee8580c5c76cbde614c955ff2d866f97d7e6e11" }, "require": { - "drupal/core": "^8.8.0 || ^9.0" + "drupal/core": "^9.4 || ^10.0" }, "type": "drupal-module", "extra": { "drupal": { - "version": "8.x-1.4", - "datestamp": "1632316348", + "version": "8.x-1.5", + "datestamp": "1671458599", "security-coverage": { "status": "covered", "message": "Covered by Drupal's security advisory policy" @@ -15488,16 +15488,16 @@ }, { "name": "symfony/string", - "version": "v5.4.19", + "version": "v5.4.21", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "0a01071610fd861cc160dfb7e2682ceec66064cb" + "reference": "edac10d167b78b1d90f46a80320d632de0bd9f2f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/0a01071610fd861cc160dfb7e2682ceec66064cb", - "reference": "0a01071610fd861cc160dfb7e2682ceec66064cb", + "url": "https://api.github.com/repos/symfony/string/zipball/edac10d167b78b1d90f46a80320d632de0bd9f2f", + "reference": "edac10d167b78b1d90f46a80320d632de0bd9f2f", "shasum": "" }, "require": { @@ -15554,7 +15554,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v5.4.19" + "source": "https://github.com/symfony/string/tree/v5.4.21" }, "funding": [ { @@ -15570,7 +15570,7 @@ "type": "tidelift" } ], - "time": "2023-01-01T08:32:19+00:00" + "time": "2023-02-22T08:00:55+00:00" }, { "name": "symfony/translation", @@ -15847,16 +15847,16 @@ }, { "name": "symfony/var-dumper", - "version": "v5.4.19", + "version": "v5.4.21", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "2944bbc23f5f8da2b962fbcbf7c4a6109b2f4b7b" + "reference": "6c5ac3a1be8b849d59a1a77877ee110e1b55eb74" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/2944bbc23f5f8da2b962fbcbf7c4a6109b2f4b7b", - "reference": "2944bbc23f5f8da2b962fbcbf7c4a6109b2f4b7b", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/6c5ac3a1be8b849d59a1a77877ee110e1b55eb74", + "reference": "6c5ac3a1be8b849d59a1a77877ee110e1b55eb74", "shasum": "" }, "require": { @@ -15916,7 +15916,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v5.4.19" + "source": "https://github.com/symfony/var-dumper/tree/v5.4.21" }, "funding": [ { @@ -15932,20 +15932,20 @@ "type": "tidelift" } ], - "time": "2023-01-16T10:52:33+00:00" + "time": "2023-02-23T10:00:28+00:00" }, { "name": "symfony/var-exporter", - "version": "v5.4.19", + "version": "v5.4.21", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "2a1d06fcf2b30829d6c01dae8e6e188424d1f8f6" + "reference": "be74908a6942fdd331554b3cec27ff41b45ccad4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/2a1d06fcf2b30829d6c01dae8e6e188424d1f8f6", - "reference": "2a1d06fcf2b30829d6c01dae8e6e188424d1f8f6", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/be74908a6942fdd331554b3cec27ff41b45ccad4", + "reference": "be74908a6942fdd331554b3cec27ff41b45ccad4", "shasum": "" }, "require": { @@ -15989,7 +15989,7 @@ "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v5.4.19" + "source": "https://github.com/symfony/var-exporter/tree/v5.4.21" }, "funding": [ { @@ -16005,7 +16005,7 @@ "type": "tidelift" } ], - "time": "2023-01-12T16:39:29+00:00" + "time": "2023-02-21T19:46:44+00:00" }, { "name": "symfony/yaml", diff --git a/vendor/composer/ClassLoader.php b/vendor/composer/ClassLoader.php index fd56bd7d84..a72151c77c 100644 --- a/vendor/composer/ClassLoader.php +++ b/vendor/composer/ClassLoader.php @@ -429,7 +429,8 @@ public function unregister() public function loadClass($class) { if ($file = $this->findFile($class)) { - (self::$includeFile)($file); + $includeFile = self::$includeFile; + $includeFile($file); return true; } @@ -560,7 +561,10 @@ private function findFileWithExtension($class, $ext) return false; } - private static function initializeIncludeClosure(): void + /** + * @return void + */ + private static function initializeIncludeClosure() { if (self::$includeFile !== null) { return; @@ -574,8 +578,8 @@ private static function initializeIncludeClosure(): void * @param string $file * @return void */ - self::$includeFile = static function($file) { + self::$includeFile = \Closure::bind(static function($file) { include $file; - }; + }, null, null); } } diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php index 57194dcb99..5d97330b68 100644 --- a/vendor/composer/autoload_real.php +++ b/vendor/composer/autoload_real.php @@ -38,15 +38,15 @@ public static function getLoader() $loader->register(true); $filesToLoad = \Composer\Autoload\ComposerStaticInit5c689ffcd54b9e495ed983fdce09b530::$files; - $requireFile = static function ($fileIdentifier, $file) { + $requireFile = \Closure::bind(static function ($fileIdentifier, $file) { if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; require $file; } - }; + }, null, null); foreach ($filesToLoad as $fileIdentifier => $file) { - ($requireFile)($fileIdentifier, $file); + $requireFile($fileIdentifier, $file); } return $loader; diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 95e9043ebe..208127320a 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -6568,27 +6568,27 @@ }, { "name": "drupal/queue_mail", - "version": "1.4.0", - "version_normalized": "1.4.0.0", + "version": "1.5.0", + "version_normalized": "1.5.0.0", "source": { "type": "git", "url": "https://git.drupalcode.org/project/queue_mail.git", - "reference": "8.x-1.4" + "reference": "8.x-1.5" }, "dist": { "type": "zip", - "url": "https://ftp.drupal.org/files/projects/queue_mail-8.x-1.4.zip", - "reference": "8.x-1.4", - "shasum": "ccc3603d084017ec4d3aa67fa60da171ef8d63b8" + "url": "https://ftp.drupal.org/files/projects/queue_mail-8.x-1.5.zip", + "reference": "8.x-1.5", + "shasum": "8ee8580c5c76cbde614c955ff2d866f97d7e6e11" }, "require": { - "drupal/core": "^8.8.0 || ^9.0" + "drupal/core": "^9.4 || ^10.0" }, "type": "drupal-module", "extra": { "drupal": { - "version": "8.x-1.4", - "datestamp": "1632316348", + "version": "8.x-1.5", + "datestamp": "1671458599", "security-coverage": { "status": "covered", "message": "Covered by Drupal's security advisory policy" @@ -6612,8 +6612,8 @@ "role": "Maintainer" }, { - "name": "sinn", - "homepage": "https://www.drupal.org/user/682600" + "name": "Steven Jones", + "homepage": "https://www.drupal.org/user/99644" }, { "name": "wafaa", @@ -16117,17 +16117,17 @@ }, { "name": "symfony/string", - "version": "v5.4.19", - "version_normalized": "5.4.19.0", + "version": "v5.4.21", + "version_normalized": "5.4.21.0", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "0a01071610fd861cc160dfb7e2682ceec66064cb" + "reference": "edac10d167b78b1d90f46a80320d632de0bd9f2f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/0a01071610fd861cc160dfb7e2682ceec66064cb", - "reference": "0a01071610fd861cc160dfb7e2682ceec66064cb", + "url": "https://api.github.com/repos/symfony/string/zipball/edac10d167b78b1d90f46a80320d632de0bd9f2f", + "reference": "edac10d167b78b1d90f46a80320d632de0bd9f2f", "shasum": "" }, "require": { @@ -16147,7 +16147,7 @@ "symfony/translation-contracts": "^1.1|^2", "symfony/var-exporter": "^4.4|^5.0|^6.0" }, - "time": "2023-01-01T08:32:19+00:00", + "time": "2023-02-22T08:00:55+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -16186,7 +16186,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v5.4.19" + "source": "https://github.com/symfony/string/tree/v5.4.21" }, "funding": [ { @@ -16488,17 +16488,17 @@ }, { "name": "symfony/var-dumper", - "version": "v5.4.19", - "version_normalized": "5.4.19.0", + "version": "v5.4.21", + "version_normalized": "5.4.21.0", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "2944bbc23f5f8da2b962fbcbf7c4a6109b2f4b7b" + "reference": "6c5ac3a1be8b849d59a1a77877ee110e1b55eb74" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/2944bbc23f5f8da2b962fbcbf7c4a6109b2f4b7b", - "reference": "2944bbc23f5f8da2b962fbcbf7c4a6109b2f4b7b", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/6c5ac3a1be8b849d59a1a77877ee110e1b55eb74", + "reference": "6c5ac3a1be8b849d59a1a77877ee110e1b55eb74", "shasum": "" }, "require": { @@ -16522,7 +16522,7 @@ "ext-intl": "To show region name in time zone dump", "symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script" }, - "time": "2023-01-16T10:52:33+00:00", + "time": "2023-02-23T10:00:28+00:00", "bin": [ "Resources/bin/var-dump-server" ], @@ -16560,7 +16560,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v5.4.19" + "source": "https://github.com/symfony/var-dumper/tree/v5.4.21" }, "funding": [ { @@ -16580,17 +16580,17 @@ }, { "name": "symfony/var-exporter", - "version": "v5.4.19", - "version_normalized": "5.4.19.0", + "version": "v5.4.21", + "version_normalized": "5.4.21.0", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "2a1d06fcf2b30829d6c01dae8e6e188424d1f8f6" + "reference": "be74908a6942fdd331554b3cec27ff41b45ccad4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/2a1d06fcf2b30829d6c01dae8e6e188424d1f8f6", - "reference": "2a1d06fcf2b30829d6c01dae8e6e188424d1f8f6", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/be74908a6942fdd331554b3cec27ff41b45ccad4", + "reference": "be74908a6942fdd331554b3cec27ff41b45ccad4", "shasum": "" }, "require": { @@ -16600,7 +16600,7 @@ "require-dev": { "symfony/var-dumper": "^4.4.9|^5.0.9|^6.0" }, - "time": "2023-01-12T16:39:29+00:00", + "time": "2023-02-21T19:46:44+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -16636,7 +16636,7 @@ "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v5.4.19" + "source": "https://github.com/symfony/var-exporter/tree/v5.4.21" }, "funding": [ { diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php index 53a62c282f..e4f71a6ede 100644 --- a/vendor/composer/installed.php +++ b/vendor/composer/installed.php @@ -3,7 +3,7 @@ 'name' => 'osu-asc-webservices/d8-upstream', 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => 'd77ab674c1d51a3c0baffc1dd084fb68d5302c80', + 'reference' => '4ca0b45218d2ba104458c074545b32b16e93dc76', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -1076,9 +1076,9 @@ 'dev_requirement' => false, ), 'drupal/queue_mail' => array( - 'pretty_version' => '1.4.0', - 'version' => '1.4.0.0', - 'reference' => '8.x-1.4', + 'pretty_version' => '1.5.0', + 'version' => '1.5.0.0', + 'reference' => '8.x-1.5', 'type' => 'drupal-module', 'install_path' => __DIR__ . '/../../web/modules/queue_mail', 'aliases' => array(), @@ -1588,7 +1588,7 @@ 'osu-asc-webservices/d8-upstream' => array( 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => 'd77ab674c1d51a3c0baffc1dd084fb68d5302c80', + 'reference' => '4ca0b45218d2ba104458c074545b32b16e93dc76', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -1693,8 +1693,8 @@ 'psr/container-implementation' => array( 'dev_requirement' => false, 'provided' => array( - 0 => '1.0', - 1 => '^1.0', + 0 => '^1.0', + 1 => '1.0', ), ), 'psr/event-dispatcher-implementation' => array( @@ -2448,9 +2448,9 @@ ), ), 'symfony/string' => array( - 'pretty_version' => 'v5.4.19', - 'version' => '5.4.19.0', - 'reference' => '0a01071610fd861cc160dfb7e2682ceec66064cb', + 'pretty_version' => 'v5.4.21', + 'version' => '5.4.21.0', + 'reference' => 'edac10d167b78b1d90f46a80320d632de0bd9f2f', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/string', 'aliases' => array(), @@ -2490,18 +2490,18 @@ 'dev_requirement' => false, ), 'symfony/var-dumper' => array( - 'pretty_version' => 'v5.4.19', - 'version' => '5.4.19.0', - 'reference' => '2944bbc23f5f8da2b962fbcbf7c4a6109b2f4b7b', + 'pretty_version' => 'v5.4.21', + 'version' => '5.4.21.0', + 'reference' => '6c5ac3a1be8b849d59a1a77877ee110e1b55eb74', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/var-dumper', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/var-exporter' => array( - 'pretty_version' => 'v5.4.19', - 'version' => '5.4.19.0', - 'reference' => '2a1d06fcf2b30829d6c01dae8e6e188424d1f8f6', + 'pretty_version' => 'v5.4.21', + 'version' => '5.4.21.0', + 'reference' => 'be74908a6942fdd331554b3cec27ff41b45ccad4', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/var-exporter', 'aliases' => array(), diff --git a/vendor/symfony/string/AbstractUnicodeString.php b/vendor/symfony/string/AbstractUnicodeString.php index 1bc6f88fda..80b8326aee 100644 --- a/vendor/symfony/string/AbstractUnicodeString.php +++ b/vendor/symfony/string/AbstractUnicodeString.php @@ -37,8 +37,8 @@ abstract class AbstractUnicodeString extends AbstractString private const ASCII = "\x20\x65\x69\x61\x73\x6E\x74\x72\x6F\x6C\x75\x64\x5D\x5B\x63\x6D\x70\x27\x0A\x67\x7C\x68\x76\x2E\x66\x62\x2C\x3A\x3D\x2D\x71\x31\x30\x43\x32\x2A\x79\x78\x29\x28\x4C\x39\x41\x53\x2F\x50\x22\x45\x6A\x4D\x49\x6B\x33\x3E\x35\x54\x3C\x44\x34\x7D\x42\x7B\x38\x46\x77\x52\x36\x37\x55\x47\x4E\x3B\x4A\x7A\x56\x23\x48\x4F\x57\x5F\x26\x21\x4B\x3F\x58\x51\x25\x59\x5C\x09\x5A\x2B\x7E\x5E\x24\x40\x60\x7F\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"; // the subset of folded case mappings that is not in lower case mappings - private const FOLD_FROM = ['İ', 'µ', 'ſ', "\xCD\x85", 'ς', 'ϐ', 'ϑ', 'ϕ', 'ϖ', 'ϰ', 'ϱ', 'ϵ', 'ẛ', "\xE1\xBE\xBE", 'ß', 'İ', 'ʼn', 'ǰ', 'ΐ', 'ΰ', 'և', 'ẖ', 'ẗ', 'ẘ', 'ẙ', 'ẚ', 'ẞ', 'ὐ', 'ὒ', 'ὔ', 'ὖ', 'ᾀ', 'ᾁ', 'ᾂ', 'ᾃ', 'ᾄ', 'ᾅ', 'ᾆ', 'ᾇ', 'ᾈ', 'ᾉ', 'ᾊ', 'ᾋ', 'ᾌ', 'ᾍ', 'ᾎ', 'ᾏ', 'ᾐ', 'ᾑ', 'ᾒ', 'ᾓ', 'ᾔ', 'ᾕ', 'ᾖ', 'ᾗ', 'ᾘ', 'ᾙ', 'ᾚ', 'ᾛ', 'ᾜ', 'ᾝ', 'ᾞ', 'ᾟ', 'ᾠ', 'ᾡ', 'ᾢ', 'ᾣ', 'ᾤ', 'ᾥ', 'ᾦ', 'ᾧ', 'ᾨ', 'ᾩ', 'ᾪ', 'ᾫ', 'ᾬ', 'ᾭ', 'ᾮ', 'ᾯ', 'ᾲ', 'ᾳ', 'ᾴ', 'ᾶ', 'ᾷ', 'ᾼ', 'ῂ', 'ῃ', 'ῄ', 'ῆ', 'ῇ', 'ῌ', 'ῒ', 'ΐ', 'ῖ', 'ῗ', 'ῢ', 'ΰ', 'ῤ', 'ῦ', 'ῧ', 'ῲ', 'ῳ', 'ῴ', 'ῶ', 'ῷ', 'ῼ', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'ſt', 'st', 'ﬓ', 'ﬔ', 'ﬕ', 'ﬖ', 'ﬗ']; - private const FOLD_TO = ['i̇', 'μ', 's', 'ι', 'σ', 'β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', 'ṡ', 'ι', 'ss', 'i̇', 'ʼn', 'ǰ', 'ΐ', 'ΰ', 'եւ', 'ẖ', 'ẗ', 'ẘ', 'ẙ', 'aʾ', 'ss', 'ὐ', 'ὒ', 'ὔ', 'ὖ', 'ἀι', 'ἁι', 'ἂι', 'ἃι', 'ἄι', 'ἅι', 'ἆι', 'ἇι', 'ἀι', 'ἁι', 'ἂι', 'ἃι', 'ἄι', 'ἅι', 'ἆι', 'ἇι', 'ἠι', 'ἡι', 'ἢι', 'ἣι', 'ἤι', 'ἥι', 'ἦι', 'ἧι', 'ἠι', 'ἡι', 'ἢι', 'ἣι', 'ἤι', 'ἥι', 'ἦι', 'ἧι', 'ὠι', 'ὡι', 'ὢι', 'ὣι', 'ὤι', 'ὥι', 'ὦι', 'ὧι', 'ὠι', 'ὡι', 'ὢι', 'ὣι', 'ὤι', 'ὥι', 'ὦι', 'ὧι', 'ὰι', 'αι', 'άι', 'ᾶ', 'ᾶι', 'αι', 'ὴι', 'ηι', 'ήι', 'ῆ', 'ῆι', 'ηι', 'ῒ', 'ΐ', 'ῖ', 'ῗ', 'ῢ', 'ΰ', 'ῤ', 'ῦ', 'ῧ', 'ὼι', 'ωι', 'ώι', 'ῶ', 'ῶι', 'ωι', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'st', 'st', 'մն', 'մե', 'մի', 'վն', 'մխ']; + private const FOLD_FROM = ['İ', 'µ', 'ſ', "\xCD\x85", 'ς', 'ϐ', 'ϑ', 'ϕ', 'ϖ', 'ϰ', 'ϱ', 'ϵ', 'ẛ', "\xE1\xBE\xBE", 'ß', 'ʼn', 'ǰ', 'ΐ', 'ΰ', 'և', 'ẖ', 'ẗ', 'ẘ', 'ẙ', 'ẚ', 'ẞ', 'ὐ', 'ὒ', 'ὔ', 'ὖ', 'ᾀ', 'ᾁ', 'ᾂ', 'ᾃ', 'ᾄ', 'ᾅ', 'ᾆ', 'ᾇ', 'ᾈ', 'ᾉ', 'ᾊ', 'ᾋ', 'ᾌ', 'ᾍ', 'ᾎ', 'ᾏ', 'ᾐ', 'ᾑ', 'ᾒ', 'ᾓ', 'ᾔ', 'ᾕ', 'ᾖ', 'ᾗ', 'ᾘ', 'ᾙ', 'ᾚ', 'ᾛ', 'ᾜ', 'ᾝ', 'ᾞ', 'ᾟ', 'ᾠ', 'ᾡ', 'ᾢ', 'ᾣ', 'ᾤ', 'ᾥ', 'ᾦ', 'ᾧ', 'ᾨ', 'ᾩ', 'ᾪ', 'ᾫ', 'ᾬ', 'ᾭ', 'ᾮ', 'ᾯ', 'ᾲ', 'ᾳ', 'ᾴ', 'ᾶ', 'ᾷ', 'ᾼ', 'ῂ', 'ῃ', 'ῄ', 'ῆ', 'ῇ', 'ῌ', 'ῒ', 'ῖ', 'ῗ', 'ῢ', 'ῤ', 'ῦ', 'ῧ', 'ῲ', 'ῳ', 'ῴ', 'ῶ', 'ῷ', 'ῼ', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'ſt', 'st', 'ﬓ', 'ﬔ', 'ﬕ', 'ﬖ', 'ﬗ']; + private const FOLD_TO = ['i̇', 'μ', 's', 'ι', 'σ', 'β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', 'ṡ', 'ι', 'ss', 'ʼn', 'ǰ', 'ΐ', 'ΰ', 'եւ', 'ẖ', 'ẗ', 'ẘ', 'ẙ', 'aʾ', 'ss', 'ὐ', 'ὒ', 'ὔ', 'ὖ', 'ἀι', 'ἁι', 'ἂι', 'ἃι', 'ἄι', 'ἅι', 'ἆι', 'ἇι', 'ἀι', 'ἁι', 'ἂι', 'ἃι', 'ἄι', 'ἅι', 'ἆι', 'ἇι', 'ἠι', 'ἡι', 'ἢι', 'ἣι', 'ἤι', 'ἥι', 'ἦι', 'ἧι', 'ἠι', 'ἡι', 'ἢι', 'ἣι', 'ἤι', 'ἥι', 'ἦι', 'ἧι', 'ὠι', 'ὡι', 'ὢι', 'ὣι', 'ὤι', 'ὥι', 'ὦι', 'ὧι', 'ὠι', 'ὡι', 'ὢι', 'ὣι', 'ὤι', 'ὥι', 'ὦι', 'ὧι', 'ὰι', 'αι', 'άι', 'ᾶ', 'ᾶι', 'αι', 'ὴι', 'ηι', 'ήι', 'ῆ', 'ῆι', 'ηι', 'ῒ', 'ῖ', 'ῗ', 'ῢ', 'ῤ', 'ῦ', 'ῧ', 'ὼι', 'ωι', 'ώι', 'ῶ', 'ῶι', 'ωι', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'st', 'st', 'մն', 'մե', 'մի', 'վն', 'մխ']; // the subset of upper case mappings that map one code point to many code points private const UPPER_FROM = ['ß', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'ſt', 'st', 'և', 'ﬓ', 'ﬔ', 'ﬕ', 'ﬖ', 'ﬗ', 'ʼn', 'ΐ', 'ΰ', 'ǰ', 'ẖ', 'ẗ', 'ẘ', 'ẙ', 'ẚ', 'ὐ', 'ὒ', 'ὔ', 'ὖ', 'ᾶ', 'ῆ', 'ῒ', 'ΐ', 'ῖ', 'ῗ', 'ῢ', 'ΰ', 'ῤ', 'ῦ', 'ῧ', 'ῶ']; diff --git a/vendor/symfony/string/LICENSE b/vendor/symfony/string/LICENSE index 5c7ba0551c..f37c76b591 100644 --- a/vendor/symfony/string/LICENSE +++ b/vendor/symfony/string/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2019-2023 Fabien Potencier +Copyright (c) 2019-present Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/symfony/var-dumper/Caster/Caster.php b/vendor/symfony/var-dumper/Caster/Caster.php index 890f531063..81bfd54e5a 100644 --- a/vendor/symfony/var-dumper/Caster/Caster.php +++ b/vendor/symfony/var-dumper/Caster/Caster.php @@ -115,7 +115,7 @@ public static function castObject(object $obj, string $class, bool $hasDebugInfo * @param array $a The array containing the properties to filter * @param int $filter A bit field of Caster::EXCLUDE_* constants specifying which properties to filter out * @param string[] $listedProperties List of properties to exclude when Caster::EXCLUDE_VERBOSE is set, and to preserve when Caster::EXCLUDE_NOT_IMPORTANT is set - * @param int &$count Set to the number of removed properties + * @param int|null &$count Set to the number of removed properties */ public static function filter(array $a, int $filter, array $listedProperties = [], ?int &$count = 0): array { diff --git a/vendor/symfony/var-dumper/Caster/ReflectionCaster.php b/vendor/symfony/var-dumper/Caster/ReflectionCaster.php index 5c644053ad..ef6a85ef0f 100644 --- a/vendor/symfony/var-dumper/Caster/ReflectionCaster.php +++ b/vendor/symfony/var-dumper/Caster/ReflectionCaster.php @@ -292,7 +292,7 @@ public static function castParameter(\ReflectionParameter $c, array $a, Stub $st if ($c->isOptional()) { try { $a[$prefix.'default'] = $v = $c->getDefaultValue(); - if ($c->isDefaultValueConstant()) { + if ($c->isDefaultValueConstant() && !\is_object($v)) { $a[$prefix.'default'] = new ConstStub($c->getDefaultValueConstantName(), $v); } if (null === $v) { diff --git a/vendor/symfony/var-dumper/LICENSE b/vendor/symfony/var-dumper/LICENSE index 72412a62b2..29f72d5e95 100644 --- a/vendor/symfony/var-dumper/LICENSE +++ b/vendor/symfony/var-dumper/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2014-2023 Fabien Potencier +Copyright (c) 2014-present Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/symfony/var-exporter/LICENSE b/vendor/symfony/var-exporter/LICENSE index 99757d5171..7536caeae8 100644 --- a/vendor/symfony/var-exporter/LICENSE +++ b/vendor/symfony/var-exporter/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2018-2023 Fabien Potencier +Copyright (c) 2018-present Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/symfony/var-exporter/VarExporter.php b/vendor/symfony/var-exporter/VarExporter.php index 003388e798..8581337813 100644 --- a/vendor/symfony/var-exporter/VarExporter.php +++ b/vendor/symfony/var-exporter/VarExporter.php @@ -34,7 +34,7 @@ final class VarExporter * * @param mixed $value The value to export * @param bool &$isStaticValue Set to true after execution if the provided value is static, false otherwise - * @param bool &$classes Classes found in the value are added to this list as both keys and values + * @param array &$foundClasses Classes found in the value are added to this list as both keys and values * * @throws ExceptionInterface When the provided value cannot be serialized */ diff --git a/web/modules/queue_mail/composer.json b/web/modules/queue_mail/composer.json index e4e8b980b0..4e215070f1 100644 --- a/web/modules/queue_mail/composer.json +++ b/web/modules/queue_mail/composer.json @@ -20,6 +20,6 @@ "source": "https://git.drupalcode.org/project/queue_mail" }, "require": { - "drupal/core": "^8.8.0 || ^9.0" + "drupal/core": "^9.4 || ^10.0" } } diff --git a/web/modules/queue_mail/modules/queue_mail_language/queue_mail_language.info.yml b/web/modules/queue_mail/modules/queue_mail_language/queue_mail_language.info.yml index 610390bbf7..fac8919ebf 100644 --- a/web/modules/queue_mail/modules/queue_mail_language/queue_mail_language.info.yml +++ b/web/modules/queue_mail/modules/queue_mail_language/queue_mail_language.info.yml @@ -1,12 +1,12 @@ name: Queue Mail Language type: module -core_version_requirement: ^8 || ^9 +core_version_requirement: ^9.4 || ^10 description: Adds language support for queued mails. package: Mail dependencies: - drupal:language -# Information added by Drupal.org packaging script on 2021-09-22 -version: '8.x-1.4' +# Information added by Drupal.org packaging script on 2022-12-19 +version: '8.x-1.5' project: 'queue_mail' -datestamp: 1632316351 +datestamp: 1671458592 diff --git a/web/modules/queue_mail/modules/queue_mail_language/src/Plugin/QueueWorker/LanguageAwareSendMailQueueWorker.php b/web/modules/queue_mail/modules/queue_mail_language/src/Plugin/QueueWorker/LanguageAwareSendMailQueueWorker.php index d71622c1ec..c8b8cc9fa8 100644 --- a/web/modules/queue_mail/modules/queue_mail_language/src/Plugin/QueueWorker/LanguageAwareSendMailQueueWorker.php +++ b/web/modules/queue_mail/modules/queue_mail_language/src/Plugin/QueueWorker/LanguageAwareSendMailQueueWorker.php @@ -2,6 +2,7 @@ namespace Drupal\queue_mail_language\Plugin\QueueWorker; +use Drupal\Component\Datetime\TimeInterface; use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Logger\LoggerChannelFactoryInterface; @@ -45,6 +46,7 @@ public static function create(ContainerInterface $container, array $configuratio $container->get('config.factory'), $container->get('queue'), $container->get('module_handler'), + $container->get('datetime.time'), $container->get('language_manager'), $container->get('queue_mail.language_negotiator') ); @@ -61,10 +63,11 @@ public function __construct( ConfigFactoryInterface $config_factory, ContainerAwareInterface $queue_factory, ModuleHandlerInterface $module_handler, + TimeInterface $time, ConfigurableLanguageManagerInterface $language_manager, QueueMailLanguageNegotiator $queue_mail_language_negotiator ) { - parent::__construct($theme_manager, $theme_init, $mail_manager, $logger_factory, $config_factory, $queue_factory, $module_handler); + parent::__construct($theme_manager, $theme_init, $mail_manager, $logger_factory, $config_factory, $queue_factory, $module_handler, $time); $this->languageManager = $language_manager; $this->queueMailLanguageNegotiator = $queue_mail_language_negotiator; } diff --git a/web/modules/queue_mail/modules/queue_mail_language/src/QueueMailLanguageNegotiator.php b/web/modules/queue_mail/modules/queue_mail_language/src/QueueMailLanguageNegotiator.php index babcc0f4d1..5464c5b776 100644 --- a/web/modules/queue_mail/modules/queue_mail_language/src/QueueMailLanguageNegotiator.php +++ b/web/modules/queue_mail/modules/queue_mail_language/src/QueueMailLanguageNegotiator.php @@ -20,7 +20,6 @@ class QueueMailLanguageNegotiator extends LanguageNegotiator { * {@inheritdoc} */ public function initializeType($type) { - $language = NULL; $method_id = static::METHOD_ID; $availableLanguages = $this->languageManager->getLanguages(); diff --git a/web/modules/queue_mail/queue_mail.info.yml b/web/modules/queue_mail/queue_mail.info.yml index a7c1cfba71..12b9581b24 100644 --- a/web/modules/queue_mail/queue_mail.info.yml +++ b/web/modules/queue_mail/queue_mail.info.yml @@ -1,11 +1,11 @@ name: Queue Mail type: module -core_version_requirement: ^8 || ^9 +core_version_requirement: ^9.4 || ^10 description: Queues all mail sent by your Drupal site so that it is sent via cron using the Drupal Queue API. This is helpful for large traffic sites where sending a lot of emails per page request can slow things down considerably. package: Mail configure: queue_mail.admin_settings -# Information added by Drupal.org packaging script on 2021-09-22 -version: '8.x-1.4' +# Information added by Drupal.org packaging script on 2022-12-19 +version: '8.x-1.5' project: 'queue_mail' -datestamp: 1632316351 +datestamp: 1671458592 diff --git a/web/modules/queue_mail/src/Form/QueueMailSettingsForm.php b/web/modules/queue_mail/src/Form/QueueMailSettingsForm.php index 48df6dfb5e..a302269ff2 100644 --- a/web/modules/queue_mail/src/Form/QueueMailSettingsForm.php +++ b/web/modules/queue_mail/src/Form/QueueMailSettingsForm.php @@ -97,7 +97,13 @@ public function buildForm(array $form, FormStateInterface $form_state) { ]; // Get a list of modules that implement hook_mail. - $mail_modules = $this->moduleHandler->getImplementations('mail'); + $modules = $this->moduleHandler->getModuleList(); + $mail_modules = []; + foreach ($modules as $module => $extension) { + if ($this->moduleHandler->hasImplementations('mail', $module)) { + $mail_modules[] = $module; + } + } $rows = []; foreach ($mail_modules as $name) { @@ -143,7 +149,7 @@ public function buildForm(array $form, FormStateInterface $form_state) { '#min' => 0, '#title' => $this->t('Queue retry threshold'), '#default_value' => $config->get('threshold'), - '#description' => $this->t('How many times to retry before deleting an item.'), + '#description' => $this->t('How many times to retry before deleting an item. Set "0" not to retry. Leave empty for unlimited.'), ]; $form['advanced']['requeue_interval'] = [ diff --git a/web/modules/queue_mail/src/Plugin/QueueWorker/SendMailQueueWorker.php b/web/modules/queue_mail/src/Plugin/QueueWorker/SendMailQueueWorker.php index 7fd80d2c32..500c791ed5 100644 --- a/web/modules/queue_mail/src/Plugin/QueueWorker/SendMailQueueWorker.php +++ b/web/modules/queue_mail/src/Plugin/QueueWorker/SendMailQueueWorker.php @@ -2,18 +2,20 @@ namespace Drupal\queue_mail\Plugin\QueueWorker; -use Drupal\Core\Queue\QueueWorkerBase; +use Drupal\Component\Datetime\TimeInterface; use Drupal\Component\Render\PlainTextOutput; -use Drupal\Core\Plugin\ContainerFactoryPluginInterface; -use Drupal\Core\Theme\ThemeManagerInterface; -use Drupal\Core\Theme\ThemeInitializationInterface; -use Drupal\Core\Mail\MailManagerInterface; -use Drupal\Core\Logger\LoggerChannelFactoryInterface; use Drupal\Core\Config\ConfigFactoryInterface; -use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\Extension\ModuleHandlerInterface; -use Symfony\Component\DependencyInjection\ContainerInterface; +use Drupal\Core\Logger\LoggerChannelFactoryInterface; +use Drupal\Core\Mail\MailManagerInterface; +use Drupal\Core\Plugin\ContainerFactoryPluginInterface; +use Drupal\Core\Queue\DelayedRequeueException; +use Drupal\Core\Queue\QueueWorkerBase; +use Drupal\Core\StringTranslation\StringTranslationTrait; +use Drupal\Core\Theme\ThemeInitializationInterface; +use Drupal\Core\Theme\ThemeManagerInterface; use Symfony\Component\DependencyInjection\ContainerAwareInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; /** * Sends emails form queue. @@ -84,6 +86,13 @@ class SendMailQueueWorker extends QueueWorkerBase implements ContainerFactoryPlu */ protected $moduleHandler; + /** + * The time service. + * + * @var \Drupal\Component\Datetime\TimeInterface + */ + protected $time; + /** * {@inheritdoc} */ @@ -95,14 +104,15 @@ public static function create(ContainerInterface $container, array $configuratio $container->get('logger.factory'), $container->get('config.factory'), $container->get('queue'), - $container->get('module_handler') + $container->get('module_handler'), + $container->get('datetime.time') ); } /** * {@inheritdoc} */ - public function __construct(ThemeManagerInterface $theme_manager, ThemeInitializationInterface $theme_init, MailManagerInterface $mail_manager, LoggerChannelFactoryInterface $logger_factory, ConfigFactoryInterface $config_factory, ContainerAwareInterface $queue_factory, ModuleHandlerInterface $module_handler) { + public function __construct(ThemeManagerInterface $theme_manager, ThemeInitializationInterface $theme_init, MailManagerInterface $mail_manager, LoggerChannelFactoryInterface $logger_factory, ConfigFactoryInterface $config_factory, ContainerAwareInterface $queue_factory, ModuleHandlerInterface $module_handler, TimeInterface $time) { $this->themeManager = $theme_manager; $this->themeInitialization = $theme_init; $this->activeTheme = $this->themeManager->getActiveTheme(); @@ -111,6 +121,7 @@ public function __construct(ThemeManagerInterface $theme_manager, ThemeInitializ $this->config = $config_factory->get('queue_mail.settings'); $this->queue = $queue_factory->get('queue_mail', TRUE); $this->moduleHandler = $module_handler; + $this->time = $time; } /** @@ -121,9 +132,11 @@ public function processItem($message) { $interval = $this->config->get('requeue_interval'); // Prevent retrying until specified interval has elapsed. - if (isset($message['last_attempt']) && ($message['last_attempt'] + $interval) > time()) { - // Skip item. - throw new \RuntimeException(sprintf('Sending of mail "%s" is skipped in the mail queue due to requeue interval.', $message['id'])); + $current_time = $this->time->getCurrentTime(); + if (isset($message['last_attempt']) && ($message['last_attempt'] + $interval) > $current_time) { + // Skip item until interval expires. + $delay = $message['last_attempt'] + $interval - $current_time; + throw new DelayedRequeueException($delay); } // Invoke hook_queue_mail_send_alter() to allow all modules to alter the @@ -177,7 +190,7 @@ public function processItem($message) { $this->logger->error('Error sending email (from %from to %to with reply-to %reply).', [ '%from' => $message['from'], '%to' => $message['to'], - '%reply' => $message['reply-to'] ? $message['reply-to'] : $this->t('not set'), + '%reply' => $message['reply-to'] ?: $this->t('not set'), ]); $this->processRetryLimit($original_message); @@ -271,7 +284,7 @@ protected function waitBetweenSending() { * Original message. */ protected function processRetryLimit(array $original_message) { - $original_message['last_attempt'] = time(); + $original_message['last_attempt'] = $this->time->getCurrentTime(); if (!isset($original_message['fail_count'])) { $original_message['fail_count'] = 0; @@ -281,14 +294,14 @@ protected function processRetryLimit(array $original_message) { $threshold = $this->config->get('threshold'); // Add back to the queue with an updated fail count. - if ($original_message['fail_count'] < $threshold) { + if (!isset($threshold) || $original_message['fail_count'] < $threshold) { $this->queue->createItem($original_message); } else { $this->logger->error('Attempt sending email (from %from to %to with reply-to %reply) exceeded retry threshold and was deleted.', [ '%from' => $original_message['from'], '%to' => $original_message['to'], - '%reply' => $original_message['reply-to'] ? $original_message['reply-to'] : $this->t('not set'), + '%reply' => $original_message['reply-to'] ?: $this->t('not set'), ]); } } diff --git a/web/modules/queue_mail/tests/modules/queue_mail_test/queue_mail_test.info.yml b/web/modules/queue_mail/tests/modules/queue_mail_test/queue_mail_test.info.yml index 13b88fac79..4e727aaeb1 100644 --- a/web/modules/queue_mail/tests/modules/queue_mail_test/queue_mail_test.info.yml +++ b/web/modules/queue_mail/tests/modules/queue_mail_test/queue_mail_test.info.yml @@ -1,14 +1,14 @@ name: Queue Mail Test type: module description: Module for use by the queue mail module tests. -core_version_requirement: ^8 || ^9 +core_version_requirement: ^9.4 || ^10 dependencies: - queue_mail:queue_mail package: Testing hidden: true -# Information added by Drupal.org packaging script on 2021-09-22 -version: '8.x-1.4' +# Information added by Drupal.org packaging script on 2022-12-19 +version: '8.x-1.5' project: 'queue_mail' -datestamp: 1632316351 +datestamp: 1671458592 diff --git a/web/modules/queue_mail/tests/src/Functional/QueueMailConfigurationTest.php b/web/modules/queue_mail/tests/src/Functional/QueueMailConfigurationTest.php index 1940d28277..a6f99fc3df 100644 --- a/web/modules/queue_mail/tests/src/Functional/QueueMailConfigurationTest.php +++ b/web/modules/queue_mail/tests/src/Functional/QueueMailConfigurationTest.php @@ -53,10 +53,8 @@ public function testDefaultConfiguration() { 'threshold' => 50, 'requeue_interval' => 10800, ]; - - foreach ($default_values as $field => $value) { - $this->assertSession()->fieldValueEquals($field, $value); - } + $this->assertFieldValues($default_values); + $this->assertSettings($default_values); } /** @@ -74,11 +72,22 @@ public function testChangeConfiguration() { 'requeue_interval' => 21600, ]; $this->submitForm($edit, 'Save configuration'); - $this->drupalGet(static::CONFIGURATION_PATH); - foreach ($edit as $field => $value) { - $this->assertSession()->fieldValueEquals($field, $value); - } + $this->assertFieldValues($edit); + $this->assertSettings($edit); + + // Unlimited retry threshold. + $edit['threshold'] = 0; + $this->submitForm($edit, 'Save configuration'); + $this->assertFieldValues($edit); + $this->assertSettings($edit); + + // No retry. + $edit['threshold'] = ''; + $this->submitForm($edit, 'Save configuration'); + $this->assertFieldValues($edit); + $edit['threshold'] = NULL; + $this->assertSettings($edit); } /** @@ -107,4 +116,23 @@ public function testWaitTimePerItemValidation() { $this->assertSession()->responseNotContains($validation_text); } + /** + * Asserts values on the settings form. + */ + protected function assertFieldValues($values) { + foreach ($values as $field => $value) { + $this->assertSession()->fieldValueEquals($field, $value); + } + } + + /** + * Asserts settings stored in queue_mail.settings. + */ + protected function assertSettings($values) { + $config = \Drupal::config('queue_mail.settings'); + foreach ($values as $key => $value) { + $this->assertSame($value, $config->get($key)); + } + } + } diff --git a/web/modules/queue_mail/tests/src/Functional/QueueMailFunctionalTest.php b/web/modules/queue_mail/tests/src/Functional/QueueMailFunctionalTest.php index fdebf703ea..8e32ac486f 100644 --- a/web/modules/queue_mail/tests/src/Functional/QueueMailFunctionalTest.php +++ b/web/modules/queue_mail/tests/src/Functional/QueueMailFunctionalTest.php @@ -248,4 +248,67 @@ public function testFailMessage() { $this->assertEquals(1, $queue_count_after_adding - $queue_count_init, 'One message has been processed.'); } + /** + * Tests retry threshold functionality. + */ + public function testRetryThreshold() { + $this->setAllEmailsToBeQueued(); + $queue = _queue_mail_get_queue(); + $settings = \Drupal::configFactory()->getEditable('queue_mail.settings'); + // Set requeue interval as 1 to make it possible to process the queue item + // on the next cron run. + $settings->set('requeue_interval', 1)->save(); + + // No retry. + $settings->set('threshold', 0)->save(); + $this->sendQueueMailTest('fail_message', 'fail@example.com', $this->getMessageParams()); + $this->assertEquals(1, $queue->numberOfItems()); + $this->cronRun(); + $this->assertEquals(0, $queue->numberOfItems()); + + // Retry threshold is 3 - message is removed from queue after 3 attempts. + $settings->set('threshold', 3)->save(); + $this->sendQueueMailTest('fail_message', 'fail@example.com', $this->getMessageParams()); + $this->assertEquals(1, $queue->numberOfItems()); + for ($i = 1; $i <= 2; $i++) { + $this->cronRun(); + $this->assertEquals(1, $queue->numberOfItems()); + $this->releaseQueueItems(); + $item = $queue->claimItem(); + $this->assertEquals($i, $item->data['fail_count']); + $this->releaseQueueItems(); + sleep(1); + } + $this->cronRun(); + $this->assertEquals(0, $queue->numberOfItems()); + + // Retry threshold is unlimited - message won't be removed from queue. + $settings->set('threshold', NULL)->save(); + $this->sendQueueMailTest('fail_message', 'fail@example.com', $this->getMessageParams()); + $this->assertEquals(1, $queue->numberOfItems()); + for ($i = 1; $i <= 10; $i++) { + $this->cronRun(); + $this->assertEquals(1, $queue->numberOfItems()); + $this->releaseQueueItems(); + $item = $queue->claimItem(); + $this->assertEquals($i, $item->data['fail_count']); + $this->releaseQueueItems(); + sleep(1); + } + } + + /** + * Releases queue items between cron run. + * + * \Drupal\Core\Queue\DatabaseQueue::garbageCollection() uses request time + * that don't release items inside few cron runs in one request. + */ + protected function releaseQueueItems() { + \Drupal::database()->update('queue') + ->fields([ + 'expire' => 0, + ]) + ->execute(); + } + } -- GitLab