diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.lv.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.lv.xlf
index b3560305df00b..878e8420a1611 100644
--- a/src/Symfony/Component/Validator/Resources/translations/validators.lv.xlf
+++ b/src/Symfony/Component/Validator/Resources/translations/validators.lv.xlf
@@ -340,15 +340,15 @@
This value should be positive.
- Šai vērtībāi jābūt pozitīvai.
+ Šai vērtībai jābūt pozitīvai.
This value should be either positive or zero.
- Šai vērtībāi jābūt pozitīvai vai vienādai ar nulli.
+ Šai vērtībai jābūt pozitīvai vai vienādai ar nulli.
This value should be negative.
- Šai vērtībāi jābūt negatīvai.
+ Šai vērtībai jābūt negatīvai.
This value should be either negative or zero.
diff --git a/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php b/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php
index c29b7df261d33..b0d137cdde04b 100644
--- a/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php
+++ b/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php
@@ -214,18 +214,24 @@ public static function castFrameStub(FrameStub $frame, array $a, Stub $stub, $is
if (file_exists($f['file']) && 0 <= self::$srcContext) {
if (!empty($f['class']) && (is_subclass_of($f['class'], 'Twig\Template') || is_subclass_of($f['class'], 'Twig_Template')) && method_exists($f['class'], 'getDebugInfo')) {
- $template = $f['object'] ?? unserialize(sprintf('O:%d:"%s":0:{}', \strlen($f['class']), $f['class']));
-
- $ellipsis = 0;
- $templateSrc = method_exists($template, 'getSourceContext') ? $template->getSourceContext()->getCode() : (method_exists($template, 'getSource') ? $template->getSource() : '');
- $templateInfo = $template->getDebugInfo();
- if (isset($templateInfo[$f['line']])) {
- if (!method_exists($template, 'getSourceContext') || !file_exists($templatePath = $template->getSourceContext()->getPath())) {
- $templatePath = null;
- }
- if ($templateSrc) {
- $src = self::extractSource($templateSrc, $templateInfo[$f['line']], self::$srcContext, 'twig', $templatePath, $f);
- $srcKey = ($templatePath ?: $template->getTemplateName()).':'.$templateInfo[$f['line']];
+ $template = null;
+ if (isset($f['object'])) {
+ $template = $f['object'];
+ } elseif ((new \ReflectionClass($f['class']))->isInstantiable()) {
+ $template = unserialize(sprintf('O:%d:"%s":0:{}', \strlen($f['class']), $f['class']));
+ }
+ if (isset($template)) {
+ $ellipsis = 0;
+ $templateSrc = method_exists($template, 'getSourceContext') ? $template->getSourceContext()->getCode() : (method_exists($template, 'getSource') ? $template->getSource() : '');
+ $templateInfo = $template->getDebugInfo();
+ if (isset($templateInfo[$f['line']])) {
+ if (!method_exists($template, 'getSourceContext') || !file_exists($templatePath = $template->getSourceContext()->getPath())) {
+ $templatePath = null;
+ }
+ if ($templateSrc) {
+ $src = self::extractSource($templateSrc, $templateInfo[$f['line']], self::$srcContext, 'twig', $templatePath, $f);
+ $srcKey = ($templatePath ?: $template->getTemplateName()).':'.$templateInfo[$f['line']];
+ }
}
}
}
diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/ExceptionCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/ExceptionCasterTest.php
index 50c7a8d24dca0..ddd7c0b6ae2c6 100644
--- a/src/Symfony/Component/VarDumper/Tests/Caster/ExceptionCasterTest.php
+++ b/src/Symfony/Component/VarDumper/Tests/Caster/ExceptionCasterTest.php
@@ -15,7 +15,9 @@
use Symfony\Component\VarDumper\Caster\Caster;
use Symfony\Component\VarDumper\Caster\ExceptionCaster;
use Symfony\Component\VarDumper\Caster\FrameStub;
+use Symfony\Component\VarDumper\Caster\TraceStub;
use Symfony\Component\VarDumper\Cloner\VarCloner;
+use Symfony\Component\VarDumper\Dumper\CliDumper;
use Symfony\Component\VarDumper\Dumper\HtmlDumper;
use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
@@ -44,15 +46,15 @@ public function testDefaultSettings()
#message: "foo"
#code: 0
#file: "%sExceptionCasterTest.php"
- #line: 28
+ #line: %d
trace: {
- %s%eTests%eCaster%eExceptionCasterTest.php:28 {
+ %s%eTests%eCaster%eExceptionCasterTest.php:%d {
Symfony\Component\VarDumper\Tests\Caster\ExceptionCasterTest->getTestException($msg, &$ref = null)
› {
› return new \Exception(''.$msg);
› }
}
- %s%eTests%eCaster%eExceptionCasterTest.php:40 { …}
+ %s%eTests%eCaster%eExceptionCasterTest.php:%d { …}
%A
EODUMP;
@@ -66,13 +68,13 @@ public function testSeek()
$expectedDump = <<<'EODUMP'
{
- %s%eTests%eCaster%eExceptionCasterTest.php:28 {
+ %s%eTests%eCaster%eExceptionCasterTest.php:%d {
Symfony\Component\VarDumper\Tests\Caster\ExceptionCasterTest->getTestException($msg, &$ref = null)
› {
› return new \Exception(''.$msg);
› }
}
- %s%eTests%eCaster%eExceptionCasterTest.php:65 { …}
+ %s%eTests%eCaster%eExceptionCasterTest.php:%d { …}
%A
EODUMP;
@@ -89,15 +91,15 @@ public function testNoArgs()
#message: "1"
#code: 0
#file: "%sExceptionCasterTest.php"
- #line: 28
+ #line: %d
trace: {
- %sExceptionCasterTest.php:28 {
+ %sExceptionCasterTest.php:%d {
Symfony\Component\VarDumper\Tests\Caster\ExceptionCasterTest->getTestException($msg, &$ref = null)
› {
› return new \Exception(''.$msg);
› }
}
- %s%eTests%eCaster%eExceptionCasterTest.php:84 { …}
+ %s%eTests%eCaster%eExceptionCasterTest.php:%d { …}
%A
EODUMP;
@@ -114,9 +116,9 @@ public function testNoSrcContext()
#message: "1"
#code: 0
#file: "%sExceptionCasterTest.php"
- #line: 28
+ #line: %d
trace: {
- %s%eTests%eCaster%eExceptionCasterTest.php:28
+ %s%eTests%eCaster%eExceptionCasterTest.php:%d
%s%eTests%eCaster%eExceptionCasterTest.php:%d
%A
EODUMP;
@@ -124,6 +126,33 @@ public function testNoSrcContext()
$this->assertDumpMatchesFormat($expectedDump, $e);
}
+ public function testShouldReturnTraceForConcreteTwigWithError()
+ {
+ require_once \dirname(__DIR__).'/Fixtures/ConcreteBug.php';
+
+ $cloner = new VarCloner();
+ $innerExc = (new \__TwigTemplate_VarDumperFixture_concreteBug(null, __FILE__))->provideError();
+ $nestingWrapper = new \stdClass();
+ $nestingWrapper->trace = new TraceStub($innerExc->getTrace());
+
+ $dumper = new CliDumper();
+ $dump = $dumper->dump($cloner->cloneVar($nestingWrapper)->withRefHandles(false), true);
+ $expectedDump = <<<'EODUMP'
+{
+ +"trace": {
+ %sConcreteBug.php:%d {
+ __TwigTemplate_VarDumperFixture_abstractBug->provideError()
+ › {
+ › return $this->createError();
+ › }
+ }
+ %sExceptionCasterTest.php:%d { …}
+%A
+EODUMP;
+
+ $this->assertStringMatchesFormat($expectedDump, $dump);
+ }
+
public function testHtmlDump()
{
if (ini_get('xdebug.file_link_format') || get_cfg_var('xdebug.file_link_format')) {
@@ -146,10 +175,10 @@ public function testHtmlDump()
#code: 0
#file: "%s%eVarDumper%eTests%eCaster%eExceptionCasterTest.php"
- #line: 28
+ #line: %d
trace: {
%s%eVarDumper%eTests%eCaster%eExceptionCasterTest.php:28
+Stack level %d.">%s%eVarDumper%eTests%eCaster%eExceptionCasterTest.php:%d
…%d
}
}
@@ -186,7 +215,7 @@ public function testFrameWithTwig()
class: "__TwigTemplate_VarDumperFixture_u75a09"
src: {
%sTwig.php:1 {
- ›
+ ›%s
› foo bar
› twig source
}
@@ -201,7 +230,7 @@ class: "__TwigTemplate_VarDumperFixture_u75a09"
%sExceptionCasterTest.php:2 {
› foo bar
› twig source
- ›
+ ›%s
}
}
}
@@ -221,7 +250,7 @@ public function testExcludeVerbosity()
#message: "foo"
#code: 0
#file: "%sExceptionCasterTest.php"
- #line: 28
+ #line: %d
}
EODUMP;
diff --git a/src/Symfony/Component/VarDumper/Tests/Fixtures/ConcreteBug.php b/src/Symfony/Component/VarDumper/Tests/Fixtures/ConcreteBug.php
new file mode 100644
index 0000000000000..3e1fe066dac96
--- /dev/null
+++ b/src/Symfony/Component/VarDumper/Tests/Fixtures/ConcreteBug.php
@@ -0,0 +1,57 @@
+createError();
+ }
+}
+
+/* foo_abstract.twig */
+class __TwigTemplate_VarDumperFixture_concreteBug extends __TwigTemplate_VarDumperFixture_abstractBug
+{
+ public function __construct(Twig\Environment $env = null, $path = null)
+ {
+ if (null !== $env) {
+ parent::__construct($env);
+ }
+ $this->parent = false;
+ $this->blocks = [];
+ $this->path = $path;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getTemplateName()
+ {
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getDebugInfo()
+ {
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getSourceContext()
+ {
+ return new Twig\Source(" foo bar\n twig source\n\n", 'foo_abstract.twig', $this->path ?: __FILE__);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ protected function doDisplay(array $context, array $blocks = [])
+ {
+ }
+}