diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/translation.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/translation.html.twig index b37da94681..a8a5c27365 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/translation.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/translation.html.twig @@ -13,7 +13,7 @@ {% set text %}
Locale | + {% if is_fallback %} +Fallback locale | + {% endif %}Domain | Times used | Message ID | @@ -177,6 +180,9 @@ {% for message in messages %}
---|---|---|---|---|
{{ message.locale }} | + {% if is_fallback %} +{{ message.fallbackLocale|default('-') }} | + {% endif %}{{ message.domain }} | {{ message.count }} |
diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig
index ecb559caae..fa2b19e882 100644
--- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig
+++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig
@@ -429,7 +429,7 @@
newToken = (newToken || token);
this.load(
'sfwdt' + token,
- '{{ path("_wdt", { "token": "xxxxxx" }) }}'.replace(/xxxxxx/, newToken),
+ '{{ path("_wdt", { "token": "xxxxxx" })|escape('js') }}'.replace(/xxxxxx/, newToken),
function(xhr, el) {
/* Evaluate in global scope scripts embedded inside the toolbar */
@@ -532,7 +532,7 @@
sfwdt.innerHTML = '\
\
\
- An error occurred while loading the web debug toolbar. Open the web profiler.\
+ An error occurred while loading the web debug toolbar. Open the web profiler.\
\
';
sfwdt.setAttribute('class', 'sf-toolbar sf-error-toolbar');
diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/LanguageTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/LanguageTypeTest.php
index 7a9fd54695..2000e1501e 100644
--- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/LanguageTypeTest.php
+++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/LanguageTypeTest.php
@@ -32,8 +32,6 @@ class LanguageTypeTest extends BaseTypeTest
->createView()->vars['choices'];
$this->assertContainsEquals(new ChoiceView('en', 'en', 'English'), $choices);
- $this->assertContainsEquals(new ChoiceView('en_GB', 'en_GB', 'British English'), $choices);
- $this->assertContainsEquals(new ChoiceView('en_US', 'en_US', 'American English'), $choices);
$this->assertContainsEquals(new ChoiceView('fr', 'fr', 'French'), $choices);
$this->assertContainsEquals(new ChoiceView('my', 'my', 'Burmese'), $choices);
}
@@ -51,7 +49,6 @@ class LanguageTypeTest extends BaseTypeTest
// Don't check objects for identity
$this->assertContainsEquals(new ChoiceView('en', 'en', 'англійська'), $choices);
- $this->assertContainsEquals(new ChoiceView('en_US', 'en_US', 'англійська (США)'), $choices);
$this->assertContainsEquals(new ChoiceView('fr', 'fr', 'французька'), $choices);
$this->assertContainsEquals(new ChoiceView('my', 'my', 'бірманська'), $choices);
}
diff --git a/src/Symfony/Component/Messenger/Tests/Transport/Doctrine/DoctrineReceiverTest.php b/src/Symfony/Component/Messenger/Tests/Transport/Doctrine/DoctrineReceiverTest.php
index c284c2536b..9c8b359f09 100644
--- a/src/Symfony/Component/Messenger/Tests/Transport/Doctrine/DoctrineReceiverTest.php
+++ b/src/Symfony/Component/Messenger/Tests/Transport/Doctrine/DoctrineReceiverTest.php
@@ -11,9 +11,12 @@
namespace Symfony\Component\Messenger\Tests\Transport\Doctrine;
+use Doctrine\DBAL\Driver\PDOException;
+use Doctrine\DBAL\Exception\DeadlockException;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\Exception\MessageDecodingFailedException;
+use Symfony\Component\Messenger\Exception\TransportException;
use Symfony\Component\Messenger\Stamp\TransportMessageIdStamp;
use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage;
use Symfony\Component\Messenger\Transport\Doctrine\Connection;
@@ -68,6 +71,26 @@ class DoctrineReceiverTest extends TestCase
$receiver->get();
}
+ public function testOccursRetryableExceptionFromConnection()
+ {
+ $serializer = $this->createSerializer();
+ $connection = $this->createMock(Connection::class);
+ $driverException = new PDOException(new \PDOException('Deadlock', 40001));
+ $connection->method('get')->willThrowException(new DeadlockException('Deadlock', $driverException));
+ $receiver = new DoctrineReceiver($connection, $serializer);
+ $this->assertSame([], $receiver->get());
+ $this->assertSame([], $receiver->get());
+ try {
+ $receiver->get();
+ } catch (TransportException $exception) {
+ // skip, and retry
+ }
+ $this->assertSame([], $receiver->get());
+ $this->assertSame([], $receiver->get());
+ $this->expectException(TransportException::class);
+ $receiver->get();
+ }
+
public function testAll()
{
$serializer = $this->createSerializer();
diff --git a/src/Symfony/Component/Messenger/Transport/Doctrine/DoctrineReceiver.php b/src/Symfony/Component/Messenger/Transport/Doctrine/DoctrineReceiver.php
index 82bfdecca0..071cf2812a 100644
--- a/src/Symfony/Component/Messenger/Transport/Doctrine/DoctrineReceiver.php
+++ b/src/Symfony/Component/Messenger/Transport/Doctrine/DoctrineReceiver.php
@@ -12,6 +12,7 @@
namespace Symfony\Component\Messenger\Transport\Doctrine;
use Doctrine\DBAL\DBALException;
+use Doctrine\DBAL\Exception\RetryableException;
use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\Exception\LogicException;
use Symfony\Component\Messenger\Exception\MessageDecodingFailedException;
@@ -28,6 +29,8 @@ use Symfony\Component\Messenger\Transport\Serialization\SerializerInterface;
*/
class DoctrineReceiver implements ReceiverInterface, MessageCountAwareInterface, ListableReceiverInterface
{
+ private const MAX_RETRIES = 3;
+ private $retryingSafetyCounter = 0;
private $connection;
private $serializer;
@@ -44,6 +47,17 @@ class DoctrineReceiver implements ReceiverInterface, MessageCountAwareInterface,
{
try {
$doctrineEnvelope = $this->connection->get();
+ $this->retryingSafetyCounter = 0; // reset counter
+ } catch (RetryableException $exception) {
+ // Do nothing when RetryableException occurs less than "MAX_RETRIES"
+ // as it will likely be resolved on the next call to get()
+ // Problem with concurrent consumers and database deadlocks
+ if (++$this->retryingSafetyCounter >= self::MAX_RETRIES) {
+ $this->retryingSafetyCounter = 0; // reset counter
+ throw new TransportException($exception->getMessage(), 0, $exception);
+ }
+
+ return [];
} catch (DBALException $exception) {
throw new TransportException($exception->getMessage(), 0, $exception);
}
diff --git a/src/Symfony/Component/Messenger/composer.json b/src/Symfony/Component/Messenger/composer.json
index 68608be615..ba708b594b 100644
--- a/src/Symfony/Component/Messenger/composer.json
+++ b/src/Symfony/Component/Messenger/composer.json
@@ -20,7 +20,7 @@
"psr/log": "~1.0"
},
"require-dev": {
- "doctrine/dbal": "^2.5",
+ "doctrine/dbal": "^2.6",
"psr/cache": "~1.0",
"doctrine/persistence": "~1.0",
"symfony/console": "^3.4|^4.0|^5.0",
diff --git a/src/Symfony/Component/Translation/DataCollectorTranslator.php b/src/Symfony/Component/Translation/DataCollectorTranslator.php
index d6295c8df6..1c672b7f4f 100644
--- a/src/Symfony/Component/Translation/DataCollectorTranslator.php
+++ b/src/Symfony/Component/Translation/DataCollectorTranslator.php
@@ -150,6 +150,7 @@ class DataCollectorTranslator implements LegacyTranslatorInterface, TranslatorIn
$id = (string) $id;
$catalogue = $this->translator->getCatalogue($locale);
$locale = $catalogue->getLocale();
+ $fallbackLocale = null;
if ($catalogue->defines($id, $domain)) {
$state = self::MESSAGE_DEFINED;
} elseif ($catalogue->has($id, $domain)) {
@@ -158,10 +159,9 @@ class DataCollectorTranslator implements LegacyTranslatorInterface, TranslatorIn
$fallbackCatalogue = $catalogue->getFallbackCatalogue();
while ($fallbackCatalogue) {
if ($fallbackCatalogue->defines($id, $domain)) {
- $locale = $fallbackCatalogue->getLocale();
+ $fallbackLocale = $fallbackCatalogue->getLocale();
break;
}
-
$fallbackCatalogue = $fallbackCatalogue->getFallbackCatalogue();
}
} else {
@@ -170,6 +170,7 @@ class DataCollectorTranslator implements LegacyTranslatorInterface, TranslatorIn
$this->messages[] = [
'locale' => $locale,
+ 'fallbackLocale' => $fallbackLocale,
'domain' => $domain,
'id' => $id,
'translation' => $translation,
diff --git a/src/Symfony/Component/Translation/Tests/DataCollectorTranslatorTest.php b/src/Symfony/Component/Translation/Tests/DataCollectorTranslatorTest.php
index 138172e21d..06f4b20ba6 100644
--- a/src/Symfony/Component/Translation/Tests/DataCollectorTranslatorTest.php
+++ b/src/Symfony/Component/Translation/Tests/DataCollectorTranslatorTest.php
@@ -34,6 +34,7 @@ class DataCollectorTranslatorTest extends TestCase
'id' => 'foo',
'translation' => 'foo (en)',
'locale' => 'en',
+ 'fallbackLocale' => null,
'domain' => 'messages',
'state' => DataCollectorTranslator::MESSAGE_DEFINED,
'parameters' => [],
@@ -42,7 +43,8 @@ class DataCollectorTranslatorTest extends TestCase
$expectedMessages[] = [
'id' => 'bar',
'translation' => 'bar (fr)',
- 'locale' => 'fr',
+ 'locale' => 'en',
+ 'fallbackLocale' => 'fr',
'domain' => 'messages',
'state' => DataCollectorTranslator::MESSAGE_EQUALS_FALLBACK,
'parameters' => [],
@@ -52,6 +54,7 @@ class DataCollectorTranslatorTest extends TestCase
'id' => 'choice',
'translation' => 'choice',
'locale' => 'en',
+ 'fallbackLocale' => null,
'domain' => 'messages',
'state' => DataCollectorTranslator::MESSAGE_MISSING,
'parameters' => ['%count%' => 0],
@@ -60,7 +63,8 @@ class DataCollectorTranslatorTest extends TestCase
$expectedMessages[] = [
'id' => 'bar_ru',
'translation' => 'bar (ru)',
- 'locale' => 'ru',
+ 'locale' => 'en',
+ 'fallbackLocale' => 'ru',
'domain' => 'messages',
'state' => DataCollectorTranslator::MESSAGE_EQUALS_FALLBACK,
'parameters' => [],
@@ -69,7 +73,8 @@ class DataCollectorTranslatorTest extends TestCase
$expectedMessages[] = [
'id' => 'bar_ru',
'translation' => 'bar (ru)',
- 'locale' => 'ru',
+ 'locale' => 'en',
+ 'fallbackLocale' => 'ru',
'domain' => 'messages',
'state' => DataCollectorTranslator::MESSAGE_EQUALS_FALLBACK,
'parameters' => ['foo' => 'bar'],
diff --git a/src/Symfony/Component/Validator/Constraints/UrlValidator.php b/src/Symfony/Component/Validator/Constraints/UrlValidator.php
index cc0522a62a..a15a92313f 100644
--- a/src/Symfony/Component/Validator/Constraints/UrlValidator.php
+++ b/src/Symfony/Component/Validator/Constraints/UrlValidator.php
@@ -26,7 +26,7 @@ class UrlValidator extends ConstraintValidator
(%s):// # protocol
(([\.\pL\pN-]+:)?([\.\pL\pN-]+)@)? # basic auth
(
- ([\pL\pN\pS\-\.])+(\.?([\pL\pN]|xn\-\-[\pL\pN-]+)+\.?) # a domain name
+ ([\pL\pN\pS\-\_\.])+(\.?([\pL\pN]|xn\-\-[\pL\pN-]+)+\.?) # a domain name
| # or
\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3} # an IP address
| # or
diff --git a/src/Symfony/Component/Validator/Tests/Constraints/LanguageValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/LanguageValidatorTest.php
index 391d124db2..669e7d2d97 100644
--- a/src/Symfony/Component/Validator/Tests/Constraints/LanguageValidatorTest.php
+++ b/src/Symfony/Component/Validator/Tests/Constraints/LanguageValidatorTest.php
@@ -73,7 +73,6 @@ class LanguageValidatorTest extends ConstraintValidatorTestCase
{
return [
['en'],
- ['en_US'],
['my'],
];
}
diff --git a/src/Symfony/Component/Validator/Tests/Constraints/UrlValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/UrlValidatorTest.php
index 42b6f1579d..63b481eaa8 100644
--- a/src/Symfony/Component/Validator/Tests/Constraints/UrlValidatorTest.php
+++ b/src/Symfony/Component/Validator/Tests/Constraints/UrlValidatorTest.php
@@ -106,6 +106,8 @@ class UrlValidatorTest extends ConstraintValidatorTestCase
['http://www.example.museum'],
['https://example.com/'],
['https://example.com:80/'],
+ ['http://examp_le.com'],
+ ['http://www.sub_domain.examp_le.com'],
['http://www.example.coop/'],
['http://www.test-example.com/'],
['http://www.symfony.com/'],
@@ -239,7 +241,6 @@ class UrlValidatorTest extends ConstraintValidatorTestCase
['://example.com'],
['http ://example.com'],
['http:/example.com'],
- ['http://examp_le.com'],
['http://example.com::aa'],
['http://example.com:aa'],
['ftp://example.fr'],
|