Skip to content

Commit d63e0fe

Browse files
committed
Merge branch '4.4' into 5.4
* 4.4: Remove extra space in NotificationEmail Fix the usage of the Valid constraints in array-based forms [DI] fix `ServiceSubscriberTrait` bug where parent has `__call()` [HttpClient] Fix reading proxy settings from dotenv when curl is used [Process] Don't return executable directories in PhpExecutableFinder Center icons vertically in trace list
2 parents fc4700f + f1f123b commit d63e0fe

File tree

10 files changed

+129
-15
lines changed

10 files changed

+129
-15
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public function __construct(Headers $headers = null, AbstractPart $body = null)
4444
{
4545
$missingPackages = [];
4646
if (!class_exists(CssInlinerExtension::class)) {
47-
$missingPackages['twig/cssinliner-extra'] = ' CSS Inliner';
47+
$missingPackages['twig/cssinliner-extra'] = 'CSS Inliner';
4848
}
4949

5050
if (!class_exists(InkyExtension::class)) {

src/Symfony/Component/ErrorHandler/Resources/assets/css/exception.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ header .container { display: flex; justify-content: space-between; }
225225
.trace-line + .trace-line { border-top: var(--border); }
226226
.trace-line:hover { background: var(--base-1); }
227227
.trace-line a { color: var(--base-6); }
228-
.trace-line .icon { opacity: .4; position: absolute; left: 10px; top: 11px; }
228+
.trace-line .icon { opacity: .4; position: absolute; left: 10px; }
229229
.trace-line .icon svg { fill: var(--base-5); height: 16px; width: 16px; }
230230
.trace-line .icon.icon-copy { left: auto; top: auto; padding-left: 5px; display: none }
231231
.trace-line:hover .icon.icon-copy:not(.hidden) { display: inline-block }

src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ public function validate($form, Constraint $formConstraint)
113113
foreach ($constraints as $constraint) {
114114
// For the "Valid" constraint, validate the data in all groups
115115
if ($constraint instanceof Valid) {
116-
if (\is_object($data)) {
116+
if (\is_object($data) || \is_array($data)) {
117117
$validator->atPath('data')->validate($data, $constraint, $groups);
118118
}
119119

src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorFunctionalTest.php

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Symfony\Component\Form\AbstractType;
1616
use Symfony\Component\Form\CallbackTransformer;
1717
use Symfony\Component\Form\Exception\TransformationFailedException;
18+
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
1819
use Symfony\Component\Form\Extension\Core\Type\DateType;
1920
use Symfony\Component\Form\Extension\Core\Type\FormType;
2021
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
@@ -321,6 +322,35 @@ public function testCascadeValidationToChildFormsWithTwoValidConstraints2()
321322
$this->assertSame('children[author].data.email', $violations[1]->getPropertyPath());
322323
}
323324

325+
public function testCascadeValidationToArrayChildForm()
326+
{
327+
$form = $this->formFactory->create(FormType::class, null, [
328+
'data_class' => Review::class,
329+
])
330+
->add('title')
331+
->add('customers', CollectionType::class, [
332+
'mapped' => false,
333+
'entry_type' => CustomerType::class,
334+
'allow_add' => true,
335+
'constraints' => [new Valid()],
336+
]);
337+
338+
$form->submit([
339+
'title' => 'Sample Title',
340+
'customers' => [
341+
['email' => null],
342+
],
343+
]);
344+
345+
$violations = $this->validator->validate($form);
346+
347+
$this->assertCount(2, $violations);
348+
$this->assertSame('This value should not be blank.', $violations[0]->getMessage());
349+
$this->assertSame('data.rating', $violations[0]->getPropertyPath());
350+
$this->assertSame('This value should not be blank.', $violations[1]->getMessage());
351+
$this->assertSame('children[customers].data[0].email', $violations[1]->getPropertyPath());
352+
}
353+
324354
public function testCascadeValidationToChildFormsUsingPropertyPathsValidatedInSequence()
325355
{
326356
$form = $this->formFactory->create(FormType::class, null, [

src/Symfony/Component/HttpClient/CurlHttpClient.php

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,10 @@ public function request(string $method, string $url, array $options = []): Respo
9595
$scheme = $url['scheme'];
9696
$authority = $url['authority'];
9797
$host = parse_url($authority, \PHP_URL_HOST);
98+
$proxy = $options['proxy']
99+
?? ('https:' === $url['scheme'] ? $_SERVER['https_proxy'] ?? $_SERVER['HTTPS_PROXY'] ?? null : null)
100+
// Ignore HTTP_PROXY except on the CLI to work around httpoxy set of vulnerabilities
101+
?? $_SERVER['http_proxy'] ?? (\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) ? $_SERVER['HTTP_PROXY'] ?? null : null) ?? $_SERVER['all_proxy'] ?? $_SERVER['ALL_PROXY'] ?? null;
98102
$url = implode('', $url);
99103

100104
if (!isset($options['normalized_headers']['user-agent'])) {
@@ -110,7 +114,7 @@ public function request(string $method, string $url, array $options = []): Respo
110114
\CURLOPT_MAXREDIRS => 0 < $options['max_redirects'] ? $options['max_redirects'] : 0,
111115
\CURLOPT_COOKIEFILE => '', // Keep track of cookies during redirects
112116
\CURLOPT_TIMEOUT => 0,
113-
\CURLOPT_PROXY => $options['proxy'],
117+
\CURLOPT_PROXY => $proxy,
114118
\CURLOPT_NOPROXY => $options['no_proxy'] ?? $_SERVER['no_proxy'] ?? $_SERVER['NO_PROXY'] ?? '',
115119
\CURLOPT_SSL_VERIFYPEER => $options['verify_peer'],
116120
\CURLOPT_SSL_VERIFYHOST => $options['verify_host'] ? 2 : 0,
@@ -409,8 +413,15 @@ private static function createRedirectResolver(array $options, string $host): \C
409413
}
410414

411415
$url = self::parseUrl(curl_getinfo($ch, \CURLINFO_EFFECTIVE_URL));
416+
$url = self::resolveUrl($location, $url);
412417

413-
return implode('', self::resolveUrl($location, $url));
418+
curl_setopt($ch, \CURLOPT_PROXY, $options['proxy']
419+
?? ('https:' === $url['scheme'] ? $_SERVER['https_proxy'] ?? $_SERVER['HTTPS_PROXY'] ?? null : null)
420+
// Ignore HTTP_PROXY except on the CLI to work around httpoxy set of vulnerabilities
421+
?? $_SERVER['http_proxy'] ?? (\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) ? $_SERVER['HTTP_PROXY'] ?? null : null) ?? $_SERVER['all_proxy'] ?? $_SERVER['ALL_PROXY'] ?? null
422+
);
423+
424+
return implode('', $url);
414425
};
415426
}
416427

src/Symfony/Component/Process/PhpExecutableFinder.php

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ public function find(bool $includeArgs = true)
4545
}
4646
}
4747

48+
if (@is_dir($php)) {
49+
return false;
50+
}
51+
4852
return $php;
4953
}
5054

