Skip to content

Commit 6e0ab3a

Browse files
Merge branch '6.0' into 6.1
* 6.0: [Messenger] Remove redundant interface in DoctrineReceiver Fix choice filter error when loading mix of grouped and non-grouped choices [Mime] Allow url as a path in the DataPart::fromPath Fix getting class constraints on debug command
2 parents cdd1093 + cf820c4 commit 6e0ab3a

File tree

7 files changed

+168
-59
lines changed

7 files changed

+168
-59
lines changed

src/Symfony/Component/Form/ChoiceList/Loader/FilterChoiceLoaderDecorator.php

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,17 @@ protected function loadChoices(): iterable
3636
}
3737

3838
foreach ($structuredValues as $group => $values) {
39-
if ($values && $filtered = array_filter($list->getChoicesForValues($values), $this->filter)) {
40-
$choices[$group] = $filtered;
39+
if (is_array($values)) {
40+
if ($values && $filtered = array_filter($list->getChoicesForValues($values), $this->filter)) {
41+
$choices[$group] = $filtered;
42+
}
43+
continue;
44+
// filter empty groups
45+
}
46+
47+
if ($filtered = array_filter($list->getChoicesForValues([$values]), $this->filter)) {
48+
$choices[$group] = $filtered[0];
4149
}
42-
// filter empty groups
4350
}
4451

4552
return $choices ?? [];

src/Symfony/Component/Form/Tests/ChoiceList/Loader/FilterChoiceLoaderDecoratorTest.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,29 @@ public function testLoadChoiceListWithGroupedChoices()
4747
]), $loader->loadChoiceList());
4848
}
4949

