8000 Merge branch '5.0' · symfony/symfony@c6d0a2a · GitHub
[go: up one dir, main page]

Skip to content

Commit c6d0a2a

Browse files
committed
Merge branch '5.0'
* 5.0: Add missing use statements [Translation] Add missing use statement [Translation] Add missing use statement [Config][XmlReferenceDumper] Prevent potential \TypeError [Mailer] Fix broken mandrill http send for recipients with names [Translation] prefer intl domain when adding messages to catalogue Fix CS Fix CS Fail on empty password verification (without warning on any implementation) [Translation][Debug] Add installation and minimal example to README [Validator] try to call __get method if property is uninitialized Show both missing packages in the same error message Fix handling of empty_data's \Closure value in Date/Time form types
2 parents 981a771 + 85f793b commit c6d0a2a

File tree

28 files changed

+297
-25
lines changed

28 files changed

+297
-25
lines changed

src/Symfony/Bridge/Twig/Mime/NotificationEmail.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,17 @@ class NotificationEmail extends TemplatedEmail
4141

4242
public function __construct(Headers $headers = null, AbstractPart $body = null)
4343
{
44+
$missingPackages = [];
4445
if (!class_exists(CssInlinerExtension::class)) {
45-
throw new \LogicException(sprintf('You cannot use "%s" if the CSS Inliner Twig extension is not available; try running "composer require twig/cssinliner-extra".', static::class));
46+
$missingPackages['twig/cssinliner-extra'] = ' CSS Inliner';
4647
}
4748

4849
if (!class_exists(InkyExtension::class)) {
49-
throw new \LogicException(sprintf('You cannot use "%s" if the Inky Twig extension is not available; try running "composer require twig/inky-extra".', static::class));
50+
$missingPackages['twig/inky-extra'] = 'Inky';
51+
}
52+
53+
if ($missingPackages) {
54+
throw new \LogicException(sprintf('You cannot use "%s" if the %s Twig extension%s not available; try running "composer require %s".', static::class, implode(' and ', $missingPackages), \count($missingPackages) > 1 ? 's are' : ' is', implode(' ', array_keys($missingPackages))));
5055
}
5156

5257
parent::__construct($headers, $body);

src/Symfony/Bundle/SecurityBundle/Debug/WrappedListener.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
namespace Symfony\Bundle\SecurityBundle\Debug;
1313

1414
use Symfony\Component\HttpKernel\Event\RequestEvent;
15-
use Symfony\Component\VarDumper\Caster\ClassStub;
1615

1716
/**
1817
* Wraps a security listener for calls record.

src/Symfony/Component/Config/Definition/Dumper/XmlReferenceDumper.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ private function writeNode(NodeInterface $node, int $depth = 0, bool $root = fal
9191
}
9292

9393
if ($prototype instanceof PrototypedArrayNode) {
94-
$prototype->setName($key);
94+
$prototype->setName($key ?? '');
9595
$children = [$key => $prototype];
9696
} elseif ($prototype instanceof ArrayNode) {
9797
$children = $prototype->getChildren();

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

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,17 @@ public function buildForm(FormBuilderInterface $builder, array $options)
109109
'invalid_message_parameters',
110110
]));
111111

112-
if (isset($emptyData['date'])) {
112+
if ($emptyData instanceof \Closure) {
113+
$lazyEmptyData = static function ($option) use ($emptyData) {
114+
return static function (FormInterface $form) use ($emptyData, $option) {
115+
$emptyData = $emptyData($form->getParent());
116+
117+
return isset($emptyData[$option]) ? $emptyData[$option] : '';
118+
};
119+
};
120+
121+
$dateOptions['empty_data'] = $lazyEmptyData('date');
122+
} elseif (isset($emptyData['date'])) {
113123
$dateOptions['empty_data'] = $emptyData['date'];
114124
}
115125

@@ -128,7 +138,9 @@ public function buildForm(FormBuilderInterface $builder, array $options)
128138
'invalid_message_parameters',
129139
]));
130140

131-
if (isset($emptyData['time'])) {
141+
if ($emptyData instanceof \Closure) {
142+
$timeOptions['empty_data'] = $lazyEmptyData('time');
143+
} elseif (isset($emptyData['time'])) {
132144
$timeOptions['empty_data'] = $emptyData['time'];
133145
}
134146

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

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -83,14 +83,28 @@ public function buildForm(FormBuilderInterface $builder, array $options)
8383
// so we need to handle the cascade setting here
8484
$emptyData = $builder->getEmptyData() ?: [];
8585

86-
if (isset($emptyData['year'])) {
87-
$yearOptions['empty_data'] = $emptyData['year'];
88-
}
89-
if (isset($emptyData['month'])) {
90-
$monthOptions['empty_data'] = $emptyData['month'];
91-
}
92-
if (isset($emptyData['day'])) {
93-
$dayOptions['empty_data'] = $emptyData['day'];
86+
if ($emptyData instanceof \Closure) {
87+
$lazyEmptyData = static function ($option) use ($emptyData) {
88+
return static function (FormInterface $form) use ($emptyData, $option) {
89+
$emptyData = $emptyData($form->getParent());
90+
91+
return isset($emptyData[$option]) ? $emptyData[$option] : '';
92+
};
93+
};
94+
95+
$yearOptions['empty_data'] = $lazyEmptyData('year');
96+
$monthOptions['empty_data'] = $lazyEmptyData('month');
97+
$dayOptions['empty_data'] = $lazyEmptyData('day');
98+
} else {
99+
if (isset($emptyData['year'])) {
100+
$yearOptions['empty_data'] = $emptyData['year'];
101+
}
102+
if (isset($emptyData['month'])) {
103+
$monthOptions['empty_data'] = $emptyData['month'];
104+
}
105+
if (isset($emptyData['day'])) {
106+
$dayOptions['empty_data'] = $emptyData['day'];
107+
}
94108
}
95109

96110
if (isset($options['invalid_message'])) {

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

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,17 @@ public function buildForm(FormBuilderInterface $builder, array $options)
9494
// so we need to handle the cascade setting here
9595
$emptyData = $builder->getEmptyData() ?: [];
9696

97-
if (isset($emptyData['hour'])) {
97+
if ($emptyData instanceof \Closure) {
98+
$lazyEmptyData = static function ($option) use ($emptyData) {
99+
return static function (FormInterface $form) use ($emptyData, $option) {
100+
$emptyData = $emptyData($form->getParent());
101+
102+
return isset($emptyData[$option]) ? $emptyData[$option] : '';
103+
};
104+
};
105+
106+
$hourOptions['empty_data'] = $lazyEmptyData('hour');
107+
} elseif (isset($emptyData['hour'])) {
98108
$hourOptions['empty_data'] = $emptyData['hour'];
99109
}
100110

@@ -161,14 +171,18 @@ public function buildForm(FormBuilderInterface $builder, array $options)
161171
$builder->add('hour', self::$widgets[$options['widget']], $hourOptions);
162172

163173
if ($options['with_minutes']) {
164-
if (isset($emptyData['minute'])) {
174+
if ($emptyData instanceof \Closure) {
175+
$minuteOptions['empty_data'] = $lazyEmptyData('minute');
176+
} elseif (isset($emptyData['minute'])) {
165177
$minuteOptions['empty_data'] = $emptyData['minute'];
166178
}
167179
$builder->add('minute', self::$widgets[$options['widget']], $minuteOptions);
168180
}
169181

170182
if ($options['with_seconds']) {
171-
if (isset($emptyData['second'])) {
183+
if ($emptyData instanceof \Closure) {
184+
$secondOptions['empty_data'] = $lazyEmptyData('second');
185+
} elseif (isset($emptyData['second'])) {
172186
$secondOptions['empty_data'] = $emptyData['second'];
173187
}
174188
$builder->add('second', self::$widgets[$options['widget']], $secondOptions);

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\Form\Tests\Extension\Core\Type;
1313

1414
use Symfony\Component\Form\FormError;
15+
use Symfony\Component\Form\FormInterface;
1516

1617
class DateTimeTypeTest extends BaseTypeTest
1718
{
@@ -659,6 +660,9 @@ public function testSubmitNullUsesDateEmptyData($widget, $emptyData, $expectedDa
659660
]);
660661
$form->submit(null);
661662

663+
if ($emptyData instanceof \Closure) {
664+
$emptyData = $emptyData($form);
665+
}
662666
$this->assertSame($emptyData, $form->getViewData());
663667
$this->assertEquals($expectedData, $form->getNormData());
664668
$this->assertEquals($expectedData, $form->getData());
@@ -667,11 +671,17 @@ public function testSubmitNullUsesDateEmptyData($widget, $emptyData, $expectedDa
667671
public function provideEmptyData()
668672
{
669673
$expectedData = \DateTime::createFromFormat('Y-m-d H:i', '2018-11-11 21:23');
674+
$lazyEmptyData = static function (FormInterface $form) {
675+
return $form->getConfig()->getCompound() ? ['date' => ['year' => '2018', 'month' => '11', 'day' => '11'], 'time' => ['hour' => '21', 'minute' => '23']] : '2018-11-11T21:23:00';
676+
};
670677

671678
return [
672679
'Simple field' => ['single_text', '2018-11-11T21:23:00', $expectedData],
673680
'Compound text field' => ['text', ['date' => ['year' => '2018', 'month' => '11', 'day' => '11'], 'time' => ['hour' => '21', 'minute' => '23']], $expectedData],
674681
'Compound choice field' => ['choice', ['date' => ['year' => '2018', 'month' => '11', 'day' => '11'], 'time' => ['hour' => '21', 'minute' => '23']], $expectedData],
682+
'Simple field lazy' => ['single_text', $lazyEmptyData, $expectedData],
683+
'Compound text field lazy' => ['text', $lazyEmptyData, $expectedData],
684+
'Compound choice field lazy' => ['choice', $lazyEmptyData, $expectedData],
675685
];
676686
}
677687

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Symfony\Component\Form\ChoiceList\View\ChoiceView;
1515
use Symfony\Component\Form\FormError;
16+
use Symfony\Component\Form\FormInterface;
1617
use Symfony\Component\Intl\Util\IntlTestHelper;
1718

1819
class DateTypeTest extends BaseTypeTest
@@ -1022,6 +1023,9 @@ public function testSubmitNullUsesDateEmptyData($widget, $emptyData, $expectedDa
10221023
]);
10231024
$form->submit(null);
10241025

1026+
if ($emptyData instanceof \Closure) {
1027+
$emptyData = $emptyData($form);
1028+
}
10251029
$this->assertSame($emptyData, $form->getViewData());
10261030
$this->assertEquals($expectedData, $form->getNormData());
10271031
$this->assertEquals($expectedData, $form->getData());
@@ -1030,11 +1034,17 @@ public function testSubmitNullUsesDateEmptyData($widget, $emptyData, $expectedDa
10301034
public function provideEmptyData()
10311035
{
10321036
$expectedData = \DateTime::createFromFormat('Y-m-d H:i:s', '2018-11-11 00:00:00');
1037+
$lazyEmptyData = static function (FormInterface $form) {
1038+
return $form->getConfig()->getCompound() ? ['year' => '2018', 'month' => '11', 'day' => '11'] : '2018-11-11';
1039+
};
10331040

10341041
return [
10351042
'Simple field' => ['single_text', '2018-11-11', $expectedData],
10361043
'Compound text fields' => ['text', ['year' => '2018', 'month' => '11', 'day' => '11'], $expectedData],
10371044
'Compound choice fields' => ['choice', ['year' => '2018', 'month' => '11', 'day' => '11'], $expectedData],
1045+
'Simple field lazy' => ['single_text', $lazyEmptyData, $expectedData],
1046+
'Compound text fields lazy' => ['text', $lazyEmptyData, $expectedData],
1047+
'Compound choice fields lazy' => ['choice', $lazyEmptyData, $expectedData],
10381048
];
10391049
}
10401050

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Symfony\Component\Form\ChoiceList\View\ChoiceView;
1515
use Symfony\Component\Form\FormError;
16+
use Symfony\Component\Form\FormInterface;
1617

1718
class TimeTypeTest extends BaseTypeTest
1819
{
@@ -937,6 +938,9 @@ public function testSubmitNullUsesDateEmptyData($widget, $emptyData, $expectedDa
937938
]);
938939
$form->submit(null);
939940

941+
if ($emptyData instanceof \Closure) {
942+
$emptyData = $emptyData($form);
943+
}
940944
$this->assertSame($emptyData, $form->getViewData());
941945
$this->assertEquals($expectedData, $form->getNormData());
942946
$this->assertEquals($expectedData, $form->getData());
@@ -945,11 +949,17 @@ public function testSubmitNullUsesDateEmptyData($widget, $emptyData, $expectedDa
945949
public function provideEmptyData()
946950
{
947951
$expectedData = \DateTime::createFromFormat('Y-m-d H:i', '1970-01-01 21:23');
952+
$lazyEmptyData = static function (FormInterface $form) {
953+
return $form->getConfig()->getCompound() ? ['hour' => '21', 'minute' => '23'] : '21:23';
954+
};
948955

949956
return [
950957
'Simple field' => ['single_text', '21:23', $expectedData],
951958
'Compound text field' => ['text', ['hour' => '21', 'minute' => '23'], $expectedData],
952959
'Compound choice field' => ['choice', ['hour' => '21', 'minute' => '23'], $expectedData],
960+
'Simple field lazy' => ['single_text', $lazyEmptyData, $expectedData],
961+
'Compound text field lazy' => ['text', $lazyEmptyData, $expectedData],
962+
'Compound choice field lazy' => ['choice', $lazyEmptyData, $expectedData],
953963
];
954964
}
955965
}

src/Symfony/Component/HttpFoundation/Session/Storage/Handler/SessionHandlerFactory.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public static function createHandler($connection): AbstractSessionHandler
5454
case 0 === strpos($connection, 'rediss:'):
5555
case 0 === strpos($connection, 'memcached:'):
5656
if (!class_exists(AbstractAdapter::class)) {
57-
throw new InvalidArgumentException(sprintf('Unsupported DSN "%s". Try running "composer require symfony/cache".', $connection));
57+
throw new \InvalidArgumentException(sprintf('Unsupported DSN "%s". Try running "composer require symfony/cache".', $connection));
5858
}
5959
$handlerClass = 0 === strpos($connection, 'memcached:') ? MemcachedSessionHandler::class : RedisSessionHandler::class;
6060
$connection = AbstractAdapter::createConnection($connection, ['lazy' => true]);
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
10000 * file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Mailer\Bridge\Mailchimp\Http;
13+
14+
use Psr\Log\LoggerInterface;
15+
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
16+
use Symfony\Component\Mailer\Exception\TransportException;
17+
use Symfony\Component\Mailer\SentMessage;
18+
use Symfony\Component\Mailer\SmtpEnvelope;
19+
use Symfony\Component\Mailer\Transport\Http\AbstractHttpTransport;
20+
use Symfony\Component\Mime\Address;
21+
use Symfony\Contracts\HttpClient\HttpClientInterface;
22+
23+
/**
24+
* @author Kevin Verschaeve
25+
*
26+
* @experimental in 4.3
27+
*/
28+
class MandrillTransport extends AbstractHttpTransport
29+
{
30+
private const ENDPOINT = 'https://mandrillapp.com/api/1.0/messages/send-raw.json';
31+
private $key;
32+
33+
public function __construct(string $key, HttpClientInterface $client = null, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null)
34+
{
35+
$this->key = $key;
36+
37+
parent::__construct($client, $dispatcher, $logger);
38+
}
39+
40+
protected function doSend(SentMessage $message): void
41+
{
42+
$envelope = $message->getEnvelope();
43+
$response = $this->client->request('POST', self::ENDPOINT, [
44+
'json' => [
45+
'key' => $this->key,
46+
'to' => $this->getRecipients($envelope),
47+
'from_email' => $envelope->getSender()->getAddress(),
48+
'raw_message' => $message->toString(),
49+
],
50+
]);
51+
52+
if (200 !== $response->getStatusCode()) {
53+
$result = $response->toArray(false);
54+
if ('error' === ($result['status'] ?? false)) {
55+
throw new TransportException(sprintf('Unable to send an email: %s (code %s).', $result['message'], $result['code']));
56+
}
57+
58+
throw new TransportException(sprintf('Unable to send an email (code %s).', $result['code']));
59+
}
60+
}
61+
62+
/**
63+
* @return string[]
64+
*/
65+
private function getRecipients(SmtpEnvelope $envelope): array
66+
{
67+
return array_map(function (Address $recipient): string {
68+
return $recipient->getAddress();
69+
}, $envelope->getRecipients());
70+
}
71+
}

src/Symfony/Component/Mailer/Bridge/Mailchimp/Transport/MandrillHttpTransport.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@
1212
namespace Symfony\Component\Mailer\Bridge\Mailchimp\Transport;
1313

1414
use Psr\Log\LoggerInterface;
15+
use Symfony\Component\Mailer\Envelope;
1516
use Symfony\Component\Mailer\Exception\HttpTransportException;
1617
use Symfony\Component\Mailer\SentMessage;
1718
use Symfony\Component\Mailer\Transport\AbstractHttpTransport;
19+
use Symfony\Component\Mime\Address;
1820
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
1921
use Symfony\Contracts\HttpClient\HttpClientInterface;
2022
use Symfony\Contracts\HttpClient\ResponseInterface;
@@ -47,7 +49,7 @@ protected function doSendHttp(SentMessage $message): ResponseInterface
4749
$response = $this->client->request('POST', 'https://'.$this->getEndpoint().'/api/1.0/messages/send-raw.json', [
4850
'json' => [
4951
'key' => $this->key,
50-
'to' => $this->stringifyAddresses($envelope->getRecipients()),
52+
'to' => $this->getRecipients($envelope->getRecipients()),
5153
'from_email' => $envelope->getSender()->toString(),
5254
'raw_message' => $message->toString(),
5355
],
@@ -71,4 +73,14 @@ private function getEndpoint(): ?string
7173
{
7274
return ($this->host ?: self::HOST).($this->port ? ':'.$this->port : '');
7375
}
76+
77+
/**
78+
* @return string[]
79+
*/
80+
private function getRecipients(Envelope $envelope): array
81+
{
82+
return array_map(function (Address $recipient): string {
83+
return $recipient->getAddress();
84+
}, $envelope->getRecipients());
85+
}
7486
}

src/Symfony/Component/Mime/Test/Constraint/EmailAttachmentCount.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\Mime\Test\Constraint;
1313

1414
use PHPUnit\Framework\Constraint\Constraint;
15+
use Symfony\Component\Mime\Message;
1516
use Symfony\Component\Mime\RawMessage;
1617

1718
final class EmailAttachmentCount extends Constraint

src/Symfony/Component/Mime/Test/Constraint/EmailHtmlBodyContains.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
namespace Symfony\Component\Mime\Test\Constraint;
1313

1414
use PHPUnit\Framework\Constraint\Constraint;
15+
use Symfony\Component\Mime\Message;
16+
use Symfony\Component\Mime\RawMessage;
1517

1618
final class EmailHtmlBodyContains extends Constraint
1719
{

src/Symfony/Component/Mime/Test/Constraint/EmailTextBodyContains.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
namespace Symfony\Component\Mime\Test\Constraint;
1313

1414
use PHPUnit\Framework\Constraint\Constraint;
15+
use Symfony\Component\Mime\Message;
16+
use Symfony\Component\Mime\RawMessage;
1517

1618
final class EmailTextBodyContains extends Constraint
1719
{

0 commit comments

Comments
 (0)
0