@@ -57,20 +61,20 @@ public function find(bool $includeArgs = true)
5761
}
5862

5963
if ($php = getenv('PHP_PATH')) {
60-
if (!@is_executable($php)) {
64+
if (!@is_executable($php) || @is_dir($php)) {
6165
return false;
6266
}
6367

6468
return $php;
6569
}
6670

6771
if ($php = getenv('PHP_PEAR_PHP_BIN')) {
68-
if (@is_executable($php)) {
72+
if (@is_executable($php) && !@is_dir($php)) {
6973
return $php;
7074
}
7175
}
7276

73-
if (@is_executable($php = \PHP_BINDIR.('\\' === \DIRECTORY_SEPARATOR ? '\\php.exe' : '/php'))) {
77+
if (@is_executable($php = \PHP_BINDIR.('\\' === \DIRECTORY_SEPARATOR ? '\\php.exe' : '/php')) && !@is_dir($php)) {
7478
return $php;
7579
}
7680

src/Symfony/Component/Process/Tests/PhpExecutableFinderTest.php

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,32 @@ public function testFindArguments()
5050
public function testNotExitsBinaryFile()
5151
{
5252
$f = new PhpExecutableFinder();
53-
$phpBinaryEnv = \PHP_BINARY;
54-
putenv('PHP_BINARY=/usr/local/php/bin/php-invalid');
5553

56-
$this->assertFalse($f->find(), '::find() returns false because of not exist file');
57-
$this->assertFalse($f->find(false), '::find(false) returns false because of not exist file');
54+
$originalPhpBinary = getenv('PHP_BINARY');
5855

59-
putenv('PHP_BINARY='.$phpBinaryEnv);
56+
try {
57+
putenv('PHP_BINARY=/usr/local/php/bin/php-invalid');
58+
59+
$this->assertFalse($f->find(), '::find() returns false because of not exist file');
60+
$this->assertFalse($f->find(false), '::find(false) returns false because of not exist file');
61+
} finally {
62+
putenv('PHP_BINARY='.$originalPhpBinary);
63+
}
64+
}
65+
66+
public function testFindWithExecutableDirectory()
67+
{
68+
$originalPhpBinary = getenv('PHP_BINARY');
69+
70+
try {
71+
$executableDirectoryPath = sys_get_temp_dir().'/PhpExecutableFinderTest_testFindWithExecutableDirectory';
72+
@mkdir($executableDirectoryPath);
73+
$this->assertTrue(is_executable($executableDirectoryPath));
74+
putenv('PHP_BINARY='.$executableDirectoryPath);
75+
76+
$this->assertFalse((new PhpExecutableFinder())->find());
77+
} finally {
78+
putenv('PHP_BINARY='.$originalPhpBinary);
79+
}
6080
}
6181
}

src/Symfony/Contracts/HttpClient/Test/HttpClientTestCase.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -954,6 +954,16 @@ public function testProxy()
954954

955955
$body = $response->toArray();
956956
$this->assertSame('Basic Zm9vOmI9YXI=', $body['HTTP_PROXY_AUTHORIZATION']);
957+
958+
$_SERVER['http_proxy'] = 'http://localhost:8057';
959+
try {
960+
$response = $client->request('GET', 'http://localhost:8057/');
961+
$body = $response->toArray();
962+
$this->assertSame('localhost:8057', $body['HTTP_HOST']);
963+
$this->assertMatchesRegularExpression('#^http://(localhost|127\.0\.0\.1):8057/$#', $body['REQUEST_URI']);
964+
} finally {
965+
unset($_SERVER['http_proxy']);
966+
}
957967
}
958968

959969
public function testNoProxy()

src/Symfony/Contracts/Service/ServiceSubscriberTrait.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public static function getSubscribedServices(): array
3636
return $services;
3737
}
3838

