Skip to content

Commit de4523a

Browse files
Merge branch '5.0'
* 5.0: [travis] fix CI (ter) Revert "[travis][appveyor] don't cache .phpunit" silence E_NOTICE triggered since PHP 7.4 [Form] Removed legacy check in `ValidationListener` [HttpClient] fix HTTP/2 support on non-SSL connections - CurlHttpClient only Force ping after transport Exception do not merge constraints within interfaces [Validator] Fixed default group for nested composite constraints
2 parents d69b8bb + 7e739ee commit de4523a

File tree

18 files changed

+197
-37
lines changed

18 files changed

+197
-37
lines changed

.appveyor.yml

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ clone_folder: c:\projects\symfony
44

55
cache:
66
- composer.phar
7+
- .phpunit -> phpunit
78

89
init:
910
- SET PATH=c:\php;%PATH%

.travis.yml

+6-5
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ matrix:
3636

3737
cache:
3838
directories:
39+
- .phpunit
3940
- php-$MIN_PHP
4041
- ~/php-ext
4142

@@ -304,8 +305,10 @@ install:
304305
if [[ !$deps && $PHP = 7.2 ]]; then
305306
phpenv global $PHP
306307
tfold 'composer update' $COMPOSER_UP
307-
tfold 'phpunit install' ./phpunit install
308-
tfold src/Symfony/Component/HttpClient.h2push "docker run -it --rm -v $(pwd):/app -v /usr/local/bin/vulcain:/usr/local/bin/vulcain -w /app php:7.3-alpine ./phpunit src/Symfony/Component/HttpClient/Tests/CurlHttpClientTest.php --filter testHttp2Push"
308+
[ -d .phpunit ] && mv .phpunit .phpunit.bak
309+
tfold src/Symfony/Component/HttpClient.h2push "docker run -it --rm -v $(pwd):/app -v $(phpenv which composer):/usr/local/bin/composer -v /usr/local/bin/vulcain:/usr/local/bin/vulcain -w /app php:7.3-alpine ./phpunit src/Symfony/Component/HttpClient/Tests/CurlHttpClientTest.php --filter testHttp2Push"
310+
sudo rm .phpunit -rf
311+
[ -d .phpunit.bak ] && mv .phpunit.bak .phpunit
309312
fi
310313
311314
if [[ $PHP != 7.4* && $PHP != $TRAVIS_PHP_VERSION && $TRAVIS_PULL_REQUEST != false ]]; then
@@ -314,12 +317,10 @@ install:
314317
fi
315318
316319
([[ $deps ]] && cd src/Symfony/Component/HttpFoundation; cp composer.json composer.bak; composer config platform.ext-mongodb 1.6.0; composer require --dev --no-update mongodb/mongodb ~1.5.0)
317-
318320
if [[ $deps || $PHP != 7.2 ]]; then
319321
tfold 'composer update' $COMPOSER_UP
320-
tfold 'phpunit install' ./phpunit install
321322
fi
322-
323+
tfold 'phpunit install' ./phpunit install
323324
if [[ $deps = high ]]; then
324325
echo "$COMPONENTS" | parallel --gnu "tfold {} 'cd {} && $COMPOSER_UP && $PHPUNIT_X$LEGACY'" || X=1
325326
(cd src/Symfony/Component/HttpFoundation; mv composer.bak composer.json)

phpunit

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#!/usr/bin/env php
22
<?php
33

