Skip to content

Commit 0293f37

Browse files
author
Robin Chalas
committed
Merge branch '2.7' into 2.8
* 2.7: [Intl] Fixed the broken link [Routing] Fix trailing slash redirection for non-safe verbs [Debug] Fix bad registration of exception handler, leading to mem leak [Form] Fixed empty data on expanded ChoiceType and FileType
2 parents 49b94cc + b49a6b7 commit 0293f37

File tree

14 files changed

+317
-78
lines changed

14 files changed

+317
-78
lines changed

src/Symfony/Component/Debug/ErrorHandler.php

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,9 +151,20 @@ public static function register($handler = null, $replace = true)
151151
}
152152
if (!$replace && $prev) {
153153
restore_error_handler();
154+
$handlerIsRegistered = is_array($prev) && $handler === $prev[0];
155+
} else {
156+
$handlerIsRegistered = true;
154157
}
155-
if (is_array($prev = set_exception_handler(array($handler, 'handleException'))) && $prev[0] === $handler) {
158+
if (is_array($prev = set_exception_handler(array($handler, 'handleException'))) && $prev[0] instanceof self) {
156159
restore_exception_handler();
160+
if (!$handlerIsRegistered) {
161+
$handler = $prev[0];
162+
} elseif ($handler !== $prev[0] && $replace) {
163+
set_exception_handler(array($handler, 'handleException'));
164+
$p = $prev[0]->setExceptionHandler(null);
165+
$handler->setExceptionHandler($p);
166+
$prev[0]->setExceptionHandler($p);
167+
}
157168
} else {
158169
$handler->setExceptionHandler($prev);
159170
}

src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public function testRegister()
3535

3636
$newHandler = new ErrorHandler();
3737

38-
$this->assertSame($newHandler, ErrorHandler::register($newHandler, false));
38+
$this->assertSame($handler, ErrorHandler::register($newHandler, false));
3939
$h = set_error_handler('var_dump');
4040
restore_error_handler();
4141
$this->assertSame(array($handler, 'handleError'), $h);

src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
use Symfony\Component\Form\Extension\Core\EventListener\MergeCollectionListener;
3434
use Symfony\Component\Form\Extension\Core\DataTransformer\ChoiceToValueTransformer;
3535
use Symfony\Component\Form\Extension\Core\DataTransformer\ChoicesToValuesTransformer;
36-
use Symfony\Component\Form\Util\FormUtil;
3736
use Symfony\Component\OptionsResolver\Options;
3837
use Symfony\Component\OptionsResolver\OptionsResolver;
3938

@@ -91,12 +90,12 @@ public function buildForm(FormBuilderInterface $builder, array $options)
9190
$form = $event->getForm();
9291
$data = $event->getData();
9392

93+
// Since the type always use mapper an empty array will not be
94+
// considered as empty in Form::submit(), we need to evaluate
95+
// empty data here so its value is submitted to sub forms
9496
if (null === $data) {
9597
$emptyData = $form->getConfig()->getEmptyData();
96-
97-
if (false === FormUtil::isEmpty($emptyData) && array() !== $emptyData) {
98-
$data = is_callable($emptyData) ? call_user_func($emptyData, $form, $data) : $emptyData;
99-
}
98+
$data = $emptyData instanceof \Closure ? $emptyData($form, $data) : $emptyData;
10099
}
101100

102101
// Convert the submitted data to a string, if scalar, before

src/Symfony/Component/Form/Extension/Core/Type/FileType.php

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ class FileType extends AbstractType
2727
*/
2828
public function buildForm(FormBuilderInterface $builder, array $options)
2929
{
30+
// Ensure that submitted data is always an uploaded file or an array of some
3031
$builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) use ($options) {
3132
$form = $event->getForm();
3233
$requestHandler = $form->getConfig()->getRequestHandler();
33-
$data = null;
3434

3535
if ($options['multiple']) {
3636
$data = array();
@@ -46,19 +46,16 @@ public function buildForm(FormBuilderInterface $builder, array $options)
4646
}
4747
}
4848

49-
// submitted data for an input file (not required) without choosing any file
50-
if (array(null) === $data || array() === $data) {
49+
// Since the array is never considered empty in the view data format
50+
// on submission, we need to evaluate the configured empty data here
51+
if (array() === $data) {
5152
$emptyData = $form->getConfig()->getEmptyData();
52-
53-
$data = is_callable($emptyData) ? call_user_func($emptyData, $form, $data) : $emptyData;
53+
$data = $emptyData instanceof \Closure ? $emptyData($form, $data) : $emptyData;
5454
}
5555

5656
$event->setData($data);
5757
} elseif (!$requestHandler->isFileUpload($event->getData())) {
58-
$emptyData = $form->getConfig()->getEmptyData();
59-
60-
$data = is_callable($emptyData) ? call_user_func($emptyData, $form, $data) : $emptyData;
61-
$event->setData($data);
58+
$event->setData(null);
6259
}
6360
});
6461
}

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

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,21 @@ public function testSubmitSingleChoiceWithEmptyData()
699699
$this->assertSame('test', $form->getData());
700700
}
701701