39-
$services = \is_callable(['parent', __FUNCTION__]) ? parent::getSubscribedServices() : [];
39+
$services = method_exists(get_parent_class(self::class) ?: '', __FUNCTION__) ? parent::getSubscribedServices() : [];
4040
$attributeOptIn = false;
4141

4242
if (\PHP_VERSION_ID >= 80000) {
@@ -106,7 +106,7 @@ public function setContainer(ContainerInterface $container)
106106
{
107107
$this->container = $container;
108108

109-
if (\is_callable(['parent', __FUNCTION__])) {
109+
if (method_exists(get_parent_class(self::class) ?: '', __FUNCTION__)) {
110110
return parent::setContainer($container);
111111
}
112112

src/Symfony/Contracts/Tests/Service/ServiceSubscriberTraitTest.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,32 @@ public function testSetContainerIsCalledOnParent()
5555
$this->assertSame($container, (new TestService())->setContainer($container));
5656
}
5757

58+
public function testParentNotCalledIfHasMagicCall()
59+
{
60+
$container = new class([]) implements ContainerInterface {
61+
use ServiceLocatorTrait;
62+
};
63+
$service = new class() extends ParentWithMagicCall {
64+
use ServiceSubscriberTrait;
65+
};
66+
67+
$this->assertNull($service->setContainer($container));
68+
$this->assertSame([], $service::getSubscribedServices());
69+
}
70+
71+
public function testParentNotCalledIfNoParent()
72+
{
73+
$container = new class([]) implements ContainerInterface {
74+
use ServiceLocatorTrait;
75+
};
76+
$service = new class() {
77+
use ServiceSubscriberTrait;
78+
};
79+
80+
$this->assertNull($service->setContainer($container));
81+
$this->assertSame([], $service::getSubscribedServices());
82+
}
83+
5884
/**
5985
* @requires PHP 8
6086
* @group legacy
@@ -118,6 +144,19 @@ public function aChildService(): Service3
118144
}
119145
}
120146

147+
class ParentWithMagicCall
148+
{
149+
public function __call($method, $args)
150+
{
151+
throw new \BadMethodCallException('Should not be called.');
152+
}
153+
154+
public static function __callStatic($method, $args)
155+
{
156+
throw new \BadMethodCallException('Should not be called.');
157+
}
158+
}
159+
121160
class Service3
122161
{
123162
}

0 commit comments

Comments
 (0)