Skip to content

Commit

Permalink
Merge branch '3.4' into 4.1
Browse files Browse the repository at this point in the history
* 3.4:
  [HttpFoundation] Check file exists before unlink
  [Console] Fixed #29835: ConfirmationQuestion with default true for answer '0'
  [Translation] Concatenated translation messages
  [Form] ensure compatibility with older PHPUnit mocks
  [Serializer] Docblock about throwing exceptions on serializer
  [Debug][ErrorHandler] Preserve our error handler when a logger set another one
  [Form] Changed UrlType input type to text when default_protocol is not null
  [Bugfix] MemcachedSessionHandler::close() must close connection
  • Loading branch information
nicolas-grekas committed Jan 25, 2019
2 parents 343d24d + afb7bb5 commit 02fe23d
Show file tree
Hide file tree
Showing 36 changed files with 517 additions and 345 deletions.
Expand Up @@ -2402,13 +2402,29 @@ public function testTimezoneWithPlaceholder()
);
}

public function testUrl()
public function testUrlWithDefaultProtocol()
{
$url = 'http://www.google.com?foo1=bar1&foo2=bar2';
$form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\UrlType', $url);
$form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\UrlType', $url, ['default_protocol' => 'http']);

$this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']],
'/input
[@type="text"]
[@name="name"]
[@class="my&class form-control"]
[@value="http://www.google.com?foo1=bar1&foo2=bar2"]
[@inputmode="url"]
'
);
}

public function testUrlWithoutDefaultProtocol()
{
$url = 'http://www.google.com?foo1=bar1&foo2=bar2';
$form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\UrlType', $url, ['default_protocol' => null]);

$this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']],
'/input
[@type="url"]
[@name="name"]
[@class="my&class form-control"]
Expand Down
2 changes: 1 addition & 1 deletion src/Symfony/Bridge/Twig/composer.json
Expand Up @@ -23,7 +23,7 @@
"symfony/asset": "~3.4|~4.0",
"symfony/dependency-injection": "~3.4|~4.0",
"symfony/finder": "~3.4|~4.0",
"symfony/form": "^4.1.5",
"symfony/form": "^4.1.11|^4.2.3",
"symfony/http-foundation": "~3.4|~4.0",
"symfony/http-kernel": "~3.4|~4.0",
"symfony/polyfill-intl-icu": "~1.0",
Expand Down
Expand Up @@ -15,6 +15,7 @@
use Symfony\Bundle\FrameworkBundle\Tests\TestCase;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\Form\Form;
use Symfony\Component\Form\FormConfigInterface;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\JsonResponse;
Expand Down Expand Up @@ -487,8 +488,7 @@ public function testCreateNotFoundException()

public function testCreateForm()
{
$config = $this->getMockBuilder('Symfony\Component\Form\FormConfigInterface')->getMock();
$form = new Form($config);
$form = new Form($this->getMockBuilder(FormConfigInterface::class)->getMock());

$formFactory = $this->getMockBuilder('Symfony\Component\Form\FormFactoryInterface')->getMock();
$formFactory->expects($this->once())->method('create')->willReturn($form);
Expand Down
2 changes: 1 addition & 1 deletion src/Symfony/Bundle/FrameworkBundle/composer.json
Expand Up @@ -39,7 +39,7 @@
"symfony/dom-crawler": "~3.4|~4.0",
"symfony/polyfill-intl-icu": "~1.0",
"symfony/security": "~3.4|~4.0",
"symfony/form": "^4.1",
"symfony/form": "^4.1.11|^4.2.3",
"symfony/expression-language": "~3.4|~4.0",
"symfony/messenger": "^4.1",
"symfony/process": "~3.4|~4.0",
Expand Down
Expand Up @@ -13,6 +13,7 @@

use Symfony\Bundle\WebProfilerBundle\Profiler\TemplateManager;
use Symfony\Bundle\WebProfilerBundle\Tests\TestCase;
use Symfony\Component\HttpKernel\Profiler\Profile;
use Twig\Environment;

/**
Expand Down Expand Up @@ -57,8 +58,7 @@ protected function setUp()
*/
public function testGetNameOfInvalidTemplate()
{
$profile = $this->mockProfile();
$this->templateManager->getName($profile, 'notexistingpanel');
$this->templateManager->getName(new Profile('token'), 'notexistingpanel');
}

/**
Expand All @@ -71,12 +71,24 @@ public function testGetNameValidTemplate()
->withAnyParameters()
->will($this->returnCallback([$this, 'profilerHasCallback']));

$profile = $this->mockProfile();
$profile->expects($this->any())
->method('hasCollector')
$this->assertEquals('FooBundle:Collector:foo.html.twig', $this->templateManager->getName(new ProfileDummy(), 'foo'));
}

/**
* template should be loaded for 'foo' because other collectors are
* missing in profile or in profiler.
*/
public function testGetTemplates()
{
$this->profiler->expects($this->any())
->method('has')
->withAnyParameters()
->will($this->returnCallback([$this, 'profileHasCollectorCallback']));

$this->assertEquals('FooBundle:Collector:foo.html.twig', $this->templateManager->getName($profile, 'foo'));
$result = $this->templateManager->getTemplates(new ProfileDummy());
$this->assertArrayHasKey('foo', $result);
$this->assertArrayNotHasKey('bar', $result);
$this->assertArrayNotHasKey('baz', $result);
}

public function profilerHasCallback($panel)
Expand Down Expand Up @@ -133,3 +145,22 @@ protected function mockProfiler()
return $this->profiler;
}
}

