diff --git a/.travis.yml b/.travis.yml
index 73eec7a9eb..24155a5c0c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -151,6 +151,7 @@ before_install:
INI=~/.phpenv/versions/$PHP/etc/conf.d/travis.ini
echo date.timezone = Europe/Paris >> $INI
echo memory_limit = -1 >> $INI
+ echo default_socket_timeout = 10 >> $INI
echo session.gc_probability = 0 >> $INI
echo opcache.enable_cli = 1 >> $INI
echo apc.enable_cli = 1 >> $INI
diff --git a/src/Symfony/Bridge/Monolog/Command/ServerLogCommand.php b/src/Symfony/Bridge/Monolog/Command/ServerLogCommand.php
index eb1a4dc257..f04db50c8c 100644
--- a/src/Symfony/Bridge/Monolog/Command/ServerLogCommand.php
+++ b/src/Symfony/Bridge/Monolog/Command/ServerLogCommand.php
@@ -102,7 +102,7 @@ EOF
}
if (!$socket = stream_socket_server($host, $errno, $errstr)) {
- throw new RuntimeException(sprintf('Server start failed on "%s": '.$errstr.' '.$errno, $host));
+ throw new RuntimeException(sprintf('Server start failed on "%s": ', $host).$errstr.' '.$errno);
}
foreach ($this->getLogs($socket) as $clientId => $message) {
diff --git a/src/Symfony/Bridge/Twig/Mime/BodyRenderer.php b/src/Symfony/Bridge/Twig/Mime/BodyRenderer.php
index 14535f232a..510cfcdd5b 100644
--- a/src/Symfony/Bridge/Twig/Mime/BodyRenderer.php
+++ b/src/Symfony/Bridge/Twig/Mime/BodyRenderer.php
@@ -74,6 +74,6 @@ final class BodyRenderer implements BodyRendererInterface
return $this->converter->convert($html);
}
- return strip_tags($html);
+ return strip_tags(preg_replace('{<(head|style)\b.*?\1>}i', '', $html));
}
}
diff --git a/src/Symfony/Bridge/Twig/Tests/Mime/BodyRendererTest.php b/src/Symfony/Bridge/Twig/Tests/Mime/BodyRendererTest.php
index 6eeade3a73..175a8e1978 100644
--- a/src/Symfony/Bridge/Twig/Tests/Mime/BodyRendererTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/Mime/BodyRendererTest.php
@@ -29,11 +29,12 @@ class BodyRendererTest extends TestCase
public function testRenderHtmlOnly(): void
{
- $email = $this->prepareEmail(null, 'HTML');
+ $html = '
headHTML';
+ $email = $this->prepareEmail(null, $html);
$body = $email->getBody();
$this->assertInstanceOf(AlternativePart::class, $body);
$this->assertEquals('HTML', $body->getParts()[0]->bodyToString());
- $this->assertEquals('HTML', $body->getParts()[1]->bodyToString());
+ $this->assertEquals(str_replace('=', '=3D', $html), $body->getParts()[1]->bodyToString());
}
public function testRenderHtmlOnlyWithTextSet(): void
diff --git a/src/Symfony/Component/Asset/VersionStrategy/JsonManifestVersionStrategy.php b/src/Symfony/Component/Asset/VersionStrategy/JsonManifestVersionStrategy.php
index e48f6f2241..c4de580d0b 100644
--- a/src/Symfony/Component/Asset/VersionStrategy/JsonManifestVersionStrategy.php
+++ b/src/Symfony/Component/Asset/VersionStrategy/JsonManifestVersionStrategy.php
@@ -59,7 +59,7 @@ class JsonManifestVersionStrategy implements VersionStrategyInterface
$this->manifestData = json_decode(file_get_contents($this->manifestPath), true);
if (0 < json_last_error()) {
- throw new \RuntimeException(sprintf('Error parsing JSON from asset manifest file "%s": '.json_last_error_msg(), $this->manifestPath));
+ throw new \RuntimeException(sprintf('Error parsing JSON from asset manifest file "%s": ', $this->manifestPath).json_last_error_msg());
}
}
diff --git a/src/Symfony/Component/Console/Helper/ProcessHelper.php b/src/Symfony/Component/Console/Helper/ProcessHelper.php
index 0198968157..f82c16bae8 100644
--- a/src/Symfony/Component/Console/Helper/ProcessHelper.php
+++ b/src/Symfony/Component/Console/Helper/ProcessHelper.php
@@ -36,6 +36,10 @@ class ProcessHelper extends Helper
*/
public function run(OutputInterface $output, $cmd, string $error = null, callable $callback = null, int $verbosity = OutputInterface::VERBOSITY_VERY_VERBOSE): Process
{
+ if (!class_exists(Process::class)) {
+ throw new \LogicException('The ProcessHelper cannot be run as the Process component is not installed. Try running "compose require symfony/process".');
+ }
+
if ($output instanceof ConsoleOutputInterface) {
$output = $output->getErrorOutput();
}
diff --git a/src/Symfony/Component/Console/Helper/QuestionHelper.php b/src/Symfony/Component/Console/Helper/QuestionHelper.php
index a4bd54a97e..7dad156206 100644
--- a/src/Symfony/Component/Console/Helper/QuestionHelper.php
+++ b/src/Symfony/Component/Console/Helper/QuestionHelper.php
@@ -35,7 +35,7 @@ class QuestionHelper extends Helper
{
private $inputStream;
private static $shell;
- private static $stty;
+ private static $stty = true;
/**
* Asks a question to the user.
@@ -109,7 +109,7 @@ class QuestionHelper extends Helper
$inputStream = $this->inputStream ?: STDIN;
$autocomplete = $question->getAutocompleterCallback();
- if (null === $autocomplete || !Terminal::hasSttyAvailable()) {
+ if (null === $autocomplete || !self::$stty || !Terminal::hasSttyAvailable()) {
$ret = false;
if ($question->isHidden()) {
try {
@@ -416,7 +416,7 @@ class QuestionHelper extends Helper
return $value;
}
- if (Terminal::hasSttyAvailable()) {
+ if (self::$stty && Terminal::hasSttyAvailable()) {
$sttyMode = shell_exec('stty -g');
shell_exec('stty -echo');
diff --git a/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php b/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php
index 8164f743bc..9afad24357 100644
--- a/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php
+++ b/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php
@@ -11,6 +11,7 @@
namespace Symfony\Component\Console\Tests\Helper;
+use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Formatter\OutputFormatter;
use Symfony\Component\Console\Helper\FormatterHelper;
use Symfony\Component\Console\Helper\HelperSet;
@@ -783,6 +784,35 @@ class QuestionHelperTest extends AbstractQuestionHelperTest
$this->assertEquals('FooBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
}
+ public function testDisableSttby()
+ {
+ if (!Terminal::hasSttyAvailable()) {
+ $this->markTestSkipped('`stty` is required to test autocomplete functionality');
+ }
+
+ $this->expectException(InvalidArgumentException::class);
+ $this->expectExceptionMessage('invalid');
+
+ QuestionHelper::disableStty();
+ $dialog = new QuestionHelper();
+ $dialog->setHelperSet(new HelperSet([new FormatterHelper()]));
+
+ $question = new ChoiceQuestion('Please select a bundle', [1 => 'AcmeDemoBundle', 4 => 'AsseticBundle']);
+ $question->setMaxAttempts(1);
+
+ //
+ // Gives `AcmeDemoBundle` with stty
+ $inputStream = $this->getInputStream("\033[A\033[A\n\033[B\033[B\n");
+
+ try {
+ $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question);
+ } finally {
+ $reflection = new \ReflectionProperty(QuestionHelper::class, 'stty');
+ $reflection->setAccessible(true);
+ $reflection->setValue(null, true);
+ }
+ }
+
public function testTraversableMultiselectAutocomplete()
{
//
diff --git a/src/Symfony/Component/DependencyInjection/EnvVarProcessor.php b/src/Symfony/Component/DependencyInjection/EnvVarProcessor.php
index eae626f0e6..b16bad18df 100644
--- a/src/Symfony/Component/DependencyInjection/EnvVarProcessor.php
+++ b/src/Symfony/Component/DependencyInjection/EnvVarProcessor.php
@@ -227,7 +227,7 @@ class EnvVarProcessor implements EnvVarProcessorInterface
$env = json_decode($env, true);
if (JSON_ERROR_NONE !== json_last_error()) {
- throw new RuntimeException(sprintf('Invalid JSON in env var "%s": '.json_last_error_msg(), $name));
+ throw new RuntimeException(sprintf('Invalid JSON in env var "%s": ', $name).json_last_error_msg());
}
if (null !== $env && !\is_array($env)) {
diff --git a/src/Symfony/Component/ErrorHandler/Error/FatalError.php b/src/Symfony/Component/ErrorHandler/Error/FatalError.php
index 68172d876c..98490b5acc 100644
--- a/src/Symfony/Component/ErrorHandler/Error/FatalError.php
+++ b/src/Symfony/Component/ErrorHandler/Error/FatalError.php
@@ -72,9 +72,11 @@ class FatalError extends \Error
'line' => $error['line'],
'trace' => $trace,
] as $property => $value) {
- $refl = new \ReflectionProperty(\Error::class, $property);
- $refl->setAccessible(true);
- $refl->setValue($this, $value);
+ if (null !== $value) {
+ $refl = new \ReflectionProperty(\Error::class, $property);
+ $refl->setAccessible(true);
+ $refl->setValue($this, $value);
+ }
}
}
diff --git a/src/Symfony/Component/Filesystem/Filesystem.php b/src/Symfony/Component/Filesystem/Filesystem.php
index a5539fa5eb..b6df1bd967 100644
--- a/src/Symfony/Component/Filesystem/Filesystem.php
+++ b/src/Symfony/Component/Filesystem/Filesystem.php
@@ -97,7 +97,7 @@ class Filesystem
if (!is_dir($dir)) {
// The directory was not created by a concurrent process. Let's throw an exception with a developer friendly error message if we have one
if (self::$lastError) {
- throw new IOException(sprintf('Failed to create "%s": '.self::$lastError, $dir), 0, null, $dir);
+ throw new IOException(sprintf('Failed to create "%s": ', $dir).self::$lastError, 0, null, $dir);
}
throw new IOException(sprintf('Failed to create "%s".', $dir), 0, null, $dir);
}
@@ -167,16 +167,16 @@ class Filesystem
if (is_link($file)) {
// See https://bugs.php.net/52176
if (!(self::box('unlink', $file) || '\\' !== \DIRECTORY_SEPARATOR || self::box('rmdir', $file)) && file_exists($file)) {
- throw new IOException(sprintf('Failed to remove symlink "%s": '.self::$lastError, $file));
+ throw new IOException(sprintf('Failed to remove symlink "%s": ', $file).self::$lastError);
}
} elseif (is_dir($file)) {
$this->remove(new \FilesystemIterator($file, \FilesystemIterator::CURRENT_AS_PATHNAME | \FilesystemIterator::SKIP_DOTS));
if (!self::box('rmdir', $file) && file_exists($file)) {
- throw new IOException(sprintf('Failed to remove directory "%s": '.self::$lastError, $file));
+ throw new IOException(sprintf('Failed to remove directory "%s": ', $file).self::$lastError);
}
} elseif (!self::box('unlink', $file) && file_exists($file)) {
- throw new IOException(sprintf('Failed to remove file "%s": '.self::$lastError, $file));
+ throw new IOException(sprintf('Failed to remove file "%s": ', $file).self::$lastError);
}
}
}
diff --git a/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php b/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php
index 9454adb068..bd7f553cde 100644
--- a/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php
+++ b/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php
@@ -63,12 +63,16 @@ class FormValidator extends ConstraintValidator
/** @var Constraint[] $constraints */
$constraints = $config->getOption('constraints', []);
+ $hasChildren = $form->count() > 0;
+
+ if ($hasChildren && $form->isRoot()) {
+ $this->resolvedGroups = new \SplObjectStorage();
+ }
+
if ($groups instanceof GroupSequence) {
// Validate the data, the form AND nested fields in sequence
$violationsCount = $this->context->getViolations()->count();
$fieldPropertyPath = \is_object($data) ? 'children[%s]' : 'children%s';
- $hasChildren = $form->count() > 0;
- $this->resolvedGroups = $hasChildren ? new \SplObjectStorage() : null;
foreach ($groups->groups as $group) {
if ($validateDataGraph) {
@@ -86,7 +90,8 @@ class FormValidator extends ConstraintValidator
// sequence recursively, thus some fields could fail
// in different steps without breaking early enough
$this->resolvedGroups[$field] = (array) $group;
- $validator->atPath(sprintf($fieldPropertyPath, $field->getPropertyPath()))->validate($field, $formConstraint);
+ $fieldFormConstraint = new Form();
+ $validator->atPath(sprintf($fieldPropertyPath, $field->getPropertyPath()))->validate($field, $fieldFormConstraint);
}
}
@@ -94,12 +99,9 @@ class FormValidator extends ConstraintValidator
break;
}
}
-
- if ($hasChildren) {
- // destroy storage at the end of the sequence to avoid memory leaks
- $this->resolvedGroups = null;
- }
} else {
+ $fieldPropertyPath = \is_object($data) ? 'children[%s]' : 'children%s';
+
if ($validateDataGraph) {
$validator->atPath('data')->validate($data, null, $groups);
}
@@ -131,6 +133,19 @@ class FormValidator extends ConstraintValidator
foreach ($groupedConstraints as $group => $constraint) {
$validator->atPath('data')->validate($data, $constraint, $group);
}
+
+ foreach ($form->all() as $field) {
+ if ($field->isSubmitted()) {
+ $this->resolvedGroups[$field] = $groups;
+ $fieldFormConstraint = new Form();
+ $validator->atPath(sprintf($fieldPropertyPath, $field->getPropertyPath()))->validate($field, $fieldFormConstraint);
+ }
+ }
+ }
+
+ if ($hasChildren && $form->isRoot()) {
+ // destroy storage to avoid memory leaks
+ $this->resolvedGroups = new \SplObjectStorage();
}
} elseif (!$form->isSynchronized()) {
$childrenSynchronized = true;
diff --git a/src/Symfony/Component/Form/Extension/Validator/ValidatorExtension.php b/src/Symfony/Component/Form/Extension/Validator/ValidatorExtension.php
index a5e38859c0..ac2d61238f 100644
--- a/src/Symfony/Component/Form/Extension/Validator/ValidatorExtension.php
+++ b/src/Symfony/Component/Form/Extension/Validator/ValidatorExtension.php
@@ -13,7 +13,7 @@ namespace Symfony\Component\Form\Extension\Validator;
use Symfony\Component\Form\AbstractExtension;
use Symfony\Component\Form\Extension\Validator\Constraints\Form;
-use Symfony\Component\Validator\Constraints\Valid;
+use Symfony\Component\Validator\Constraints\Traverse;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Validator\ValidatorInterface;
@@ -37,7 +37,7 @@ class ValidatorExtension extends AbstractExtension
/* @var $metadata ClassMetadata */
$metadata->addConstraint(new Form());
- $metadata->addPropertyConstraint('children', new Valid());
+ $metadata->addConstraint(new Traverse(false));
$this->validator = $validator;
}
diff --git a/src/Symfony/Component/Form/Form.php b/src/Symfony/Component/Form/Form.php
index a14b0ce05c..e22415c95e 100644
--- a/src/Symfony/Component/Form/Form.php
+++ b/src/Symfony/Component/Form/Form.php
@@ -1063,7 +1063,7 @@ class Form implements \IteratorAggregate, FormInterface, ClearableErrorsInterfac
$value = $transformer->transform($value);
}
} catch (TransformationFailedException $exception) {
- throw new TransformationFailedException(sprintf('Unable to transform data for property path "%s": '.$exception->getMessage(), $this->getPropertyPath()), $exception->getCode(), $exception, $exception->getInvalidMessage(), $exception->getInvalidMessageParameters());
+ throw new TransformationFailedException(sprintf('Unable to transform data for property path "%s": ', $this->getPropertyPath()).$exception->getMessage(), $exception->getCode(), $exception, $exception->getInvalidMessage(), $exception->getInvalidMessageParameters());
}
return $value;
@@ -1085,7 +1085,7 @@ class Form implements \IteratorAggregate, FormInterface, ClearableErrorsInterfac
$value = $transformers[$i]->reverseTransform($value);
}
} catch (TransformationFailedException $exception) {
- throw new TransformationFailedException(sprintf('Unable to reverse value for property path "%s": '.$exception->getMessage(), $this->getPropertyPath()), $exception->getCode(), $exception, $exception->getInvalidMessage(), $exception->getInvalidMessageParameters());
+ throw new TransformationFailedException(sprintf('Unable to reverse value for property path "%s": ', $this->getPropertyPath()).$exception->getMessage(), $exception->getCode(), $exception, $exception->getInvalidMessage(), $exception->getInvalidMessageParameters());
}
return $value;
@@ -1114,7 +1114,7 @@ class Form implements \IteratorAggregate, FormInterface, ClearableErrorsInterfac
$value = $transformer->transform($value);
}
} catch (TransformationFailedException $exception) {
- throw new TransformationFailedException(sprintf('Unable to transform value for property path "%s": '.$exception->getMessage(), $this->getPropertyPath()), $exception->getCode(), $exception, $exception->getInvalidMessage(), $exception->getInvalidMessageParameters());
+ throw new TransformationFailedException(sprintf('Unable to transform value for property path "%s": ', $this->getPropertyPath()).$exception->getMessage(), $exception->getCode(), $exception, $exception->getInvalidMessage(), $exception->getInvalidMessageParameters());
}
return $value;
@@ -1138,7 +1138,7 @@ class Form implements \IteratorAggregate, FormInterface, ClearableErrorsInterfac
$value = $transformers[$i]->reverseTransform($value);
}
} catch (TransformationFailedException $exception) {
- throw new TransformationFailedException(sprintf('Unable to reverse value for property path "%s": '.$exception->getMessage(), $this->getPropertyPath()), $exception->getCode(), $exception, $exception->getInvalidMessage(), $exception->getInvalidMessageParameters());
+ throw new TransformationFailedException(sprintf('Unable to reverse value for property path "%s": ', $this->getPropertyPath()).$exception->getMessage(), $exception->getCode(), $exception, $exception->getInvalidMessage(), $exception->getInvalidMessageParameters());
}
return $value;
diff --git a/src/Symfony/Component/Form/Resources/config/validation.xml b/src/Symfony/Component/Form/Resources/config/validation.xml
index b2b935442d..918f101f42 100644
--- a/src/Symfony/Component/Form/Resources/config/validation.xml
+++ b/src/Symfony/Component/Form/Resources/config/validation.xml
@@ -6,8 +6,8 @@
-
-
-
+
+
+
diff --git a/src/Symfony/Component/Form/Resources/translations/validators.cs.xlf b/src/Symfony/Component/Form/Resources/translations/validators.cs.xlf
index 776da49481..44d597db98 100644
--- a/src/Symfony/Component/Form/Resources/translations/validators.cs.xlf
+++ b/src/Symfony/Component/Form/Resources/translations/validators.cs.xlf
@@ -14,6 +14,10 @@
CSRF token je neplatný. Zkuste prosím znovu odeslat formulář.
+
+
+ Tato hodnota není platná HTML5 barva.
+