702+
public function testSubmitSingleChoiceWithEmptyDataAndInitialData()
703+
{
704+
$form = $this->factory->create(static::TESTED_TYPE, 'initial', array(
705+
'multiple' => false,
706+
'expanded' => false,
707+
'choices' => array('initial', 'test'),
708+
'choices_as_values' => true,
709+
'empty_data' => 'test',
710+
));
711+
712+
$form->submit(null);
713+
714+
$this->assertSame('test', $form->getData());
715+
}
716+
702717
public function testSubmitMultipleChoiceWithEmptyData()
703718
{
704719
$form = $this->factory->create(static::TESTED_TYPE, null, array(
@@ -714,6 +729,36 @@ public function testSubmitMultipleChoiceWithEmptyData()
714729
$this->assertSame(array('test'), $form->getData());
715730
}
716731

732+
public function testSubmitMultipleChoiceWithEmptyDataAndInitialEmptyArray()
733+
{
734+
$form = $this->factory->create(static::TESTED_TYPE, array(), array(
735+
'multiple' => true,
736+
'expanded' => false,
737+
'choices' => array('test'),
738+
'choices_as_values' => true,
739+
'empty_data' => array('test'),
740+
));
741+
742+
$form->submit(null);
743+
744+
$this->assertSame(array('test'), $form->getData());
745+
}
746+
747+
public function testSubmitMultipleChoiceWithEmptyDataAndInitialData()
748+
{
749+
$form = $this->factory->create(static::TESTED_TYPE, array('initial'), array(
750+
'multiple' => true,
751+
'expanded' => false,
752+
'choices' => array('initial', 'test'),
753+
'choices_as_values' => true,
754+
'empty_data' => array('test'),
755+
));
756+
757+
$form->submit(null);
758+
759+
$this->assertSame(array('test'), $form->getData());
760+
}
761+
717762
public function testSubmitSingleChoiceExpandedWithEmptyData()
718763
{
719764
$form = $this->factory->create(static::TESTED_TYPE, null, array(
@@ -729,6 +774,21 @@ public function testSubmitSingleChoiceExpandedWithEmptyData()
729774
$this->assertSame('test', $form->getData());
730775
}
731776

777+
public function testSubmitSingleChoiceExpandedWithEmptyDataAndInitialData()
778+
{
779+
$form = $this->factory->create(static::TESTED_TYPE, 'initial', array(
780+
'multiple' => false,
781+
'expanded' => true,
782+
'choices' => array('initial', 'test'),
783+
'choices_as_values' => true,
784+
'empty_data' => 'test',
785+
));
786+
787+
$form->submit(null);
788+
789+
$this->assertSame('test', $form->getData());
790+
}
791+
732792
public function testSubmitMultipleChoiceExpandedWithEmptyData()
733793
{
734794
$form = $this->factory->create(static::TESTED_TYPE, null, array(
@@ -744,6 +804,36 @@ public function testSubmitMultipleChoiceExpandedWithEmptyData()
744804
$this->assertSame(array('test'), $form->getData());
745805
}
746806

807+
public function testSubmitMultipleChoiceExpandedWithEmptyDataAndInitialEmptyArray()
808+
{
809+
$form = $this->factory->create(static::TESTED_TYPE, array(), array(
810+
'multiple' => true,
811+
'expanded' => true,
812+
'choices' => array('test'),
813+
'choices_as_values' => true,
814+
'empty_data' => array('test'),
815+
));
816+
817+
$form->submit(null);
818+
819+
$this->assertSame(array('test'), $form->getData());
820+
}
821+
822+
public function testSubmitMultipleChoiceExpandedWithEmptyDataAndInitialData()
823+
{
824+
$form = $this->factory->create(static::TESTED_TYPE, array('init'), array(
825+
'multiple' => true,
826+
'expanded' => true,
827+
'choices' => array('init', 'test'),
828+
'choices_as_values' => true,
829+
'empty_data' => array('test'),
830+
));
831+
832+
$form->submit(null);
833+
834+
$this->assertSame(array('test'), $form->getData());
835+
}
836+
747837
/**
748838
* @group legacy
749839
*/

src/Symfony/Component/Intl/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ A PHP replacement layer for the C intl extension that also provides access to
55
the localization data of the ICU library.
66

77
The replacement layer is limited to the locale "en". If you want to use other
8-
locales, you should [install the intl PHP extension] [0] instead.
8+
locales, you should [install the intl PHP extension][0] instead.
99

1010
Resources
1111
---------

src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ public function match(\$rawPathinfo)
101101
\$allow = array();
102102
\$pathinfo = rawurldecode(\$rawPathinfo);
103103
\$context = \$this->context;
104-
\$request = \$this->request;
104+
\$request = \$this->request ?: \$this->createRequest(\$pathinfo);
105105
106106
$code
107107
@@ -283,7 +283,11 @@ private function compileRoute(Route $route, $name, $supportsRedirections, $paren
283283

284284
if ($hasTrailingSlash) {
285285
$code .= <<<EOF
286-
if (substr(\$pathinfo, -1) !== '/') {
286+
if ('/' === substr(\$pathinfo, -1)) {
287+
// no-op
288+
} elseif (!in_array(\$this->context->getMethod(), array('HEAD', 'GET'))) {
289+
goto $gotoname;
290+
} else {
287291
return \$this->redirect(\$rawPathinfo.'/', '$name');
288292
}
289293
@@ -329,7 +333,7 @@ private function compileRoute(Route $route, $name, $supportsRedirections, $paren
329333
}
330334
$code .= " }\n";
331335

332-
if ($methods) {
336+
if ($methods || $hasTrailingSlash) {
333337
$code .= " $gotoname:\n";
334338
}
335339

src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public function match($rawPathinfo)
2020
$allow = array();
2121
$pathinfo = rawurldecode($rawPathinfo);
2222
$context = $this->context;
23-
$request = $this->request;
23+
$request = $this->request ?: $this->createRequest($pathinfo);
2424

2525
// foo
2626
if (0 === strpos($pathinfo, '/foo') && preg_match('#^/foo/(?P<bar>baz|symfony)$#s', $pathinfo, $matches)) {

src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public function match($rawPathinfo)
2020
$allow = array();
2121
$pathinfo = rawurldecode($rawPathinfo);
2222
$context = $this->context;
23-
$request = $this->request;
23+
$request = $this->request ?: $this->createRequest($pathinfo);
2424

2525
// foo
2626
if (0 === strpos($pathinfo, '/foo') && preg_match('#^/foo/(?P<bar>baz|symfony)$#s', $pathinfo, $matches)) {
@@ -66,23 +66,33 @@ public function match($rawPathinfo)
6666

6767
// baz3
6868
if ('/test/baz3' === rtrim($pathinfo, '/')) {
69-
if (substr($pathinfo, -1) !== '/') {
69+
if ('/' === substr($pathinfo, -1)) {
70+
// no-op
71+
} elseif (!in_array($this->context->getMethod(), array('HEAD', 'GET'))) {
72+
goto not_baz3;
73+
} else {
7074
return $this->redirect($rawPathinfo.'/', 'baz3');
7175
}
7276

7377
return array('_route' => 'baz3');
7478
}
79+
not_baz3:
7580

7681
}
7782

7883
// baz4
7984
if (preg_match('#^/test/(?P<foo>[^/]++)/?$#s', $pathinfo, $matches)) {
80-
if (substr($pathinfo, -1) !== '/') {
85+
if ('/' === substr($pathinfo, -1)) {
86+
// no-op
87+
} elseif (!in_array($this->context->getMethod(), array('HEAD', 'GET'))) {
88+
goto not_baz4;
89+
} else {
8190
return $this->redirect($rawPathinfo.'/', 'baz4');
8291
}
8392

8493
return $this->mergeDefaults(array_replace($matches, array('_route' => 'baz4')), array ());
8594
}
95+
not_baz4:
8696

8797
// baz5
8898
if (preg_match('#^/test/(?P<foo>[^/]++)/$#s', $pathinfo, $matches)) {
@@ -170,12 +180,17 @@ public function match($rawPathinfo)
170180

171181
// hey
172182
if ('/multi/hey' === rtrim($pathinfo, '/')) {
173-
if (substr($pathinfo, -1) !== '/') {
183+
if ('/' === substr($pathinfo, -1)) {
184+
// no-op
185+
} elseif (!in_array($this->context->getMethod(), array('HEAD', 'GET'))) {
186+
goto not_hey;
187+
} else {
174188
return $this->redirect($rawPathinfo.'/', 'hey');
175189
}
176190

177191
return array('_route' => 'hey');
178192
}
193+
not_hey:
179194

180195
}
181196

src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher3.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public function match($rawPathinfo)
2020
$allow = array();
2121
$pathinfo = rawurldecode($rawPathinfo);
2222
$context = $this->context;
23-
$request = $this->request;
23+
$request = $this->request ?: $this->createRequest($pathinfo);
2424

2525
if (0 === strpos($pathinfo, '/rootprefix')) {
2626
// static

0 commit comments

Comments
 (0)