class ProfileDummy extends Profile
{
public function __construct()
{
parent::__construct('token');
}

public function hasCollector($name)
{
switch ($name) {
case 'foo':
case 'bar':
return true;
default:
return false;
}
}
}
Expand Up @@ -53,7 +53,7 @@ private function getDefaultNormalizer()
return $answer && $answerIsTrue;
}

return !$answer || $answerIsTrue;
return '' === $answer || $answerIsTrue;
};
}
}
@@ -0,0 +1,62 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Console\Tests\Question;

use PHPUnit\Framework\TestCase;
use Symfony\Component\Console\Question\ConfirmationQuestion;

class ConfirmationQuestionTest extends TestCase
{
/**
* @dataProvider normalizerUsecases
*/
public function testDefaultRegexUsecases($default, $answers, $expected, $message)
{
$sut = new ConfirmationQuestion('A question', $default);

foreach ($answers as $answer) {
$normalizer = $sut->getNormalizer();
$actual = $normalizer($answer);
$this->assertEquals($expected, $actual, sprintf($message, $answer));
}
}

public function normalizerUsecases()
{
return [
[
true,
['y', 'Y', 'yes', 'YES', 'yEs', ''],
true,
'When default is true, the normalizer must return true for "%s"',
],
[
true,
['n', 'N', 'no', 'NO', 'nO', 'foo', '1', '0'],
false,
'When default is true, the normalizer must return false for "%s"',
],
[
false,
['y', 'Y', 'yes', 'YES', 'yEs'],
true,
'When default is false, the normalizer must return true for "%s"',
],
[
false,
['n', 'N', 'no', 'NO', 'nO', 'foo', '1', '0', ''],
false,
'When default is false, the normalizer must return false for "%s"',
],
];
}
}
4 changes: 4 additions & 0 deletions src/Symfony/Component/Debug/ErrorHandler.php
Expand Up @@ -492,6 +492,10 @@ public function handleError($type, $message, $file, $line)
$this->loggers[$type][0]->log($level, $logMessage, $errorAsException ? ['exception' => $errorAsException] : []);
} finally {
$this->isRecursive = false;

if (!\defined('HHVM_VERSION')) {
set_error_handler([$this, __FUNCTION__]);
}
}
}

Expand Down
44 changes: 44 additions & 0 deletions src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php
Expand Up @@ -12,10 +12,13 @@
namespace Symfony\Component\Debug\Tests;

use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;
use Psr\Log\NullLogger;
use Symfony\Component\Debug\BufferingLogger;
use Symfony\Component\Debug\ErrorHandler;
use Symfony\Component\Debug\Exception\SilencedErrorContext;
use Symfony\Component\Debug\Tests\Fixtures\LoggerThatSetAnErrorHandler;

/**
* ErrorHandlerTest.
Expand Down Expand Up @@ -321,6 +324,8 @@ public function testHandleDeprecation()
$handler = new ErrorHandler();
$handler->setDefaultLogger($logger);
@$handler->handleError(E_USER_DEPRECATED, 'Foo deprecation', __FILE__, __LINE__, []);

restore_error_handler();
}

public function testHandleException()
Expand Down Expand Up @@ -501,4 +506,43 @@ public function testCustomExceptionHandler()

$handler->handleException(new \Exception());
}

/**
* @dataProvider errorHandlerIsNotLostWhenLoggingProvider
*/
public function testErrorHandlerIsNotLostWhenLogging($customErrorHandlerHasBeenPreviouslyDefined, LoggerInterface $logger)
{
try {
if ($customErrorHandlerHasBeenPreviouslyDefined) {
set_error_handler('count');
}

$handler = ErrorHandler::register();
$handler->setDefaultLogger($logger);

@trigger_error('foo', E_USER_DEPRECATED);
@trigger_error('bar', E_USER_DEPRECATED);

$this->assertSame([$handler, 'handleError'], set_error_handler('var_dump'));

restore_error_handler();

if ($customErrorHandlerHasBeenPreviouslyDefined) {
restore_error_handler();
}
} finally {
restore_error_handler();
restore_exception_handler();
}
}

