diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig
index d281aa0fc7..ad5011082f 100644
--- a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig
+++ b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig
@@ -112,11 +112,11 @@
{%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%}
{%- endif -%}
- {{- form_label(form) -}}
- {{- form_widget(form, widget_attr) -}}
- {{- form_help(form) -}}
- {{- form_errors(form) -}}
-
+ {{- form_label(form) }} {# -#}
+ {{ form_widget(form, widget_attr) }} {# -#}
+ {{ form_widget(form) }} {# -#}
+ {{ form_errors(form) }} {# -#}
+ {# -#}
{%- endblock form_row %}
{% block button_row -%}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml
index 4ca196e47d..36d80501bd 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml
@@ -70,6 +70,9 @@
+
+
+
diff --git a/src/Symfony/Component/BrowserKit/Tests/ClientTest.php b/src/Symfony/Component/BrowserKit/Tests/ClientTest.php
index 8bc169872e..530d05abba 100644
--- a/src/Symfony/Component/BrowserKit/Tests/ClientTest.php
+++ b/src/Symfony/Component/BrowserKit/Tests/ClientTest.php
@@ -778,6 +778,9 @@ class ClientTest extends TestCase
$this->assertEquals([], $client->getCookieJar()->all(), '->restart() clears the cookies');
}
+ /**
+ * @runInSeparateProcess
+ */
public function testInsulatedRequests()
{
$client = new TestClient();
diff --git a/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php b/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php
index cf23365d4f..43da7f2766 100644
--- a/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php
+++ b/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php
@@ -481,7 +481,7 @@ class ErrorHandlerTest extends TestCase
public function testHandleErrorException()
{
- $exception = new \Error("Class 'Foo' not found");
+ $exception = new \Error("Class 'IReallyReallyDoNotExistAnywhereInTheRepositoryISwear' not found");
$handler = new ErrorHandler();
$handler->setExceptionHandler(function () use (&$args) {
@@ -491,7 +491,7 @@ class ErrorHandlerTest extends TestCase
$handler->handleException($exception);
$this->assertInstanceOf('Symfony\Component\Debug\Exception\ClassNotFoundException', $args[0]);
- $this->assertStringStartsWith("Attempted to load class \"Foo\" from the global namespace.\nDid you forget a \"use\" statement", $args[0]->getMessage());
+ $this->assertStringStartsWith("Attempted to load class \"IReallyReallyDoNotExistAnywhereInTheRepositoryISwear\" from the global namespace.\nDid you forget a \"use\" statement", $args[0]->getMessage());
}
/**
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php
index 4349ee92e8..84dd0bbccc 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php
@@ -25,9 +25,9 @@ use Symfony\Component\DependencyInjection\Exception\AutowiringFailedException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\DependencyInjection\Tests\Fixtures\CaseSensitiveClass;
use Symfony\Component\DependencyInjection\Tests\Fixtures\includes\FooVariadic;
use Symfony\Component\DependencyInjection\TypedReference;
-use Symfony\Component\HttpKernel\HttpKernelInterface;
require_once __DIR__.'/../Fixtures/includes/autowiring_classes.php';
@@ -547,13 +547,17 @@ class AutowirePassTest extends TestCase
);
}
+ /**
+ * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
+ * @exceptedExceptionMessage Invalid service "Symfony\Component\DependencyInjection\Tests\Fixtures\NamedArgumentsDummy": method "setLogger()" does not exist.
+ */
public function testWithNonExistingSetterAndAutowiring()
{
$container = new ContainerBuilder();
- $definition = $container->register(HttpKernelInterface::class, HttpKernelInterface::class)->setAutowired(true);
+ $definition = $container->register(CaseSensitiveClass::class, CaseSensitiveClass::class)->setAutowired(true);
$definition->addMethodCall('setLogger');
- $this->expectException(RuntimeException::class);
+
(new ResolveClassPass())->process($container);
(new AutowireRequiredMethodsPass())->process($container);
(new AutowirePass())->process($container);
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveBindingsPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveBindingsPassTest.php
index 84b3d6c652..7bbecf6207 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveBindingsPassTest.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveBindingsPassTest.php
@@ -17,13 +17,11 @@ use Symfony\Component\DependencyInjection\Compiler\AutowireRequiredMethodsPass;
use Symfony\Component\DependencyInjection\Compiler\ResolveBindingsPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
-use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Tests\Fixtures\CaseSensitiveClass;
use Symfony\Component\DependencyInjection\Tests\Fixtures\NamedArgumentsDummy;
use Symfony\Component\DependencyInjection\Tests\Fixtures\ParentNotExists;
use Symfony\Component\DependencyInjection\TypedReference;
-use Symfony\Component\HttpKernel\HttpKernelInterface;
require_once __DIR__.'/../Fixtures/includes/autowiring_classes.php';
@@ -115,6 +113,10 @@ class ResolveBindingsPassTest extends TestCase
$this->assertEquals([['setDefaultLocale', ['fr']]], $definition->getMethodCalls());
}
+ /**
+ * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
+ * @exceptedExceptionMessage Invalid service "Symfony\Component\DependencyInjection\Tests\Fixtures\NamedArgumentsDummy": method "setLogger()" does not exist.
+ */
public function testWithNonExistingSetterAndBinding()
{
$container = new ContainerBuilder();
@@ -123,36 +125,11 @@ class ResolveBindingsPassTest extends TestCase
'$c' => (new Definition('logger'))->setFactory('logger'),
];
- $definition = $container->register(HttpKernelInterface::class, HttpKernelInterface::class);
+ $definition = $container->register(NamedArgumentsDummy::class, NamedArgumentsDummy::class);
$definition->addMethodCall('setLogger');
$definition->setBindings($bindings);
- $this->expectException(RuntimeException::class);
$pass = new ResolveBindingsPass();
$pass->process($container);
}
-
- public function testTupleBinding()
- {
- $container = new ContainerBuilder();
-
- $bindings = [
- '$c' => new BoundArgument(new Reference('bar')),
- CaseSensitiveClass::class.'$c' => new BoundArgument(new Reference('foo')),
- ];
-
- $definition = $container->register(NamedArgumentsDummy::class, NamedArgumentsDummy::class);
- $definition->addMethodCall('setSensitiveClass');
- $definition->addMethodCall('setAnotherC');
- $definition->setBindings($bindings);
-
- $pass = new ResolveBindingsPass();
- $pass->process($container);
-
- $expected = [
- ['setSensitiveClass', [new Reference('foo')]],
- ['setAnotherC', [new Reference('bar')]],
- ];
- $this->assertEquals($expected, $definition->getMethodCalls());
- }
}
diff --git a/src/Symfony/Component/Form/Extension/Core/Type/FileType.php b/src/Symfony/Component/Form/Extension/Core/Type/FileType.php
index 59c72889d6..f8afce2ee5 100644
--- a/src/Symfony/Component/Form/Extension/Core/Type/FileType.php
+++ b/src/Symfony/Component/Form/Extension/Core/Type/FileType.php
@@ -13,15 +13,33 @@ namespace Symfony\Component\Form\Extension\Core\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
+use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolver;
+use Symfony\Component\Translation\TranslatorInterface;
class FileType extends AbstractType
{
+ const KIB_BYTES = 1024;
+ const MIB_BYTES = 1048576;
+
+ private static $suffixes = [
+ 1 => 'bytes',
+ self::KIB_BYTES => 'KiB',
+ self::MIB_BYTES => 'MiB',
+ ];
+
+ private $translator;
+
+ public function __construct(TranslatorInterface $translator = null)
+ {
+ $this->translator = $translator;
+ }
+
/**
* {@inheritdoc}
*/
@@ -43,6 +61,10 @@ class FileType extends AbstractType
foreach ($files as $file) {
if ($requestHandler->isFileUpload($file)) {
$data[] = $file;
+
+ if (method_exists($requestHandler, 'getUploadFileError') && null !== $errorCode = $requestHandler->getUploadFileError($file)) {
+ $form->addError($this->getFileUploadError($errorCode));
+ }
}
}
@@ -54,6 +76,8 @@ class FileType extends AbstractType
}
$event->setData($data);
+ } elseif ($requestHandler->isFileUpload($event->getData()) && method_exists($requestHandler, 'getUploadFileError') && null !== $errorCode = $requestHandler->getUploadFileError($event->getData())) {
+ $form->addError($this->getFileUploadError($errorCode));
} elseif (!$requestHandler->isFileUpload($event->getData())) {
$event->setData(null);
}
@@ -116,4 +140,109 @@ class FileType extends AbstractType
{
return 'file';
}
+
+ private function getFileUploadError($errorCode)
+ {
+ $messageParameters = [];
+
+ if (UPLOAD_ERR_INI_SIZE === $errorCode) {
+ list($limitAsString, $suffix) = $this->factorizeSizes(0, self::getMaxFilesize());
+ $messageTemplate = 'The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.';
+ $messageParameters = [
+ '{{ limit }}' => $limitAsString,
+ '{{ suffix }}' => $suffix,
+ ];
+ } elseif (UPLOAD_ERR_FORM_SIZE === $errorCode) {
+ $messageTemplate = 'The file is too large.';
+ } else {
+ $messageTemplate = 'The file could not be uploaded.';
+ }
+
+ if (null !== $this->translator) {
+ $message = $this->translator->trans($messageTemplate, $messageParameters);
+ } else {
+ $message = strtr($messageTemplate, $messageParameters);
+ }
+
+ return new FormError($message, $messageTemplate, $messageParameters);
+ }
+
+ /**
+ * Returns the maximum size of an uploaded file as configured in php.ini.
+ *
+ * This method should be kept in sync with Symfony\Component\HttpFoundation\File\UploadedFile::getMaxFilesize().
+ *
+ * @return int The maximum size of an uploaded file in bytes
+ */
+ private static function getMaxFilesize()
+ {
+ $iniMax = strtolower(ini_get('upload_max_filesize'));
+
+ if ('' === $iniMax) {
+ return PHP_INT_MAX;
+ }
+
+ $max = ltrim($iniMax, '+');
+ if (0 === strpos($max, '0x')) {
+ $max = \intval($max, 16);
+ } elseif (0 === strpos($max, '0')) {
+ $max = \intval($max, 8);
+ } else {
+ $max = (int) $max;
+ }
+
+ switch (substr($iniMax, -1)) {
+ case 't': $max *= 1024;
+ // no break
+ case 'g': $max *= 1024;
+ // no break
+ case 'm': $max *= 1024;
+ // no break
+ case 'k': $max *= 1024;
+ }
+
+ return $max;
+ }
+
+ /**
+ * Converts the limit to the smallest possible number
+ * (i.e. try "MB", then "kB", then "bytes").
+ *
+ * This method should be kept in sync with Symfony\Component\Validator\Constraints\FileValidator::factorizeSizes().
+ */
+ private function factorizeSizes($size, $limit)
+ {
+ $coef = self::MIB_BYTES;
+ $coefFactor = self::KIB_BYTES;
+
+ $limitAsString = (string) ($limit / $coef);
+
+ // Restrict the limit to 2 decimals (without rounding! we
+ // need the precise value)
+ while (self::moreDecimalsThan($limitAsString, 2)) {
+ $coef /= $coefFactor;
+ $limitAsString = (string) ($limit / $coef);
+ }
+
+ // Convert size to the same measure, but round to 2 decimals
+ $sizeAsString = (string) round($size / $coef, 2);
+
+ // If the size and limit produce the same string output
+ // (due to rounding), reduce the coefficient
+ while ($sizeAsString === $limitAsString) {
+ $coef /= $coefFactor;
+ $limitAsString = (string) ($limit / $coef);
+ $sizeAsString = (string) round($size / $coef, 2);
+ }
+
+ return [$limitAsString, self::$suffixes[$coef]];
+ }
+
+ /**
+ * This method should be kept in sync with Symfony\Component\Validator\Constraints\FileValidator::moreDecimalsThan().
+ */
+ private static function moreDecimalsThan($double, $numberOfDecimals)
+ {
+ return \strlen((string) $double) > \strlen(round($double, $numberOfDecimals));
+ }
}
diff --git a/src/Symfony/Component/Form/Extension/HttpFoundation/HttpFoundationRequestHandler.php b/src/Symfony/Component/Form/Extension/HttpFoundation/HttpFoundationRequestHandler.php
index d560c50d5d..a58ad246ea 100644
--- a/src/Symfony/Component/Form/Extension/HttpFoundation/HttpFoundationRequestHandler.php
+++ b/src/Symfony/Component/Form/Extension/HttpFoundation/HttpFoundationRequestHandler.php
@@ -17,6 +17,7 @@ use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\RequestHandlerInterface;
use Symfony\Component\Form\Util\ServerParams;
use Symfony\Component\HttpFoundation\File\File;
+use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\Request;
/**
@@ -115,4 +116,16 @@ class HttpFoundationRequestHandler implements RequestHandlerInterface
{
return $data instanceof File;
}
+
+ /**
+ * @return int|null
+ */
+ public function getUploadFileError($data)
+ {
+ if (!$data instanceof UploadedFile || $data->isValid()) {
+ return null;
+ }
+
+ return $data->getError();
+ }
}
diff --git a/src/Symfony/Component/Form/NativeRequestHandler.php b/src/Symfony/Component/Form/NativeRequestHandler.php
index 29283c7720..60f8cf79ae 100644
--- a/src/Symfony/Component/Form/NativeRequestHandler.php
+++ b/src/Symfony/Component/Form/NativeRequestHandler.php
@@ -135,6 +135,30 @@ class NativeRequestHandler implements RequestHandlerInterface
return \is_array($data) && isset($data['error']) && \is_int($data['error']);
}
+ /**
+ * @return int|null
+ */
+ public function getUploadFileError($data)
+ {
+ if (!\is_array($data)) {
+ return null;
+ }
+
+ if (!isset($data['error'])) {
+ return null;
+ }
+
+ if (!\is_int($data['error'])) {
+ return null;
+ }
+
+ if (UPLOAD_ERR_OK === $data['error']) {
+ return null;
+ }
+
+ return $data['error'];
+ }
+
/**
* Returns the method used to submit the request to the server.
*
diff --git a/src/Symfony/Component/Form/Tests/AbstractRequestHandlerTest.php b/src/Symfony/Component/Form/Tests/AbstractRequestHandlerTest.php
index 16d4045e6d..b470769344 100644
--- a/src/Symfony/Component/Form/Tests/AbstractRequestHandlerTest.php
+++ b/src/Symfony/Component/Form/Tests/AbstractRequestHandlerTest.php
@@ -360,6 +360,28 @@ abstract class AbstractRequestHandlerTest extends TestCase
$this->assertFalse($this->requestHandler->isFileUpload($this->getInvalidFile()));
}
+ /**
+ * @dataProvider uploadFileErrorCodes
+ */
+ public function testFailedFileUploadIsTurnedIntoFormError($errorCode, $expectedErrorCode)
+ {
+ $this->assertSame($expectedErrorCode, $this->requestHandler->getUploadFileError($this->getFailedUploadedFile($errorCode)));
+ }
+
+ public function uploadFileErrorCodes()
+ {
+ return [
+ 'no error' => [UPLOAD_ERR_OK, null],
+ 'upload_max_filesize ini directive' => [UPLOAD_ERR_INI_SIZE, UPLOAD_ERR_INI_SIZE],
+ 'MAX_FILE_SIZE from form' => [UPLOAD_ERR_FORM_SIZE, UPLOAD_ERR_FORM_SIZE],
+ 'partially uploaded' => [UPLOAD_ERR_PARTIAL, UPLOAD_ERR_PARTIAL],
+ 'no file upload' => [UPLOAD_ERR_NO_FILE, UPLOAD_ERR_NO_FILE],
+ 'missing temporary directory' => [UPLOAD_ERR_NO_TMP_DIR, UPLOAD_ERR_NO_TMP_DIR],
+ 'write failure' => [UPLOAD_ERR_CANT_WRITE, UPLOAD_ERR_CANT_WRITE],
+ 'stopped by extension' => [UPLOAD_ERR_EXTENSION, UPLOAD_ERR_EXTENSION],
+ ];
+ }
+
abstract protected function setRequestData($method, $data, $files = []);
abstract protected function getRequestHandler();
@@ -368,6 +390,8 @@ abstract class AbstractRequestHandlerTest extends TestCase
abstract protected function getInvalidFile();
+ abstract protected function getFailedUploadedFile($errorCode);
+
protected function createForm($name, $method = null, $compound = false)
{
$config = $this->createBuilder($name, $compound);
diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/FileTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/FileTypeTest.php
index 6dde61e870..da018b4a19 100644
--- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/FileTypeTest.php
+++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/FileTypeTest.php
@@ -184,6 +184,128 @@ class FileTypeTest extends BaseTypeTest
];
}
+ /**
+ * @dataProvider uploadFileErrorCodes
+ */
+ public function testFailedFileUploadIsTurnedIntoFormErrorUsingHttpFoundationRequestHandler($errorCode, $expectedErrorMessage)
+ {
+ $form = $this->factory
+ ->createBuilder(static::TESTED_TYPE)
+ ->setRequestHandler(new HttpFoundationRequestHandler())
+ ->getForm();
+ $form->submit(new UploadedFile(__DIR__.'/../../../Fixtures/foo', 'foo', null, null, $errorCode, true));
+
+ if (UPLOAD_ERR_OK === $errorCode) {
+ $this->assertTrue($form->isValid());
+ } else {
+ $this->assertFalse($form->isValid());
+ $this->assertSame($expectedErrorMessage, $form->getErrors()[0]->getMessage());
+ }
+ }
+
+ /**
+ * @dataProvider uploadFileErrorCodes
+ */
+ public function testFailedFileUploadIsTurnedIntoFormErrorUsingNativeRequestHandler($errorCode, $expectedErrorMessage)
+ {
+ $form = $this->factory
+ ->createBuilder(static::TESTED_TYPE)
+ ->setRequestHandler(new NativeRequestHandler())
+ ->getForm();
+ $form->submit([
+ 'name' => 'foo.txt',
+ 'type' => 'text/plain',
+ 'tmp_name' => 'owfdskjasdfsa',
+ 'error' => $errorCode,
+ 'size' => 100,
+ ]);
+
+ if (UPLOAD_ERR_OK === $errorCode) {
+ $this->assertTrue($form->isValid());
+ } else {
+ $this->assertFalse($form->isValid());
+ $this->assertSame($expectedErrorMessage, $form->getErrors()[0]->getMessage());
+ }
+ }
+
+ /**
+ * @dataProvider uploadFileErrorCodes
+ */
+ public function testMultipleSubmittedFailedFileUploadsAreTurnedIntoFormErrorUsingHttpFoundationRequestHandler($errorCode, $expectedErrorMessage)
+ {
+ $form = $this->factory
+ ->createBuilder(static::TESTED_TYPE, null, [
+ 'multiple' => true,
+ ])
+ ->setRequestHandler(new HttpFoundationRequestHandler())
+ ->getForm();
+ $form->submit([
+ new UploadedFile(__DIR__.'/../../../Fixtures/foo', 'foo', null, null, $errorCode, true),
+ new UploadedFile(__DIR__.'/../../../Fixtures/foo', 'bar', null, null, $errorCode, true),
+ ]);
+
+ if (UPLOAD_ERR_OK === $errorCode) {
+ $this->assertTrue($form->isValid());
+ } else {
+ $this->assertFalse($form->isValid());
+ $this->assertCount(2, $form->getErrors());
+ $this->assertSame($expectedErrorMessage, $form->getErrors()[0]->getMessage());
+ $this->assertSame($expectedErrorMessage, $form->getErrors()[1]->getMessage());
+ }
+ }
+
+ /**
+ * @dataProvider uploadFileErrorCodes
+ */
+ public function testMultipleSubmittedFailedFileUploadsAreTurnedIntoFormErrorUsingNativeRequestHandler($errorCode, $expectedErrorMessage)
+ {
+ $form = $this->factory
+ ->createBuilder(static::TESTED_TYPE, null, [
+ 'multiple' => true,
+ ])
+ ->setRequestHandler(new NativeRequestHandler())
+ ->getForm();
+ $form->submit([
+ [
+ 'name' => 'foo.txt',
+ 'type' => 'text/plain',
+ 'tmp_name' => 'owfdskjasdfsa',
+ 'error' => $errorCode,
+ 'size' => 100,
+ ],
+ [
+ 'name' => 'bar.txt',
+ 'type' => 'text/plain',
+ 'tmp_name' => 'owfdskjasdfsa',
+ 'error' => $errorCode,
+ 'size' => 100,
+ ],
+ ]);
+
+ if (UPLOAD_ERR_OK === $errorCode) {
+ $this->assertTrue($form->isValid());
+ } else {
+ $this->assertFalse($form->isValid());
+ $this->assertCount(2, $form->getErrors());
+ $this->assertSame($expectedErrorMessage, $form->getErrors()[0]->getMessage());
+ $this->assertSame($expectedErrorMessage, $form->getErrors()[1]->getMessage());
+ }
+ }
+
+ public function uploadFileErrorCodes()
+ {
+ return [
+ 'no error' => [UPLOAD_ERR_OK, null],
+ 'upload_max_filesize ini directive' => [UPLOAD_ERR_INI_SIZE, 'The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.'],
+ 'MAX_FILE_SIZE from form' => [UPLOAD_ERR_FORM_SIZE, 'The file is too large.'],
+ 'partially uploaded' => [UPLOAD_ERR_PARTIAL, 'The file could not be uploaded.'],
+ 'no file upload' => [UPLOAD_ERR_NO_FILE, 'The file could not be uploaded.'],
+ 'missing temporary directory' => [UPLOAD_ERR_NO_TMP_DIR, 'The file could not be uploaded.'],
+ 'write failure' => [UPLOAD_ERR_CANT_WRITE, 'The file could not be uploaded.'],
+ 'stopped by extension' => [UPLOAD_ERR_EXTENSION, 'The file could not be uploaded.'],
+ ];
+ }
+
private function createUploadedFile(RequestHandlerInterface $requestHandler, $path, $originalName)
{
if ($requestHandler instanceof HttpFoundationRequestHandler) {
diff --git a/src/Symfony/Component/Form/Tests/Extension/HttpFoundation/HttpFoundationRequestHandlerTest.php b/src/Symfony/Component/Form/Tests/Extension/HttpFoundation/HttpFoundationRequestHandlerTest.php
index 2b13451183..0e5389568e 100644
--- a/src/Symfony/Component/Form/Tests/Extension/HttpFoundation/HttpFoundationRequestHandlerTest.php
+++ b/src/Symfony/Component/Form/Tests/Extension/HttpFoundation/HttpFoundationRequestHandlerTest.php
@@ -56,4 +56,9 @@ class HttpFoundationRequestHandlerTest extends AbstractRequestHandlerTest
{
return 'file:///etc/passwd';
}
+
+ protected function getFailedUploadedFile($errorCode)
+ {
+ return new UploadedFile(__DIR__.'/../../Fixtures/foo', 'foo', null, null, $errorCode, true);
+ }
}
diff --git a/src/Symfony/Component/Form/Tests/NativeRequestHandlerTest.php b/src/Symfony/Component/Form/Tests/NativeRequestHandlerTest.php
index 25a4716650..36638a124f 100644
--- a/src/Symfony/Component/Form/Tests/NativeRequestHandlerTest.php
+++ b/src/Symfony/Component/Form/Tests/NativeRequestHandlerTest.php
@@ -275,4 +275,15 @@ class NativeRequestHandlerTest extends AbstractRequestHandlerTest
'size' => '100',
];
}
+
+ protected function getFailedUploadedFile($errorCode)
+ {
+ return [
+ 'name' => 'upload.txt',
+ 'type' => 'text/plain',
+ 'tmp_name' => 'owfdskjasdfsa',
+ 'error' => $errorCode,
+ 'size' => 100,
+ ];
+ }
}
diff --git a/src/Symfony/Component/Translation/DataCollectorTranslator.php b/src/Symfony/Component/Translation/DataCollectorTranslator.php
index 39561ec92e..68200a7f45 100644
--- a/src/Symfony/Component/Translation/DataCollectorTranslator.php
+++ b/src/Symfony/Component/Translation/DataCollectorTranslator.php
@@ -11,6 +11,7 @@
namespace Symfony\Component\Translation;
+use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface;
use Symfony\Component\Translation\Exception\InvalidArgumentException;
use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface;
use Symfony\Contracts\Translation\LocaleAwareInterface;
@@ -19,7 +20,7 @@ use Symfony\Contracts\Translation\TranslatorInterface;
/**
* @author Abdellatif Ait boudad
*/
-class DataCollectorTranslator implements LegacyTranslatorInterface, TranslatorInterface, TranslatorBagInterface
+class DataCollectorTranslator implements LegacyTranslatorInterface, TranslatorInterface, TranslatorBagInterface, WarmableInterface
{
const MESSAGE_DEFINED = 0;
const MESSAGE_MISSING = 1;
@@ -100,6 +101,16 @@ class DataCollectorTranslator implements LegacyTranslatorInterface, TranslatorIn
return $this->translator->getCatalogue($locale);
}
+ /**
+ * {@inheritdoc}
+ */
+ public function warmUp($cacheDir)
+ {
+ if ($this->translator instanceof WarmableInterface) {
+ $this->translator->warmUp($cacheDir);
+ }
+ }
+
/**
* Gets the fallback locales.
*
diff --git a/src/Symfony/Component/Translation/Resources/bin/translation-status.php b/src/Symfony/Component/Translation/Resources/bin/translation-status.php
index acc8b4e227..0d37c3e0aa 100644
--- a/src/Symfony/Component/Translation/Resources/bin/translation-status.php
+++ b/src/Symfony/Component/Translation/Resources/bin/translation-status.php
@@ -159,6 +159,11 @@ function printTitle($title)
function printTable($translations, $verboseOutput)
{
+ if (0 === count($translations)) {
+ echo 'No translations found';
+
+ return;
+ }
$longestLocaleNameLength = max(array_map('strlen', array_keys($translations)));
foreach ($translations as $locale => $translation) {
diff --git a/src/Symfony/Component/Translation/composer.json b/src/Symfony/Component/Translation/composer.json
index 7d5df73025..809625b5ad 100644
--- a/src/Symfony/Component/Translation/composer.json
+++ b/src/Symfony/Component/Translation/composer.json
@@ -24,7 +24,9 @@
"symfony/config": "~3.4|~4.0",
"symfony/console": "~3.4|~4.0",
"symfony/dependency-injection": "~3.4|~4.0",
+ "symfony/http-kernel": "~3.4|~4.0",
"symfony/intl": "~3.4|~4.0",
+ "symfony/var-dumper": "~3.4|~4.0",
"symfony/yaml": "~3.4|~4.0",
"symfony/finder": "~2.8|~3.0|~4.0",
"psr/log": "~1.0"
diff --git a/src/Symfony/Component/Validator/Constraints/Collection.php b/src/Symfony/Component/Validator/Constraints/Collection.php
index 21427722d9..86418690b8 100644
--- a/src/Symfony/Component/Validator/Constraints/Collection.php
+++ b/src/Symfony/Component/Validator/Constraints/Collection.php
@@ -68,7 +68,7 @@ class Collection extends Composite
}
if (!$field instanceof Optional && !$field instanceof Required) {
- $this->fields[$fieldName] = $field = new Required($field);
+ $this->fields[$fieldName] = new Required($field);
}
}
}
diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf
index 7b1799d533..d1601f72df 100644
--- a/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf
+++ b/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf
@@ -334,6 +334,34 @@
Cette valeur doit être un JSON valide.
+
+
+ Cette collection ne doit pas comporter de doublons.
+
+
+
+ Cette valeur doit être strictement positive.
+
+
+
+ Cette valeur doit être supérieure ou égale à zéro.
+
+
+
+ Cette valeur doit être strictement négative.
+
+
+
+ Cette valeur doit être inférieure ou égale à zéro.
+
+
+
+ Cette valeur n'est pas un fuseau horaire valide.
+
+
+
+ Ce mot de passe a été révélé par une faille de sécurité et ne doit plus être utilisé. Veuillez utiliser un autre mot de passe.
+