Skip to content

Commit 43717a2

Browse files
committed
Merge branch '2.3' into 2.4
* 2.3: Revert "Fix "Array was modified outside object" in ResizeFormListener." Added failing test bumped Symfony version to 2.3.11 updated VERSION for 2.3.10 update CONTRIBUTORS for 2.3.10 updated CHANGELOG for 2.3.10 [Console] removed problematic regex [DomCrawler] Added support for <area> tags to be treated as links Fix "Array was modified outside object" in ResizeFormListener. Conflicts: src/Symfony/Component/HttpKernel/Kernel.php
2 parents 940f217 + 7613bbd commit 43717a2

File tree

3 files changed

+60
-56
lines changed

3 files changed

+60
-56
lines changed

Formatter/OutputFormatter.php

Lines changed: 40 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,6 @@
2020
*/
2121
class OutputFormatter implements OutputFormatterInterface
2222
{
23-
/**
24-
* The pattern to phrase the format.
25-
*/
26-
const FORMAT_PATTERN = '#(\\\\?)<(/?)([a-z][a-z0-9_=;-]*)?>((?: [^<\\\\]+ | (?!<(?:/?[a-z]|/>)). | .(?<=\\\\<) )*)#isx';
27-
2823
private $decorated;
2924
private $styles = array();
3025
private $styleStack;
@@ -147,9 +142,43 @@ public function getStyle($name)
147142
*/
148143
public function format($message)
149144
{
150-
$message = preg_replace_callback(self::FORMAT_PATTERN, array($this, 'replaceStyle'), $message);
145+
$offset = 0;
146+
$output = '';
147+
$tagRegex = '[a-z][a-z0-9_=;-]*';
148+
preg_match_all("#<(($tagRegex) | /($tagRegex)?)>#isx", $message, $matches, PREG_OFFSET_CAPTURE);
149+
foreach ($matches[0] as $i => $match) {
150+
$pos = $match[1];
151+
$text = $match[0];
152+
153+
// add the text up to the next tag
154+
$output .= $this->applyCurrentStyle(substr($message, $offset, $pos - $offset));
155+
$offset = $pos + strlen($text);
156+
157+
// opening tag?
158+
if ($open = '/' != $text[1]) {
159+
$tag = $matches[1][$i][0];
160+
} else {
161+
$tag = isset($matches[3][$i][0]) ? $matches[3][$i][0] : '';
162+
}
163+
164+
if (!$open && !$tag) {
165+
// </>
166+
$this->styleStack->pop();
167+
} elseif ($pos && '\\' == $message[$pos - 1]) {
168+
// escaped tag
169+
$output .= $this->applyCurrentStyle($text);
170+
} elseif (false === $style = $this->createStyleFromString(strtolower($tag))) {
171+
$output .= $this->applyCurrentStyle($text);
172+
} elseif ($open) {
173+
$this->styleStack->push($style);
174+
} else {
175+
$this->styleStack->pop($style);
176+
}
177+
}
178+
179+
$output .= $this->applyCurrentStyle(substr($message, $offset));
151180

152-
return str_replace('\\<', '<', $message);
181+
return str_replace('\\<', '<', $output);
153182
}
154183

155184
/**
@@ -160,53 +189,6 @@ public function getStyleStack()
160189
return $this->styleStack;
161190
}
162191

163-
/**
164-
* Replaces style of the output.
165-
*
166-
* All escaped tags and tags that reference unknown styles are kept as is.
167-
*
168-
* @param array $match
169-
*
170-
* @return string The replaced style
171-
*/
172-
private function replaceStyle($match)
173-
{
174-
// we got "\<" escaped char
175-
if ('\\' === $match[1]) {
176-
return $this->applyCurrentStyle($match[0]);
177-
}
178-
179-
if ('' === $match[3]) {
180-
if ('/' === $match[2]) {
181-
// we got "</>" tag
182-
$this->styleStack->pop();
183-
184-
return $this->applyCurrentStyle($match[4]);
185-
}
186-
187-
// we got "<>" tag
188-
return '<>'.$this->applyCurrentStyle($match[4]);
189-
}
190-
191-
if (isset($this->styles[strtolower($match[3])])) {
192-
$style = $this->styles[strtolower($match[3])];
193-
} else {
194-
$style = $this->createStyleFromString($match[3]);
195-
196-
if (false === $style) {
197-
return $this->applyCurrentStyle($match[0]);
198-
}
199-
}
200-
201-
if ('/' === $match[2]) {
202-
$this->styleStack->pop($style);
203-
} else {
204-
$this->styleStack->push($style);
205-
}
206-
207-
return $this->applyCurrentStyle($match[4]);
208-
}
209-
210192
/**
211193
* Tries to create new style instance from string.
212194
*
@@ -216,6 +198,10 @@ private function replaceStyle($match)
216198
*/
217199
private function createStyleFromString($string)
218200
{
201+
if (isset($this->styles[$string])) {
202+
return $this->styles[$string];
203+
}
204+
219205
if (!preg_match_all('/([^=]+)=([^;]+)(;|$)/', strtolower($string), $matches, PREG_SET_ORDER)) {
220206
return false;
221207
}

Tests/Fixtures/application_renderexception3decorated.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
 
2020
 [Exception] 
21-
 First exception <p>this is html</p> 
21+
 First exception <p>this is html</p> 
2222
 
2323

2424

Tests/Formatter/OutputFormatterTest.php

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,16 @@ public function testNestedStyles()
7373
);
7474
}
7575

76+
public function testAdjacentStyles()
77+
{
78+
$formatter = new OutputFormatter(true);
79+
80+
$this->assertEquals(
81+
"\033[37;41msome error\033[0m\033[32msome info\033[0m",
82+
$formatter->format('<error>some error</error><info>some info</info>')
83+
);
84+
}
85+
7686
public function testStyleMatchingNotGreedy()
7787
{
7888
$formatter = new OutputFormatter(true);
@@ -140,7 +150,15 @@ public function testInlineStyle()
140150
public function testNonStyleTag()
141151
{
142152
$formatter = new OutputFormatter(true);
143-
$this->assertEquals("\033[32msome \033[0m\033[32m<tag> styled \033[0m\033[32m<p>single-char tag\033[0m\033[32m</p>\033[0m", $formatter->format('<info>some <tag> styled <p>single-char tag</p></info>'));
153+
154+
$this->assertEquals("\033[32msome \033[0m\033[32m<tag>\033[0m\033[32m styled \033[0m\033[32m<p>\033[0m\033[32msingle-char tag\033[0m\033[32m</p>\033[0m", $formatter->format('<info>some <tag> styled <p>single-char tag</p></info>'));
155+
}
156+
157+
public function testFormatLongString()
158+
{
159+
$formatter = new OutputFormatter(true);
160+
$long = str_repeat("\\", 14000);
161+
$this->assertEquals("\033[37;41msome error\033[0m".$long, $formatter->format('<error>some error</error>'.$long));
144162
}
145163

146164
public function testNotDecoratedFormatter()

0 commit comments

Comments
 (0)