4+
// Cache-Id: 2020-04-10 20:30 UTC
5+
46
if (!file_exists(__DIR__.'/vendor/symfony/phpunit-bridge/bin/simple-phpunit')) {
57
echo "Unable to find the `simple-phpunit` script in `vendor/symfony/phpunit-bridge/bin/`.\nPlease run `composer update` before running this command.\n";
68
exit(1);

src/Symfony/Component/Form/Extension/Validator/EventListener/ValidationListener.php

+1-2
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,7 @@ public function validateForm(FormEvent $event)
5050
foreach ($this->validator->validate($form) as $violation) {
5151
// Allow the "invalid" constraint to be put onto
5252
// non-synchronized forms
53-
// ConstraintViolation::getConstraint() must not expect to provide a constraint as long as Symfony\Component\Validator\ExecutionContext exists (before 3.0)
54-
$allowNonSynchronized = (null === $violation->getConstraint() || $violation->getConstraint() instanceof Form) && Form::NOT_SYNCHRONIZED_ERROR === $violation->getCode();
53+
$allowNonSynchronized = $violation->getConstraint() instanceof Form && Form::NOT_SYNCHRONIZED_ERROR === $violation->getCode();
5554

5655
$this->violationMapper->mapViolation($violation, $form, $allowNonSynchronized);
5756
}

src/Symfony/Component/HttpClient/CurlHttpClient.php

+4-4
Original file line numberDiff line numberDiff line change
@@ -141,12 +141,12 @@ public function request(string $method, string $url, array $options = []): Respo
141141
CURLOPT_CERTINFO => $options['capture_peer_cert_chain'],
142142
];
143143

