8000 Merge branch '2.8' into 3.1 · symfony/symfony@34abba6 · GitHub
[go: up one dir, main page]

Skip to content

Commit 34abba6

Browse 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

File tree

7 files changed

+166
-48
lines changed

7 files changed

+166
-48
lines changed

src/Symfony/Component/DomCrawler/Crawler.php

Lines 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

Lines 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

Lines 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

Lines 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 {
Lines 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

Lines 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

Lines 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