Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 34abba6

Browse filesBrowse files
Merge branch '2.8' into 3.1
* 2.8: [VarDumper] Fix source links with latests Twig versions [DomCrawler] Optimize DomCrawler::relativize() [HttpKernel] Fix source links with latests Twig versions [DomCrawler] Allow pipe (|) character in link tags when using Xpath expressions
2 parents f07bf03 + 5b566da commit 34abba6
Copy full SHA for 34abba6

File tree

Expand file treeCollapse file tree

7 files changed

+166
-48
lines changed
Filter options
Expand file treeCollapse file tree

7 files changed

+166
-48
lines changed

‎src/Symfony/Component/DomCrawler/Crawler.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DomCrawler/Crawler.php
+45-13Lines changed: 45 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -940,29 +940,54 @@ private function relativize($xpath)
940940
{
941941
$expressions = array();
942942

943-
$unionPattern = '/\|(?![^\[]*\])/';
944943
// An expression which will never match to replace expressions which cannot match in the crawler
945944
// We cannot simply drop
946945
$nonMatchingExpression = 'a[name() = "b"]';
947946

948-
// Split any unions into individual expressions.
949-
foreach (preg_split($unionPattern, $xpath) as $expression) {
950-
$expression = trim($expression);
951-
$parenthesis = '';
947+
$xpathLen = strlen($xpath);
948+
$openedBrackets = 0;
949+
$startPosition = strspn($xpath, " \t\n\r\0\x0B");
950+
951+
for ($i = $startPosition; $i <= $xpathLen; ++$i) {
952+
$i += strcspn($xpath, '"\'[]|', $i);
953+
954+
if ($i < $xpathLen) {
955+
switch ($xpath[$i]) {
956+
case '"':
957+
case "'":
958+
if (false === $i = strpos($xpath, $xpath[$i], $i + 1)) {
959+
return $xpath; // The XPath expression is invalid
960+
}
961+
continue 2;
962+
case '[':
963+
++$openedBrackets;
964+
continue 2;
965+
case ']':
966+
--$openedBrackets;
967+
continue 2;
968+
}
969+
}
970+
if ($openedBrackets) {
971+
continue;
972+
}
952973

953-
// If the union is inside some braces, we need to preserve the opening braces and apply
954-
// the change only inside it.
955-
if (preg_match('/^[\(\s*]+/', $expression, $matches)) {
956-
$parenthesis = $matches[0];
957-
$expression = substr($expression, strlen($parenthesis));
974+
if ($startPosition < $xpathLen && '(' === $xpath[$startPosition]) {
975+
// If the union is inside some braces, we need to preserve the opening braces and apply
976+
// the change only inside it.
977+
$j = 1 + strspn($xpath, "( \t\n\r\0\x0B", $startPosition + 1);
978+
$parenthesis = substr($xpath, $startPosition, $j);
979+
$startPosition += $j;
980+
} else {
981+
$parenthesis = '';
958982
}
983+
$expression = rtrim(substr($xpath, $startPosition, $i - $startPosition));
959984

960985
if (0 === strpos($expression, 'self::*/')) {
961986
$expression = './'.substr($expression, 8);
962987
}
963988

964989
// add prefix before absolute element selector
965-
if (empty($expression)) {
990+
if ('' === $expression) {
966991
$expression = $nonMatchingExpression;
967992
} elseif (0 === strpos($expression, '//')) {
968993
$expression = 'descendant-or-self::'.substr($expression, 2);
@@ -975,17 +1000,24 @@ private function relativize($xpath)
9751000
} elseif ('/' === $expression[0] || '.' === $expression[0] || 0 === strpos($expression, 'self::')) {
9761001
$expression = $nonMatchingExpression;
9771002
} elseif (0 === strpos($expression, 'descendant::')) {
978-
$expression = 'descendant-or-self::'.substr($expression, strlen('descendant::'));
1003+
$expression = 'descendant-or-self::'.substr($expression, 12);
9791004
} elseif (preg_match('/^(ancestor|ancestor-or-self|attribute|following|following-sibling|namespace|parent|preceding|preceding-sibling)::/', $expression)) {
9801005
// the fake root has no parent, preceding or following nodes and also no attributes (even no namespace attributes)
9811006
$expression = $nonMatchingExpression;
9821007
} elseif (0 !== strpos($expression, 'descendant-or-self::')) {
9831008
$expression = 'self::'.$expression;
9841009
}
9851010
$expressions[] = $parenthesis.$expression;
1011+
1012+
if ($i === $xpathLen) {
1013+
return implode(' | ', $expressions);
1014+
}
1015+
1016+
$i += strspn($xpath, " \t\n\r\0\x0B", $i + 1);
1017+
$startPosition = $i + 1;
9861018
}
9871019

988-
return implode(' | ', $expressions);
1020+
return $xpath; // The XPath expression is invalid
9891021
}
9901022

9911023
/**

‎src/Symfony/Component/DomCrawler/Tests/CrawlerTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DomCrawler/Tests/CrawlerTest.php
+4-1Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,7 @@ public function testFilterXpathComplexQueries()
430430
$this->assertCount(5, $crawler->filterXPath('(//a | //div)//img'));
431431
$this->assertCount(7, $crawler->filterXPath('((//a | //div)//img | //ul)'));
432432
$this->assertCount(7, $crawler->filterXPath('( ( //a | //div )//img | //ul )'));
433+
$this->assertCount(1, $crawler->filterXPath("//a[./@href][((./@id = 'Klausi|Claudiu' or normalize-space(string(.)) = 'Klausi|Claudiu' or ./@title = 'Klausi|Claudiu' or ./@rel = 'Klausi|Claudiu') or .//img[./@alt = 'Klausi|Claudiu'])]"));
433434
}
434435

435436
public function testFilterXPath()
@@ -596,7 +597,7 @@ public function testFilterXPathWithSelfAxes()
596597

597598
$this->assertCount(0, $crawler->filterXPath('self::a'), 'The fake root node has no "real" element name');
598599
$this->assertCount(0, $crawler->filterXPath('self::a/img'), 'The fake root node has no "real" element name');
599-
$this->assertCount(9, $crawler->filterXPath('self::*/a'));
600+
$this->assertCount(10, $crawler->filterXPath('self::*/a'));
600601
}
601602

602603
public function testFilter()
@@ -1079,6 +1080,8 @@ public function createTestCrawler($uri = null)
10791080
10801081
<a href="?get=param">GetLink</a>
10811082
1083+
<a href="/example">Klausi|Claudiu</a>
1084+
10821085
<form action="foo" id="FooFormId">
10831086
<input type="text" value="TextValue" name="TextName" />
10841087
<input type="submit" value="FooValue" name="FooName" id="FooId" />

‎src/Symfony/Component/HttpKernel/DataCollector/DumpDataCollector.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpKernel/DataCollector/DumpDataCollector.php
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,11 @@ public function dump(Data $data)
9494
} elseif (isset($trace[$i]['object']) && $trace[$i]['object'] instanceof \Twig_Template) {
9595
$template = $trace[$i]['object'];
9696
$name = $template->getTemplateName();
97-
$file = method_exists($template, 'getSourceContext') ? $template->getSourceContext()->getPath() : false;
9897
$src = method_exists($template, 'getSourceContext') ? $template->getSourceContext()->getCode() : (method_exists($template, 'getSource') ? $template->getSource() : false);
9998
$info = $template->getDebugInfo();
100-
if (null !== $src && isset($info[$trace[$i - 1]['line']])) {
99+
if (isset($info[$trace[$i - 1]['line']])) {
101100
$line = $info[$trace[$i - 1]['line']];
101+
$file = method_exists($template, 'getSourceContext') ? $template->getSourceContext()->getPath() : false;
102102

103103
if ($src) {
104104
$src = explode("\n", $src);

‎src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php
+11-7Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -150,15 +150,19 @@ public static function castFrameStub(FrameStub $frame, array $a, Stub $stub, $is
150150

151151
if (!empty($f['class']) && is_subclass_of($f['class'], 'Twig_Template') && method_exists($f['class'], 'getDebugInfo')) {
152152
$template = isset($f['object']) ? $f['object'] : new $f['class'](new \Twig_Environment(new \Twig_Loader_Filesystem()));
153-
154-
try {
155-
$templateName = $template->getTemplateName();
156-
$templateSrc = explode("\n", method_exists($template, 'getSource') ? $template->getSource() : $template->getEnvironment()->getLoader()->getSource($templateName));
157-
$templateInfo = $template->getDebugInfo();
158-
if (isset($templateInfo[$f['line']])) {
153+
$templateName = $template->getTemplateName();
154+
$templateSrc = method_exists($template, 'getSourceContext') ? $template->getSourceContext()->getCode() : (method_exists($template, 'getSource') ? $template->getSource() : '');
155+
$templateInfo = $template->getDebugInfo();
156+
if (isset($templateInfo[$f['line']])) {
157+
if (method_exists($template, 'getSourceContext')) {
158+
$templateName = $template->getSourceContext()->getPath() ?: $templateName;
159+
}
160+
if ($templateSrc) {
161+
$templateSrc = explode("\n", $templateSrc);
159162
$src[$templateName.':'.$templateInfo[$f['line']]] = self::extractSource($templateSrc, $templateInfo[$f['line']], self::$srcContext);
163+
} else {
164+
$src[$templateName] = $templateInfo[$f['line']];
160165
}
161-
} catch (\Twig_Error_Loader $e) {
162166
}
163167
}
164168
} else {
+87Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\VarDumper\Tests\Caster;
13+
14+
use Symfony\Component\VarDumper\Caster\FrameStub;
15+
use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
16+
17+
class ExceptionCasterTest extends \PHPUnit_Framework_TestCase
18+
{
19+
use VarDumperTestTrait;
20+
21+
/**
22+
* @requires function Twig_Template::getSourceContext
23+
*/
24+
public function testFrameWithTwig()
25+
{
26+
require_once dirname(__DIR__).'/Fixtures/Twig.php';
27+
28+
$f = array(
29+
new FrameStub(array(
30+
'file' => dirname(__DIR__).'/Fixtures/Twig.php',
31+
'line' => 19,
32+
'class' => '__TwigTemplate_VarDumperFixture_u75a09',
33+
'object' => new \__TwigTemplate_VarDumperFixture_u75a09(new \Twig_Environment(new \Twig_Loader_Filesystem())),
34+
)),
35+
new FrameStub(array(
36+
'file' => dirname(__DIR__).'/Fixtures/Twig.php',
37+
'line' => 19,
38+
'class' => '__TwigTemplate_VarDumperFixture_u75a09',
39+
'object' => new \__TwigTemplate_VarDumperFixture_u75a09(new \Twig_Environment(new \Twig_Loader_Filesystem()), null),
40+
)),
41+
);
42+
43+
$expectedDump = <<<'EODUMP'
44+
array:2 [
45+
0 => {
46+
class: "__TwigTemplate_VarDumperFixture_u75a09"
47+
object: __TwigTemplate_VarDumperFixture_u75a09 {
48+
%A
49+
}
50+
src: {
51+
%sTwig.php:19: """
52+
// line 2\n
53+
throw new \Exception('Foobar');\n
54+
}\n
55+
"""
56+
bar.twig:2: """
57+
foo bar\n
58+
twig source\n
59+
\n
60+
"""
61+
}
62+
}
63+
1 => {
64+
class: "__TwigTemplate_VarDumperFixture_u75a09"
65+
object: __TwigTemplate_VarDumperFixture_u75a09 {
66+
%A
67+
}
68+
src: {
69+
%sTwig.php:19: """
70+
// line 2\n
71+
throw new \Exception('Foobar');\n
72+
}\n
73+
"""
74+
foo.twig:2: """
75+
foo bar\n
76+
twig source\n
77+
\n
78+
"""
79+
}
80+
}
81+
]
82+
83+
EODUMP;
84+
85+
$this->assertDumpMatchesFormat($expectedDump, $f);
86+
}
87+
}

‎src/Symfony/Component/VarDumper/Tests/CliDumperTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/VarDumper/Tests/CliDumperTest.php
+9-14Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,9 @@ public function testFlags()
228228
putenv('DUMP_STRING_LENGTH=');
229229
}
230230

231+
/**
232+
* @requires function Twig_Template::getSourceContext
233+
*/
231234
public function testThrowingCaster()
232235
{
233236
$out = fopen('php://memory', 'r+b');
@@ -262,19 +265,6 @@ public function testThrowingCaster()
262265
rewind($out);
263266
$out = stream_get_contents($out);
264267

265-
if (method_exists($twig, 'getSource')) {
266-
$twig = <<<EOTXT
267-
foo.twig:2: """
268-
foo bar\\n
269-
twig source\\n
270-
\\n
271-
"""
272-
273-
EOTXT;
274-
} else {
275-
$twig = '';
276-
}
277-
278268
$r = defined('HHVM_VERSION') ? '' : '#%d';
279269
$this->assertStringMatchesFormat(
280270
<<<EOTXT
@@ -296,7 +286,12 @@ public function testThrowingCaster()
296286
throw new \Exception('Foobar');\\n
297287
}\\n
298288
"""
299-
{$twig} }
289+
bar.twig:2: """
290+
foo bar\\n
291+
twig source\\n
292+
\\n
293+
"""
294+
}
300295
}
301296
%d. Twig_Template->displayWithErrorHandling() ==> __TwigTemplate_VarDumperFixture_u75a09->doDisplay(): {
302297
src: {

‎src/Symfony/Component/VarDumper/Tests/Fixtures/Twig.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/VarDumper/Tests/Fixtures/Twig.php
+8-11Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@
33
/* foo.twig */
44
class __TwigTemplate_VarDumperFixture_u75a09 extends Twig_Template
55
{
6-
public function __construct(Twig_Environment $env)
6+
private $filename;
7+
8+
public function __construct(Twig_Environment $env, $filename = 'bar.twig')
79
{
810
parent::__construct($env);
9-
1011
$this->parent = false;
11-
12-
$this->blocks = array(
13-
);
12+
$this->blocks = array();
13+
$this->filename = $filename;
1414
}
1515

1616
protected function doDisplay(array $context, array $blocks = array())
@@ -26,14 +26,11 @@ public function getTemplateName()
2626

2727
public function getDebugInfo()
2828
{
29-
return array (19 => 2);
29+
return array(19 => 2);
3030
}
3131

32-
public function getSource()
32+
public function getSourceContext()
3333
{
34-
return " foo bar
35-
twig source
36-
37-
";
34+
return new Twig_Source(" foo bar\n twig source\n\n", 'foo.twig', $this->filename);
3835
}
3936
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.