Skip to content

Commit c7b2cbc

Browse files
committed
Merge branch '6.4' into 7.1
* 6.4: [Console] Fix division by 0 error [ErrorHandler] Fix error message with PHP 8.5 Add an experimental CI job for PHP 8.5 [HttpClient] Always set CURLOPT_CUSTOMREQUEST to the correct HTTP method in CurlHttpClient evaluate access flags for properties with asymmetric visibility [Mime] Fix wrong PHPDoc in `FormDataPart` constructor
2 parents 753b3b8 + caa1be7 commit c7b2cbc

File tree

11 files changed

+90
-10
lines changed

11 files changed

+90
-10
lines changed

.github/workflows/unit-tests.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ jobs:
3333
mode: low-deps
3434
- php: '8.3'
3535
- php: '8.4'
36+
- php: '8.5'
3637
#mode: experimental
3738
fail-fast: false
3839

src/Symfony/Component/Console/Helper/ProgressBar.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ public function getEstimated(): float
229229

230230
public function getRemaining(): float
231231
{
232-
if (!$this->step) {
232+
if (0 === $this->step || $this->step === $this->startingStep) {
233233
return 0;
234234
}
235235

src/Symfony/Component/Console/Tests/Helper/ProgressBarTest.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,14 @@ public function testRegularTimeEstimation()
110110
);
111111
}
112112

