Skip to content

Commit 0a95168

Browse files
committed
Merge branch '2.8' into 3.3
* 2.8: [HttpFoundation] Support 0 bit netmask in IPv6 () Set `width: auto` on WebProfiler toolbar's reset. [HttpKernel] Fix logging of post-terminate errors/exceptions [Debug] Fix catching fatal errors in case of nested error handlers Fix hidden currency element with Bootstrap 3 theme
2 parents d200185 + eddd273 commit 0a95168

File tree

11 files changed

+176
-37
lines changed

11 files changed

+176
-37
lines changed

src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,21 @@
2020
{%- endblock %}
2121

2222
{% block money_widget -%}
23-
<div class="input-group">
24-
{% set append = money_pattern starts with '{{' %}
25-
{% if not append %}
26-
<span class="input-group-addon">{{ money_pattern|replace({ '{{ widget }}':''}) }}</span>
27-
{% endif %}
23+
{% set prepend = not (money_pattern starts with '{{') %}
24+
{% set append = not (money_pattern ends with '}}') %}
25+
{% if prepend or append %}
26+
<div class="input-group">
27+
{% if prepend %}
28+
<span class="input-group-addon">{{ money_pattern|replace({ '{{ widget }}':''}) }}</span>
29+
{% endif %}
30+
{{- block('form_widget_simple') -}}
31+
{% if append %}
32+
<span class="input-group-addon">{{ money_pattern|replace({ '{{ widget }}':''}) }}</span>
33+
{% endif %}
34+
</div>
35+
{% else %}
2836
{{- block('form_widget_simple') -}}
29-
{% if append %}
30-
<span class="input-group-addon">{{ money_pattern|replace({ '{{ widget }}':''}) }}</span>
31-
{% endif %}
32-
</div>
37+
{% endif %}
3338
{%- endblock money_widget %}
3439

3540
{% block percent_widget -%}

src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
box-sizing: content-box;
4242
vertical-align: baseline;
4343
letter-spacing: normal;
44+
width: auto;
4445
}
4546

4647
.sf-toolbarreset {

src/Symfony/Component/Debug/ErrorHandler.php

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,7 @@ public function handleException($exception, array $error = null)
526526
$exception = new FatalThrowableError($exception);
527527
}
528528
$type = $exception instanceof FatalErrorException ? $exception->getSeverity() : E_ERROR;
529+
$handlerException = null;
529530

530531
if (($this->loggedErrors & $type) || $exception instanceof FatalThrowableError) {
531532
if ($exception instanceof FatalErrorException) {
@@ -560,18 +561,20 @@ public function handleException($exception, array $error = null)
560561
}
561562
}
562563
}
563-
if (empty($this->exceptionHandler)) {
564-
throw $exception; // Give back $exception to the native handler
565-
}
566564
try {
567-
call_user_func($this->exceptionHandler, $exception);
565+
if (null !== $this->exceptionHandler) {
566+
return \call_user_func($this->exceptionHandler, $exception);
567+
}
568+
$handlerException = $handlerException ?: $exception;
568569
} catch (\Exception $handlerException) {
569570
} catch (\Throwable $handlerException) {
570571
}
571-
if (isset($handlerException)) {
572-
$this->exceptionHandler = null;
573-
$this->handleException($handlerException);
572+
$this->exceptionHandler = null;
573+
if ($exception === $handlerException) {
574+
self::$reservedMemory = null; // Disable the fatal error handler
575+
throw $exception; // Give back $exception to the native handler
574576
}
577+
$this->handleException($handlerException);
575578
}
576579