public function errorHandlerIsNotLostWhenLoggingProvider()
{
return [
[false, new NullLogger()],
[true, new NullLogger()],
[false, new LoggerThatSetAnErrorHandler()],
[true, new LoggerThatSetAnErrorHandler()],
];
}
}
@@ -0,0 +1,14 @@
<?php

namespace Symfony\Component\Debug\Tests\Fixtures;

use Psr\Log\AbstractLogger;

class LoggerThatSetAnErrorHandler extends AbstractLogger
{
public function log($level, $message, array $context = [])
{
set_error_handler('is_string');
restore_error_handler();
}
}
13 changes: 13 additions & 0 deletions src/Symfony/Component/Form/Extension/Core/Type/UrlType.php
Expand Up @@ -14,6 +14,8 @@
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\EventListener\FixUrlProtocolListener;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolver;

class UrlType extends AbstractType
Expand All @@ -28,6 +30,17 @@ public function buildForm(FormBuilderInterface $builder, array $options)
}
}

/**
* {@inheritdoc}
*/
public function buildView(FormView $view, FormInterface $form, array $options)
{
if ($options['default_protocol']) {
$view->vars['attr']['inputmode'] = 'url';
$view->vars['type'] = 'text';
}
}

/**
* {@inheritdoc}
*/
Expand Down
8 changes: 5 additions & 3 deletions src/Symfony/Component/Form/Form.php
Expand Up @@ -532,9 +532,11 @@ public function submit($submittedData, $clearMissing = true)
$submittedData = null;
} elseif (is_scalar($submittedData)) {
$submittedData = (string) $submittedData;
} elseif (!$this->config->getOption('allow_file_upload') && $this->config->getRequestHandler()->isFileUpload($submittedData)) {
$submittedData = null;
$this->transformationFailure = new TransformationFailedException('Submitted data was expected to be text or number, file upload given.');
} elseif ($this->config->getRequestHandler()->isFileUpload($submittedData)) {
if (!$this->config->getOption('allow_file_upload')) {
$submittedData = null;
$this->transformationFailure = new TransformationFailedException('Submitted data was expected to be text or number, file upload given.');
}
} elseif (\is_array($submittedData) && !$this->config->getCompound() && !$this->config->hasOption('multiple')) {
$submittedData = null;
$this->transformationFailure = new TransformationFailedException('Submitted data was expected to be text or number, array given.');
Expand Down
20 changes: 0 additions & 20 deletions src/Symfony/Component/Form/Tests/AbstractFormTest.php
Expand Up @@ -65,26 +65,6 @@ protected function getBuilder($name = 'name', EventDispatcherInterface $dispatch
return new FormBuilder($name, $dataClass, $dispatcher ?: $this->dispatcher, $this->factory, $options);
}

/**
* @param string $name
*
* @return \PHPUnit_Framework_MockObject_MockObject
*/
protected function getMockForm($name = 'name')
{
$form = $this->getMockBuilder('Symfony\Component\Form\Test\FormInterface')->getMock();
$config = $this->getMockBuilder('Symfony\Component\Form\FormConfigInterface')->getMock();

$form->expects($this->any())
->method('getName')
->will($this->returnValue($name));
$form->expects($this->any())
->method('getConfig')
->will($this->returnValue($config));

return $form;
}

/**
* @return \PHPUnit_Framework_MockObject_MockObject
*/
Expand Down
19 changes: 17 additions & 2 deletions src/Symfony/Component/Form/Tests/AbstractLayoutTest.php
Expand Up @@ -2236,10 +2236,25 @@ public function testTimezoneWithPlaceholder()
);
}

public function testUrl()
public function testUrlWithDefaultProtocol()
{
$url = 'http://www.google.com?foo1=bar1&foo2=bar2';
$form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\UrlType', $url);
$form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\UrlType', $url, ['default_protocol' => 'http']);

$this->assertWidgetMatchesXpath($form->createView(), [],
'/input
[@type="text"]
[@name="name"]
[@value="http://www.google.com?foo1=bar1&foo2=bar2"]
[@inputmode="url"]
'
);
}

public function testUrlWithoutDefaultProtocol()
{
$url = 'http://www.google.com?foo1=bar1&foo2=bar2';
$form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\UrlType', $url, ['default_protocol' => null]);

$this->assertWidgetMatchesXpath($form->createView(), [],
'/input
Expand Down

0 comments on commit 02fe23d

Please sign in to comment.