144-
if (1.0 === (float) $options['http_version']) {
144+
if (\defined('CURL_VERSION_HTTP2') && (CURL_VERSION_HTTP2 & self::$curlVersion['features']) && ('https:' === $scheme || 2.0 === (float) $options['http_version'])) {
145+
$curlopts[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_2_0;
146+
} elseif (1.0 === (float) $options['http_version']) {
145147
$curlopts[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_0;
146-
} elseif (1.1 === (float) $options['http_version'] || 'https:' !== $scheme) {
148+
} elseif (1.1 === (float) $options['http_version']) {
147149
$curlopts[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_1;
148-
} elseif (\defined('CURL_VERSION_HTTP2') && CURL_VERSION_HTTP2 & self::$curlVersion['features']) {
149-
$curlopts[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_2_0;
150150
}
151151

152152
if (isset($options['auth_ntlm'])) {

src/Symfony/Component/HttpKernel/Log/Logger.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ public function log($level, $message, array $context = [])
7979
}
8080

8181
$formatter = $this->formatter;
82-
fwrite($this->handle, $formatter($level, $message, $context));
82+
@fwrite($this->handle, $formatter($level, $message, $context));
8383
}
8484

8585
private function format(string $level, string $message, array $context): string

src/Symfony/Component/Mailer/Tests/Transport/Smtp/SmtpTransportTest.php

+44
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\Component\Mailer\Envelope;
16+
use Symfony\Component\Mailer\Exception\TransportException;
1617
use Symfony\Component\Mailer\Transport\Smtp\SmtpTransport;
1718
use Symfony\Component\Mailer\Transport\Smtp\Stream\AbstractStream;
1819
use Symfony\Component\Mailer\Transport\Smtp\Stream\SocketStream;
@@ -43,6 +44,29 @@ public function testSendDoesNotPingBelowThreshold(): void
4344
$this->assertNotContains("NOOP\r\n", $stream->getCommands());
4445
}
4546

47+
public function testSendPingAfterTransportException(): void
48+
{
49+
$stream = new DummyStream();
50+
$envelope = new Envelope(new Address('[email protected]'), [new Address('[email protected]')]);
51+
52+
$transport = new SmtpTransport($stream);
53+
$transport->send(new RawMessage('Message 1'), $envelope);
54+
$stream->close();
55+
$catch = false;
56+
57+
try {
58+
$transport->send(new RawMessage('Message 2'), $envelope);
59+
} catch (TransportException $exception) {
60+
$catch = true;
61+
}
62+
$this->assertTrue($catch);
63+
$this->assertTrue($stream->isClosed());
64+
65+
$transport->send(new RawMessage('Message 3'), $envelope);
66+
67+
$this->assertFalse($stream->isClosed());
68+
}
69+
4670
public function testSendDoesPingAboveThreshold(): void
4771
{
4872
$stream = new DummyStream();
@@ -76,13 +100,23 @@ class DummyStream extends AbstractStream
76100
*/
77101
private $commands;
78102

103+
/**
104+
* @var bool
105+
*/
106+
private $closed = true;
107+
79108
public function initialize(): void
80109
{
110+
$this->closed = false;
81111
$this->nextResponse = '220 localhost';
82112
}
83113

84114
public function write(string $bytes, $debug = true): void
85115
{
116+
if ($this->closed) {
117+
throw new TransportException('Unable to write bytes on the wire.');
118+
}
119+
86120
$this->commands[] = $bytes;
87121

88122
if (0 === strpos($bytes, 'DATA')) {
@@ -120,4 +154,14 @@ protected function getReadConnectionDescription(): string
120154
{
121155
return 'null';
122156
}
157+
158+
public function close(): void
159+
{
160+
$this->closed = true;
161+
}
162+
163+
public function isClosed(): bool
164+
{
165+
return $this->closed;
166+
}
123167
}

src/Symfony/Component/Mailer/Transport/Smtp/SmtpTransport.php

+2-3
Original file line numberDiff line numberDiff line change
@@ -206,12 +206,11 @@ protected function doSend(SentMessage $message): void
206206
$this->stream->flush();
207207
$this->executeCommand("\r\n.\r\n", [250]);
208208
$message->appendDebug($this->stream->getDebug());
209+
$this->lastMessageTime = microtime(true);
209210
} catch (TransportExceptionInterface $e) {
210211
$e->appendDebug($this->stream->getDebug());
211-
212+
$this->lastMessageTime = 0;
212213
throw $e;
213-
} finally {
214-
$this->lastMessageTime = microtime(true);
215214
}
216215
}
217216

src/Symfony/Component/Validator/Constraints/Composite.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,8 @@ public function __construct($options = null)
9090
}
9191
}
9292

93-
$this->groups = array_keys($mergedGroups);
93+
// prevent empty composite constraint to have empty groups
94+
$this->groups = array_keys($mergedGroups) ?: [self::DEFAULT_GROUP];
9495
$this->$compositeOption = $nestedConstraints;
9596

9697
return;

src/Symfony/Component/Validator/Mapping/Factory/LazyLoadingMetadataFactory.php

+10-19
Original file line numberDiff line numberDiff line change
@@ -113,34 +113,25 @@ public function getMetadataFor($value)
113113

114114
private function mergeConstraints(ClassMetadata $metadata)
115115
{
116+
if ($metadata->getReflectionClass()->isInterface()) {
117+
return;
118+
}
119+
116120
// Include constraints from the parent class
117121
if ($parent = $metadata->getReflectionClass()->getParentClass()) {
118122
$metadata->mergeConstraints($this->getMetadataFor($parent->name));
119123
}
120124

121-
$interfaces = $metadata->getReflectionClass()->getInterfaces();
122-
123-
$interfaces = array_filter($interfaces, function (\ReflectionClass $interface) use ($parent, $interfaces) {
124-
$interfaceName = $interface->getName();
125-
126-
if ($parent && $parent->implementsInterface($interfaceName)) {
127-
return false;
128-
}
129-
130-
foreach ($interfaces as $i) {
131-
if ($i !== $interface && $i->implementsInterface($interfaceName)) {
132-
return false;
133-
}
134-
}
135-
136-
return true;
137-
});
138-
139125
// Include constraints from all directly implemented interfaces
140-
foreach ($interfaces as $interface) {
126+
foreach ($metadata->getReflectionClass()->getInterfaces() as $interface) {
141127
if ('Symfony\Component\Validator\GroupSequenceProviderInterface' === $interface->name) {
142128
continue;
143129
}
130+
131+
if ($parent && \in_array($interface->getName(), $parent->getInterfaceNames(), true)) {
132+
continue;
133+
}
134+
144135
$metadata->mergeConstraints($this->getMetadataFor($interface->name));
145136
}
146137
}

src/Symfony/Component/Validator/Tests/Constraints/CollectionTest.php

+12
Original file line numberDiff line numberDiff line change
@@ -100,4 +100,16 @@ public function testAcceptRequiredConstraintAsOneElementArray()
100100

101101
$this->assertEquals($collection1, $collection2);
102102
}
103+
104+
public function testConstraintHasDefaultGroupWithOptionalValues()
105+
{
106+
$constraint = new Collection([
107+
'foo' => new Required(),
108+
'bar' => new Optional(),
109+
]);
110+
111+
$this->assertEquals(['Default'], $constraint->groups);
112+
$this->assertEquals(['Default'], $constraint->fields['foo']->groups);
113+
$this->assertEquals(['Default'], $constraint->fields['bar']->groups);
114+
}
103115
}