50+
public function testLoadChoiceListMixedWithGroupedAndNonGroupedChoices()
51+
{
52+
$filter = function ($choice) {
53+
return 0 === $choice % 2;
54+
};
55+
56+
$choices = array_merge(range(1, 9), ['grouped' => range(10, 40, 5)]);
57+
$loader = new FilterChoiceLoaderDecorator(new ArrayChoiceLoader($choices), $filter);
58+
59+
$this->assertEquals(new ArrayChoiceList([
60+
1 => 2,
61+
3 => 4,
62+
5 => 6,
63+
7 => 8,
64+
'grouped' => [
65+
0 => 10,
66+
2 => 20,
67+
4 => 30,
68+
6 => 40,
69+
],
70+
]), $loader->loadChoiceList());
71+
}
72+
5073
public function testLoadValuesForChoices()
5174
{
5275
$evenValues = [1 => '2', 3 => '4'];

src/Symfony/Component/Messenger/Bridge/Doctrine/Transport/DoctrineReceiver.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,13 @@
2020
use Symfony\Component\Messenger\Stamp\TransportMessageIdStamp;
2121
use Symfony\Component\Messenger\Transport\Receiver\ListableReceiverInterface;
2222
use Symfony\Component\Messenger\Transport\Receiver\MessageCountAwareInterface;
23-
use Symfony\Component\Messenger\Transport\Receiver\ReceiverInterface;
2423
use Symfony\Component\Messenger\Transport\Serialization\PhpSerializer;
2524
use Symfony\Component\Messenger\Transport\Serialization\SerializerInterface;
2625

2726
/**
2827
* @author Vincent Touzet <[email protected]>
2928
*/
30-
class DoctrineReceiver implements ReceiverInterface, MessageCountAwareInterface, ListableReceiverInterface
29+
class DoctrineReceiver implements ListableReceiverInterface, MessageCountAwareInterface
3130
{
3231
private const MAX_RETRIES = 3;
3332
private int $retryingSafetyCounter = 0;

src/Symfony/Component/Mime/Part/DataPart.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,20 @@ public static function fromPath(string $path, string $name = null, string $conte
6161
$contentType = self::$mimeTypes->getMimeTypes($ext)[0] ?? 'application/octet-stream';
6262
}
6363

64-
if (!is_file($path) || !is_readable($path)) {
64+
if ((is_file($path) && !is_readable($path)) || is_dir($path)) {
6565
throw new InvalidArgumentException(sprintf('Path "%s" is not readable.', $path));
6666
}
6767

6868
if (false === $handle = @fopen($path, 'r', false)) {
6969
throw new InvalidArgumentException(sprintf('Unable to open path "%s".', $path));
7070
}
71+
72+
if (!is_file($path)) {
73+
$cache = fopen('php://temp', 'r+');
74+
stream_copy_to_stream($handle, $cache);
75+
$handle = $cache;
76+
}
77+
7178
$p = new self($handle, $name ?: basename($path), $contentType);
7279
$p->handle = $handle;
7380

src/Symfony/Component/Mime/Tests/Part/DataPartTest.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,30 @@ public function testFromPathWithNotAFile()
134134
DataPart::fromPath(__DIR__.'/../Fixtures/mimetypes/');
135135
}
136136

137+
/**
138+
* @group network
139+
*/
140+
public function testFromPathWithUrl()
141+
{
142+
if (!\in_array('https', stream_get_wrappers())) {
143+
$this->markTestSkipped('"https" stream wrapper is not enabled.');
144+
}
145+
146+
$p = DataPart::fromPath($file = 'https://symfony.com/images/common/logo/logo_symfony_header.png');
147+
$content = file_get_contents($file);
148+
$this->assertEquals($content, $p->getBody());
149+
$maxLineLength = 76;
150+
$this->assertEquals(substr(base64_encode($content), 0, $maxLineLength), substr($p->bodyToString(), 0, $maxLineLength));
151+
$this->assertEquals(substr(base64_encode($content), 0, $maxLineLength), substr(implode('', iterator_to_array($p->bodyToIterable())), 0, $maxLineLength));
152+
$this->assertEquals('image', $p->getMediaType());
153+
$this->assertEquals('png', $p->getMediaSubType());
154+
$this->assertEquals(new Headers(
155+
new ParameterizedHeader('Content-Type', 'image/png', ['name' => 'logo_symfony_header.png']),
156+
new UnstructuredHeader('Content-Transfer-Encoding', 'base64'),
157+
new ParameterizedHeader('Content-Disposition', 'attachment', ['name' => 'logo_symfony_header.png', 'filename' => 'logo_symfony_header.png'])
158+
), $p->getPreparedHeaders());
159+
}
160+
137161
public function testHasContentId()
138162
{
139163
$p = new DataPart('content');

src/Symfony/Component/Validator/Command/DebugCommand.php

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,19 @@ private function dumpValidatorsForClass(InputInterface $input, OutputInterface $
8888
$rows = [];
8989
$dump = new Dumper($output);
9090

91-
foreach ($this->getConstrainedPropertiesData($class) as $propertyName => $constraintsData) {
91+
/** @var ClassMetadataInterface $classMetadata */
92+
$classMetadata = $this->validator->getMetadataFor($class);
93+
94+
foreach ($this->getClassConstraintsData($classMetadata) as $data) {
95+
$rows[] = [
96+
'-',
97+
$data['class'],
98+
implode(', ', $data['groups']),
99+
$dump($data['options']),
100+
];
101+
}
102+
103+
foreach ($this->getConstrainedPropertiesData($classMetadata) as $propertyName => $constraintsData) {
92104
foreach ($constraintsData as $data) {
93105
$rows[] = [
94106
$propertyName,
@@ -119,12 +131,20 @@ private function dumpValidatorsForClass(InputInterface $input, OutputInterface $
119131
$table->render();
120132
}
121133

122-
private function getConstrainedPropertiesData(string $class): array
134+
private function getClassConstraintsData(ClassMetadataInterface $classMetadata): iterable
123135
{
124-
$data = [];
136+
foreach ($classMetadata->getConstraints() as $constraint) {
137+
yield [
138+
'class' => \get_class($constraint),
139+
'groups' => $constraint->groups,
140+
'options' => $this->getConstraintOptions($constraint),
141+
];
142+
}
143+
}
125144

126-
/** @var ClassMetadataInterface $classMetadata */
127-
$classMetadata = $this->validator->getMetadataFor($class);
145+
private function getConstrainedPropertiesData(ClassMetadataInterface $classMetadata): array
146+
{
147+
$data = [];
128148

129149
foreach ($classMetadata->getConstrainedProperties() as $constrainedProperty) {
130150
$data[$constrainedProperty] = $this->getPropertyData($classMetadata, $constrainedProperty);

0 commit comments

Comments
 (0)