Skip to content

Commit eddd273

Browse files
committed
Merge branch '2.7' into 2.8
* 2.7: [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 af81bb5 + 9ac08e8 commit eddd273

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
@@ -31,6 +31,7 @@
3131
-moz-box-sizing: content-box;
3232
box-sizing: content-box;
3333
vertical-align: baseline;
34+
width: auto;
3435
}
3536

3637
.sf-toolbarreset {

src/Symfony/Component/Debug/ErrorHandler.php

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,7 @@ public function handleException($exception, array $error = null)
555555
$exception = new FatalThrowableError($exception);
556556
}
557557
$type = $exception instanceof FatalErrorException ? $exception->getSeverity() : E_ERROR;
558+
$handlerException = null;
558559

559560
if (($this->loggedErrors & $type) || $exception instanceof FatalThrowableError) {
560561
$e = array(
@@ -599,18 +600,20 @@ public function handleException($exception, array $error = null)
599600
}
600601
}
601602
}
602-
if (empty($this->exceptionHandler)) {
603-
throw $exception; // Give back $exception to the native handler
604-
}
605603
try {
606-
call_user_func($this->exceptionHandler, $exception);
604+
if (null !== $this->exceptionHandler) {
605+
return \call_user_func($this->exceptionHandler, $exception);
606+
}
607+
$handlerException = $handlerException ?: $exception;
607608
} catch (\Exception $handlerException) {
608609
} catch (\Throwable $handlerException) {
609610
}
610-
if (isset($handlerException)) {
611-
$this->exceptionHandler = null;
612-
$this->handleException($handlerException);
611+
$this->exceptionHandler = null;
612+
if ($exception === $handlerException) {
613+
self::$reservedMemory = null; // Disable the fatal error handler
614+
throw $exception; // Give back $exception to the native handler
613615
}
616+
$this->handleException($handlerException);
614617
}
615618

616619
/**
@@ -626,15 +629,30 @@ public static function handleFatalError(array $error = null)
626629
return;
627630
}
628631

629-
self::$reservedMemory = null;
632+
$handler = self::$reservedMemory = null;
633+
$handlers = array();
630634

631-
$handler = set_error_handler('var_dump');
632-
$handler = is_array($handler) ? $handler[0] : null;
633-
restore_error_handler();
635+
while (!is_array($handler) || !$handler[0] instanceof self) {
636+
$handler = set_exception_handler('var_dump');
637+
restore_exception_handler();
634638

635-
if (!$handler instanceof self) {
639+
if (!$handler) {
640+
break;
641+
}
642+
restore_exception_handler();
643+
array_unshift($handlers, $handler);
644+
}
645+
foreach ($handlers as $h) {
646+
set_exception_handler($h);
647+
}
648+
if (!$handler) {
636649
return;
637650
}
651+
if ($handler !== $h) {
652+
$handler[0]->setExceptionHandler($h);
653+
}
654+
$handler = $handler[0];
655+
$handlers = array();
638656

639657
if ($exit = null === $error) {
640658
$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
@@ -1977,6 +1977,25 @@ public function testMoney()
19771977
);
19781978
}
19791979

1980+
public function testMoneyWithoutCurrency()
1981+
{
1982+
$form = $this->factory->createNamed('name', 'money', 1234.56, array(
1983+
'currency' => false,
1984+
));
1985+
1986+
$this->assertWidgetMatchesXpath($form->createView(), array('id' => 'my&id', 'attr' => array('class' => 'my&class')),
1987+
'/input
1988+
[@id="my&id"]
1989+
[@type="text"]
1990+
[@name="name"]
1991+
[@class="my&class form-control"]
1992+
[@value="1234.56"]
1993+
[not(preceding-sibling::*)]
1994+
[not(following-sibling::*)]
1995+
'
1996+
);
1997+
}
1998+
19801999
public function testNumber()
19812000
{
19822001
$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
@@ -53,7 +53,7 @@ public function testMoneyPatternWorksForYen()
5353
$view = $this->factory->create(static::TESTED_TYPE, null, array('currency' => 'JPY'))
5454
->createView();
5555

56-
$this->assertTrue((bool) strstr($view->vars['money_pattern'], '¥'));
56+
$this->assertSame('¥ {{ widget }}', $view->vars['money_pattern']);
5757
}
5858

5959
// https://github.com/symfony/symfony/issues/5458
@@ -72,4 +72,12 @@ public function testSubmitNull($expected = null, $norm = null, $view = null)
7272
{
7373
parent::testSubmitNull($expected, $norm, '');
7474
}
75+
76+
public function testMoneyPatternWithoutCurrency()
77+
{
78+
$view = $this->factory->create(static::TESTED_TYPE, null, array('currency' => false))
79+
->createView();
80+
81+
$this->assertSame('{{ widget }}', $view->vars['money_pattern']);
82+
}
7583
}

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
@@ -36,6 +36,7 @@ class DebugHandlersListener implements EventSubscriberInterface
3636
private $scream;
3737
private $fileLinkFormat;
3838
private $firstCall = true;
39+
private $hasTerminatedWithException;
3940

4041
/**
4142
* @param callable|null $exceptionHandler A handler that will be called on Exception
@@ -60,14 +61,16 @@ public function __construct($exceptionHandler, LoggerInterface $logger = null, $
6061
*/
6162
public function configure(Event $event = null)
6263
{
63-
if (!$this->firstCall) {
64+
if (!$event instanceof KernelEvent ? !$this->firstCall : !$event->isMasterRequest()) {
6465
return;
6566
}
66-
$this->firstCall = false;
67+
$this->firstCall = $this->hasTerminatedWithException = false;
68+
69+
$handler = set_exception_handler('var_dump');
70+
$handler = is_array($handler) ? $handler[0] : null;
71+
restore_exception_handler();
72+
6773
if ($this->logger || null !== $this->throwAt) {
68-
$handler = set_error_handler('var_dump');
69-
$handler = is_array($handler) ? $handler[0] : null;
70-
restore_error_handler();
7174
if ($handler instanceof ErrorHandler) {
7275
if ($this->logger) {
7376
$handler->setDefaultLogger($this->logger, $this->levels);
@@ -91,8 +94,16 @@ public function configure(Event $event = null)
9194
}
9295
if (!$this->exceptionHandler) {
9396
if ($event instanceof KernelEvent) {
94-
if (method_exists($event->getKernel(), 'terminateWithException')) {
95-
$this->exceptionHandler = array($event->getKernel(), 'terminateWithException');
97+
if (method_exists($kernel = $event->getKernel(), 'terminateWithException')) {
98+
$request = $event->getRequest();
99+
$hasRun = &$this->hasTerminatedWithException;
100+
$this->exceptionHandler = function (\Exception $e) use ($kernel, $request, &$hasRun) {
101+
if ($hasRun) {
102+
throw $e;
103+
}
104+
$hasRun = true;
105+
$kernel->terminateWithException($e, $request);
106+
};
96107
}
97108
} elseif ($event instanceof ConsoleEvent && $app = $event->getCommand()->getApplication()) {
98109
$output = $event->getOutput();
@@ -105,9 +116,6 @@ public function configure(Event $event = null)
105116
}
106117
}
107118
if ($this->exceptionHandler) {
108-
$handler = set_exception_handler('var_dump');
109-
$handler = is_array($handler) ? $handler[0] : null;
110-
restore_exception_handler();
111119
if ($handler instanceof ErrorHandler) {
112120
$h = $handler->setExceptionHandler('var_dump') ?: $this->exceptionHandler;
113121
$handler->setExceptionHandler($h);

0 commit comments

Comments
 (0)