src/Symfony/Component/Validator/Tests/Constraints/CollectionValidatorTest.php

+23
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,29 @@ public function testExtraFieldsDisallowed()
143143
->assertRaised();
144144
}
145145

146+
public function testExtraFieldsDisallowedWithOptionalValues()
147+
{
148+
$constraint = new Optional();
149+
150+
$data = $this->prepareTestData([
151+
'baz' => 6,
152+
]);
153+
154+
$this->validator->validate($data, new Collection([
155+
'fields' => [
156+
'foo' => $constraint,
157+
],
158+
'extraFieldsMessage' => 'myMessage',
159+
]));
160+
161+
$this->buildViolation('myMessage')
162+
->setParameter('{{ field }}', '"baz"')
163+
->atPath('property.path[baz]')
164+
->setInvalidValue(6)
165+
->setCode(Collection::NO_SUCH_FIELD_ERROR)
166+
->assertRaised();
167+
}
168+
146169
// bug fix
147170
public function testNullNotConsideredExtraField()
148171
{

src/Symfony/Component/Validator/Tests/Constraints/CompositeTest.php

+25-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
class ConcreteComposite extends Composite
2121
{
22-
public $constraints;
22+
public $constraints = [];
2323

2424
protected function getCompositeOption(): string
2525
{
@@ -37,6 +37,30 @@ public function getDefaultOption(): ?string
3737
*/
3838
class CompositeTest extends TestCase
3939
{
40+
public function testConstraintHasDefaultGroup()
41+
{
42+
$constraint = new ConcreteComposite([
43+
new NotNull(),
44+
new NotBlank(),
45+
]);
46+
47+
$this->assertEquals(['Default'], $constraint->groups);
48+
$this->assertEquals(['Default'], $constraint->constraints[0]->groups);
49+
$this->assertEquals(['Default'], $constraint->constraints[1]->groups);
50+
}
51+
52+
public function testNestedCompositeConstraintHasDefaultGroup()
53+
{
54+
$constraint = new ConcreteComposite([
55+
new ConcreteComposite(),
56+
new ConcreteComposite(),
57+
]);
58+
59+
$this->assertEquals(['Default'], $constraint->groups);
60+
$this->assertEquals(['Default'], $constraint->constraints[0]->groups);
61+
$this->assertEquals(['Default'], $constraint->constraints[1]->groups);
62+
}
63+
4064
public function testMergeNestedGroupsIfNoExplicitParentGroup()
4165
{
4266
$constraint = new ConcreteComposite([
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
namespace Symfony\Component\Validator\Tests\Fixtures;
4+
5+
abstract class AbstractPropertyGetter implements PropertyGetterInterface
6+
{
7+
private $property;
8+
9+
public function getProperty()
10+
{
11+
return $this->property;
12+
}
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
namespace Symfony\Component\Validator\Tests\Fixtures;
4+
5+
interface ChildGetterInterface extends PropertyGetterInterface
6+
{
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
namespace Symfony\Component\Validator\Tests\Fixtures;
4+
5+
/**
6+
* This class has two paths to PropertyGetterInterface:
7+
* PropertyGetterInterface <- AbstractPropertyGetter <- PropertyGetter
8+
* PropertyGetterInterface <- ChildGetterInterface <- PropertyGetter
9+
*/
10+
class PropertyGetter extends AbstractPropertyGetter implements ChildGetterInterface
11+
{
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
3+
namespace Symfony\Component\Validator\Tests\Fixtures;
4+
5+
interface PropertyGetterInterface
6+
{
7+
public function getProperty();
8+
}

0 commit comments

Comments
 (0)