577580
/**
@@ -587,15 +590,30 @@ public static function handleFatalError(array $error = null)
587590
return;
588591
}
589592

590-
self::$reservedMemory = null;
593+
$handler = self::$reservedMemory = null;
594+
$handlers = array();
591595

592-
$handler = set_error_handler('var_dump');
593-
$handler = is_array($handler) ? $handler[0] : null;
594-
restore_error_handler();
596+
while (!is_array($handler) || !$handler[0] instanceof self) {
597+
$handler = set_exception_handler('var_dump');
598+
restore_exception_handler();
595599

596-
if (!$handler instanceof self) {
600+
if (!$handler) {
601+
break;
602+
}
603+
restore_exception_handler();
604+
array_unshift($handlers, $handler);
605+
}
606+
foreach ($handlers as $h) {
607+
set_exception_handler($h);
608+
}
609+
if (!$handler) {
597610
return;
598611
}
612+
if ($handler !== $h) {
613+
$handler[0]->setExceptionHandler($h);
614+
}
615+
$handler = $handler[0];
616+
$handlers = array();
599617

600618
if ($exit = null === $error) {
601619
$error = error_get_last();
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
--TEST--
2+
Test rethrowing in custom exception handler
3+
--FILE--
4+
<?php
5+
6+
namespace Symfony\Component\Debug;
7+
8+
$vendor = __DIR__;
9+
while (!file_exists($vendor.'/vendor')) {
10+
$vendor = dirname($vendor);
11+
}
12+
require $vendor.'/vendor/autoload.php';
13+
14+
if (true) {
15+
class TestLogger extends \Psr\Log\AbstractLogger
16+
{
17+
public function log($level, $message, array $context = array())
18+
{
19+
echo $message, "\n";
20+
}
21+
}
22+
}
23+
24+
set_exception_handler(function ($e) { echo 123; throw $e; });
25+
ErrorHandler::register()->setDefaultLogger(new TestLogger());
26+
ini_set('display_errors', 1);
27+
28+
throw new \Exception('foo');
29+
30+
?>
31+
--EXPECTF--
32+
Uncaught Exception: foo
33+
123
34+
Fatal error: Uncaught %s:25
35+
Stack trace:
36+
%a
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
--TEST--
2+
Test catching fatal errors when handlers are nested
3+
--FILE--
4+
<?php
5+
6+
namespace Symfony\Component\Debug;
7+
8+
$vendor = __DIR__;
9+
while (!file_exists($vendor.'/vendor')) {
10+
$vendor = dirname($vendor);
11+
}
12+
require $vendor.'/vendor/autoload.php';
13+
14+
Debug::enable();
15+
ini_set('display_errors', 0);
16+
17+
$eHandler = set_error_handler('var_dump');
18+
$xHandler = set_exception_handler('var_dump');
19+
20+
var_dump(array(
21+
$eHandler[0] === $xHandler[0] ? 'Error and exception handlers do match' : 'Error and exception handlers are different',
22+
));
23+
24+
$eHandler[0]->setExceptionHandler('print_r');
25+
26+
if (true) {
27+
class Broken implements \Serializable {};
28+
}
29+
30+
?>
31+
--EXPECTF--
32+
array(1) {
33+
[0]=>
34+
string(37) "Error and exception handlers do match"
35+
}
36+
object(Symfony\Component\Debug\Exception\FatalErrorException)#4 (8) {
37+
["message":protected]=>
38+
string(199) "Error: Class Symfony\Component\Debug\Broken contains 2 abstract methods and must therefore be declared abstract or implement the remaining methods (Serializable::serialize, Serializable::unserialize)"
39+
%a
40+
}

src/Symfony/Component/Form/Tests/AbstractBootstrap3LayoutTest.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1914,6 +1914,25 @@ public function testMoney()
19141914
);
19151915
}
19161916

1917+
public function testMoneyWithoutCurrency()
1918+
{
1919+
$form = $this->factory->createNamed('name', 'money', 1234.56, array(
1920+
'currency' => false,
1921+
));
1922+
1923+
$this->assertWidgetMatchesXpath($form->createView(), array('id' => 'my&id', 'attr' => array('class' => 'my&class')),
1924+
'/input
1925+
[@id="my&id"]
1926+
[@type="text"]
1927+
[@name="name"]
1928+
[@class="my&class form-control"]
1929+
[@value="1234.56"]
1930+
[not(preceding-sibling::*)]
1931+
[not(following-sibling::*)]
1932+
'
1933+
);
1934+
}
1935+
19171936
public function testNumber()
19181937
{
19191938
$form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\NumberType', 1234.56);

src/Symfony/Component/Form/Tests/Extension/Core/Type/MoneyTypeTest.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public function testMoneyPatternWorksForYen()
4343
$view = $this->factory->create(static::TESTED_TYPE, null, array('currency' => 'JPY'))
4444
->createView();
4545

46-
$this->assertTrue((bool) strstr($view->vars['money_pattern'], '¥'));
46+
$this->assertSame('¥ {{ widget }}', $view->vars['money_pattern']);
4747
}
4848

4949
// https://github.com/symfony/symfony/issues/5458
@@ -62,4 +62,12 @@ public function testSubmitNull($expected = null, $norm = null, $view = null)
6262
{
6363
parent::testSubmitNull($expected, $norm, '');
6464
}
65+
66+
public function testMoneyPatternWithoutCurrency()
67+
{
68+
$view = $this->factory->create(static::TESTED_TYPE, null, array('currency' => false))
69+
->createView();
70+
71+
$this->assertSame('{{ widget }}', $view->vars['money_pattern']);
72+
}
6573
}

src/Symfony/Component/HttpFoundation/IpUtils.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,10 @@ public static function checkIp6($requestIp, $ip)
123123
if (false !== strpos($ip, '/')) {
124124
list($address, $netmask) = explode('/', $ip, 2);
125125

126+
if ('0' === $netmask) {
127+
return (bool) unpack('n*', @inet_pton($address));
128+
}
129+
126130
if ($netmask < 1 || $netmask > 128) {
127131
return self::$checkedIps[$cacheKey] = false;
128132
}

src/Symfony/Component/HttpFoundation/Tests/IpUtilsTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ public function getIpv6Data()
6262
array(false, '2a01:198:603:0:396e:4789:8e99:890f', '::1'),
6363
array(true, '0:0:0:0:0:0:0:1', '::1'),
6464
array(false, '0:0:603:0:396e:4789:8e99:0001', '::1'),
65+
array(true, '0:0:603:0:396e:4789:8e99:0001', '::/0'),
66+
array(true, '0:0:603:0:396e:4789:8e99:0001', '2a01:198:603:0::/0'),
6567
array(true, '2a01:198:603:0:396e:4789:8e99:890f', array('::1', '2a01:198:603:0::/65')),
6668
array(true, '2a01:198:603:0:396e:4789:8e99:890f', array('2a01:198:603:0::/65', '::1')),
6769
array(false, '2a01:198:603:0:396e:4789:8e99:890f', array('::1', '1a01:198:603:0::/65')),

src/Symfony/Component/HttpKernel/EventListener/DebugHandlersListener.php

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class DebugHandlersListener implements EventSubscriberInterface
3737
private $fileLinkFormat;
3838
private $scope;
3939
private $firstCall = true;
40+
private $hasTerminatedWithException;
4041

4142
/**
4243
* @param callable|null $exceptionHandler A handler that will be called on Exception
@@ -63,14 +64,16 @@ public function __construct(callable $exceptionHandler = null, LoggerInterface $
6364
*/
6465
public function configure(Event $event = null)
6566
{
66-
if (!$this->firstCall) {
67+
if (!$event instanceof KernelEvent ? !$this->firstCall : !$event->isMasterRequest()) {
6768
return;
6869
}
69-
$this->firstCall = false;
70+
$this->firstCall = $this->hasTerminatedWithException = false;
71+
72+
$handler = set_exception_handler('var_dump');
73+
$handler = is_array($handler) ? $handler[0] : null;
74+
restore_exception_handler();
75+
7076
if ($this->logger || null !== $this->throwAt) {
71-
$handler = set_error_handler('var_dump');
72-
$handler = is_array($handler) ? $handler[0] : null;
73-
restore_error_handler();
7477
if ($handler instanceof ErrorHandler) {
7578
if ($this->logger) {
7679
$handler->setDefaultLogger($this->logger, $this->levels);
@@ -99,8 +102,16 @@ public function configure(Event $event = null)
99102
}
100103
if (!$this->exceptionHandler) {
101104
if ($event instanceof KernelEvent) {
102-
if (method_exists($event->getKernel(), 'terminateWithException')) {
103-
$this->exceptionHandler = array($event->getKernel(), 'terminateWithException');
105+
if (method_exists($kernel = $event->getKernel(), 'terminateWithException')) {
106+
$request = $event->getRequest();
107+
$hasRun = &$this->hasTerminatedWithException;
108+
$this->exceptionHandler = function (\Exception $e) use ($kernel, $request, &$hasRun) {
109+
if ($hasRun) {
110+
throw $e;
111+
}
112+
$hasRun = true;
113+
$kernel->terminateWithException($e, $request);
114+
};
104115
}
105116
} elseif ($event instanceof ConsoleEvent && $app = $event->getCommand()->getApplication()) {
106117
$output = $event->getOutput();
@@ -113,9 +124,6 @@ public function configure(Event $event = null)
113124
}
114125
}
115126
if ($this->exceptionHandler) {
116-
$handler = set_exception_handler('var_dump');
117-
$handler = is_array($handler) ? $handler[0] : null;
118-
restore_exception_handler();
119127
if ($handler instanceof ErrorHandler) {
120128
$h = $handler->setExceptionHandler('var_dump') ?: $this->exceptionHandler;
121129
$handler->setExceptionHandler($h);

0 commit comments

Comments
 (0)