113+
public function testRegularTimeRemainingWithDifferentStartAtAndCustomDisplay()
114+
{
115+
ProgressBar::setFormatDefinition('custom', ' %current%/%max% [%bar%] %percent:3s%% %remaining% %estimated%');
116+
$bar = new ProgressBar($output = $this->getOutputStream(), 1_200, 0);
117+
$bar->setFormat('custom');
118+
$bar->start(1_200, 600);
119+
}
120+
113121
public function testResumedTimeEstimation()
114122
{
115123
$bar = new ProgressBar($output = $this->getOutputStream(), 1_200, 0);

src/Symfony/Component/ErrorHandler/Tests/phpt/fatal_with_nested_handlers.phpt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ var_dump([
2424
$eHandler[0]->setExceptionHandler('print_r');
2525

2626
if (true) {
27-
class Broken implements \JsonSerializable
27+
class Broken implements \Iterator
2828
{
2929
}
3030
}
@@ -37,14 +37,14 @@ array(1) {
3737
}
3838
object(Symfony\Component\ErrorHandler\Error\FatalError)#%d (%d) {
3939
["message":protected]=>
40-
string(186) "Error: Class Symfony\Component\ErrorHandler\Broken contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (JsonSerializable::jsonSerialize)"
40+
string(209) "Error: Class Symfony\Component\ErrorHandler\Broken contains 5 abstract methods and must therefore be declared abstract or implement the remaining methods (Iterator::current, Iterator::next, Iterator::key, ...)"
4141
%a
4242
["error":"Symfony\Component\ErrorHandler\Error\FatalError":private]=>
4343
array(4) {
4444
["type"]=>
4545
int(1)
4646
["message"]=>
47-
string(179) "Class Symfony\Component\ErrorHandler\Broken contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (JsonSerializable::jsonSerialize)"
47+
string(202) "Class Symfony\Component\ErrorHandler\Broken contains 5 abstract methods and must therefore be declared abstract or implement the remaining methods (Iterator::current, Iterator::next, Iterator::key, ...)"
4848
["file"]=>
4949
string(%d) "%s"
5050
["line"]=>

src/Symfony/Component/HttpClient/CurlHttpClient.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,13 +197,12 @@ public function request(string $method, string $url, array $options = []): Respo
197197
$curlopts[\CURLOPT_RESOLVE] = $resolve;
198198
}
199199

200+
$curlopts[\CURLOPT_CUSTOMREQUEST] = $method;
200201
if ('POST' === $method) {
201202
// Use CURLOPT_POST to have browser-like POST-to-GET redirects for 301, 302 and 303
202203
$curlopts[\CURLOPT_POST] = true;
203204
} elseif ('HEAD' === $method) {
204205
$curlopts[\CURLOPT_NOBODY] = true;
205-
} else {
206-
$curlopts[\CURLOPT_CUSTOMREQUEST] = $method;
207206
}
208207

209208
if ('\\' !== \DIRECTORY_SEPARATOR && $options['timeout'] < 1) {

src/Symfony/Component/HttpClient/Tests/HttpClientTestCase.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -656,4 +656,26 @@ public function testDefaultContentType()
656656

657657
$this->assertSame(['abc' => 'def', 'content-type' => 'application/json', 'REQUEST_METHOD' => 'POST'], $response->toArray());
658658
}
659+
660+
public function testHeadRequestWithClosureBody()
661+
{
662+
$p = TestHttpServer::start(8067);
663+
664+
try {
665+
$client = $this->getHttpClient(__FUNCTION__);
666+
667+
$response = $client->request('HEAD', 'http://localhost:8057/head', [
668+
'body' => fn () => '',
669+
]);
670+
$headers = $response->getHeaders();
671+
} finally {
672+
$p->stop();
673+
}
674+
675+
$this->assertArrayHasKey('x-request-vars', $headers);
676+
677+
$vars = json_decode($headers['x-request-vars'][0], true);
678+
$this->assertIsArray($vars);
679+
$this->assertSame('HEAD', $vars['REQUEST_METHOD']);
680+
}
659681
}

src/Symfony/Component/HttpClient/composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
"php": ">=8.2",
2626
"psr/log": "^1|^2|^3",
2727
"symfony/deprecation-contracts": "^2.5|^3",
28-
"symfony/http-client-contracts": "~3.4.3|^3.5.1",
28+
"symfony/http-client-contracts": "~3.4.4|^3.5.2",
2929
"symfony/service-contracts": "^2.5|^3"
3030
},
3131
"require-dev": {

src/Symfony/Component/Mime/Part/Multipart/FormDataPart.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
final class FormDataPart extends AbstractMultipartPart
2525
{
2626
/**
27-
* @param array<string|array|DataPart> $fields
27+
* @param array<string|array|TextPart> $fields
2828
*/
2929
public function __construct(
3030
private array $fields = [],

src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -705,8 +705,12 @@ private function isAllowedProperty(string $class, string $property, bool $writeA
705705
return false;
706706
}
707707

708-
if (\PHP_VERSION_ID >= 80400 && ($reflectionProperty->isProtectedSet() || $reflectionProperty->isPrivateSet())) {
709-
return false;
708+
if (\PHP_VERSION_ID >= 80400 && $reflectionProperty->isProtectedSet()) {
709+
return (bool) ($this->propertyReflectionFlags & \ReflectionProperty::IS_PROTECTED);
710+
}
711+
712+
if (\PHP_VERSION_ID >= 80400 && $reflectionProperty->isPrivateSet()) {
713+
return (bool) ($this->propertyReflectionFlags & \ReflectionProperty::IS_PRIVATE);
710714
}
711715

712716
if (\PHP_VERSION_ID >= 80400 &&$reflectionProperty->isVirtual() && !$reflectionProperty->hasHook(\PropertyHookType::Set)) {

src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,51 @@ public function testAsymmetricVisibility()
704704
$this->assertFalse($this->extractor->isWritable(AsymmetricVisibility::class, 'protectedPrivate'));
705705
}
706706

707+
/**
708+
* @requires PHP 8.4
709+
*/
710+
public function testAsymmetricVisibilityAllowPublicOnly()
711+
{
712+
$extractor = new ReflectionExtractor(null, null, null, true, ReflectionExtractor::ALLOW_PUBLIC);
713+
714+
$this->assertTrue($extractor->isReadable(AsymmetricVisibility::class, 'publicPrivate'));
715+
$this->assertTrue($extractor->isReadable(AsymmetricVisibility::class, 'publicProtected'));
716+
$this->assertFalse($extractor->isReadable(AsymmetricVisibility::class, 'protectedPrivate'));
717+
$this->assertFalse($extractor->isWritable(AsymmetricVisibility::class, 'publicPrivate'));
718+
$this->assertFalse($extractor->isWritable(AsymmetricVisibility::class, 'publicProtected'));
719+
$this->assertFalse($extractor->isWritable(AsymmetricVisibility::class, 'protectedPrivate'));
720+
}
721+
722+
/**
723+
* @requires PHP 8.4
724+
*/
725+
public function testAsymmetricVisibilityAllowProtectedOnly()
726+
{
727+
$extractor = new ReflectionExtractor(null, null, null, true, ReflectionExtractor::ALLOW_PROTECTED);
728+
729+
$this->assertFalse($extractor->isReadable(AsymmetricVisibility::class, 'publicPrivate'));
730+
$this->assertFalse($extractor->isReadable(AsymmetricVisibility::class, 'publicProtected'));
731+
$this->assertTrue($extractor->isReadable(AsymmetricVisibility::class, 'protectedPrivate'));
732+
$this->assertFalse($extractor->isWritable(AsymmetricVisibility::class, 'publicPrivate'));
733+
$this->assertTrue($extractor->isWritable(AsymmetricVisibility::class, 'publicProtected'));
734+
$this->assertFalse($extractor->isWritable(AsymmetricVisibility::class, 'protectedPrivate'));
735+
}
736+
737+
/**
738+
* @requires PHP 8.4
739+
*/
740+
public function testAsymmetricVisibilityAllowPrivateOnly()
741+
{
742+
$extractor = new ReflectionExtractor(null, null, null, true, ReflectionExtractor::ALLOW_PRIVATE);
743+
744+
$this->assertFalse($extractor->isReadable(AsymmetricVisibility::class, 'publicPrivate'));
745+
$this->assertFalse($extractor->isReadable(AsymmetricVisibility::class, 'publicProtected'));
746+
$this->assertFalse($extractor->isReadable(AsymmetricVisibility::class, 'protectedPrivate'));
747+
$this->assertTrue($extractor->isWritable(AsymmetricVisibility::class, 'publicPrivate'));
748+
$this->assertFalse($extractor->isWritable(AsymmetricVisibility::class, 'publicProtected'));
749+
$this->assertTrue($extractor->isWritable(AsymmetricVisibility::class, 'protectedPrivate'));
750+
}
751+
707752
/**
708753
* @requires PHP 8.4
709754
*/

0 commit comments

Comments
 (0)