Skip to content

Commit b91e829

Browse files
committed
Merge branch '5.4' into 6.3
* 5.4: [Console] Only execute additional checks for color support if the output is a TTY fix aircraft inflection [TwigBundle] Fix configuration when 'paths' is null [String] Correct inflection of axis [Security] Fix `AuthenticationUtils::getLastUsername()` returning null [Process] Fixed inconsistent test
2 parents f845c6e + 1c7c730 commit b91e829

File tree

8 files changed

+180
-6
lines changed

8 files changed

+180
-6
lines changed

src/Symfony/Bundle/TwigBundle/DependencyInjection/Configuration.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ private function addTwigOptions(ArrayNodeDefinition $rootNode): void
157157
->normalizeKeys(false)
158158
->useAttributeAsKey('paths')
159159
->beforeNormalization()
160-
->always()
160+
->ifArray()
161161
->then(function ($paths) {
162162
$normalized = [];
163163
foreach ($paths as $path => $namespace) {

src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/ConfigurationTest.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,16 @@ public function testArrayKeysInGlobalsAreNotNormalized()
5252

5353
$this->assertSame(['global' => ['value' => ['some-key' => 'some-value']]], $config['globals']);
5454
}
55+
56+
public function testNullPathsAreConvertedToIterable()
57+
{
58+
$input = [
59+
'paths' => null,
60+
];
61+
62+
$processor = new Processor();
63+
$config = $processor->processConfiguration(new Configuration(), [$input]);
64+
65+
$this->assertSame([], $config['paths']);
66+
}
5567
}

src/Symfony/Component/Console/Output/StreamOutput.php

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,10 @@ protected function hasColorSupport(): bool
9696
return false;
9797
}
9898

99+
if (!$this->isTty()) {
100+
return false;
101+
}
102+
99103
if (\DIRECTORY_SEPARATOR === '\\'
100104
&& \function_exists('sapi_windows_vt100_support')
101105
&& @sapi_windows_vt100_support($this->stream)
@@ -106,7 +110,36 @@ protected function hasColorSupport(): bool
106110
return 'Hyper' === getenv('TERM_PROGRAM')
107111
|| false !== getenv('ANSICON')
108112
|| 'ON' === getenv('ConEmuANSI')
109-
|| str_starts_with((string) getenv('TERM'), 'xterm')
110-
|| stream_isatty($this->stream);
113+
|| str_starts_with((string) getenv('TERM'), 'xterm');
114+
}
115+
116+
/**
117+
* Checks if the stream is a TTY, i.e; whether the output stream is connected to a terminal.
118+
*
119+
* Reference: Composer\Util\Platform::isTty
120+
* https://github.com/composer/composer
121+
*/
122+
private function isTty(): bool
123+
{
124+
// Detect msysgit/mingw and assume this is a tty because detection
125+
// does not work correctly, see https://github.com/composer/composer/issues/9690
126+
if (\in_array(strtoupper((string) getenv('MSYSTEM')), ['MINGW32', 'MINGW64'], true)) {
127+
return true;
128+
}
129+
130+
// Modern cross-platform function, includes the fstat fallback so if it is present we trust it
131+
if (\function_exists('stream_isatty')) {
132+
return stream_isatty($this->stream);
133+
}
134+
135+
// Only trusting this if it is positive, otherwise prefer fstat fallback.
136+
if (\function_exists('posix_isatty') && posix_isatty($this->stream)) {
137+
return true;
138+
}
139+
140+
$stat = @fstat($this->stream);
141+
142+
// Check if formatted mode is S_IFCHR
143+
return $stat ? 0020000 === ($stat['mode'] & 0170000) : false;
111144
}
112145
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
while (!str_contains($process->getOutput(), 'ready')) {
2626
usleep(1000);
2727
}
28-
$process->signal(\SIGSTOP);
28+
$process->isRunning() && $process->signal(\SIGSTOP);
2929
$process->wait();
3030

3131
return $process->getExitCode();

src/Symfony/Component/Security/Http/Authentication/AuthenticationUtils.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,10 @@ public function getLastUsername(): string
5353
$request = $this->getRequest();
5454

5555
if ($request->attributes->has(SecurityRequestAttributes::LAST_USERNAME)) {
56-
return $request->attributes->get(SecurityRequestAttributes::LAST_USERNAME, '');
56+
return $request->attributes->get(SecurityRequestAttributes::LAST_USERNAME) ?? '';
5757
}
5858

59-
return $request->hasSession() ? $request->getSession()->get(SecurityRequestAttributes::LAST_USERNAME, '') : '';
59+
return $request->hasSession() ? ($request->getSession()->get(SecurityRequestAttributes::LAST_USERNAME) ?? '') : '';
6060
}
6161

6262
/**
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Security\Http\Tests\Authentication;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\HttpFoundation\Request;
16+
use Symfony\Component\HttpFoundation\RequestStack;
17+
use Symfony\Component\HttpFoundation\Session\Session;
18+
use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
19+
use Symfony\Component\Security\Core\Security;
20+
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
21+
22+
class AuthenticationUtilsTest extends TestCase
23+
{
24+
public function testLastAuthenticationErrorWhenRequestHasAttribute()
25+
{
26+
$request = Request::create('/');
27+
$request->attributes->set(Security::AUTHENTICATION_ERROR, 'my error');
28+
29+
$requestStack = new RequestStack();
30+
$requestStack->push($request);
31+
32+
$utils = new AuthenticationUtils($requestStack);
33+
$this->assertSame('my error', $utils->getLastAuthenticationError());
34+
}
35+
36+
public function testLastAuthenticationErrorInSession()
37+
{
38+
$request = Request::create('/');
39+
40+
$session = new Session(new MockArraySessionStorage());
41+
$session->set(Security::AUTHENTICATION_ERROR, 'session error');
42+
$request->setSession($session);
43+
44+
$requestStack = new RequestStack();
45+
$requestStack->push($request);
46+
47+
$utils = new AuthenticationUtils($requestStack);
48+
$this->assertSame('session error', $utils->getLastAuthenticationError());
49+
$this->assertFalse($session->has(Security::AUTHENTICATION_ERROR));
50+
}
51+
52+
public function testLastAuthenticationErrorInSessionWithoutClearing()
53+
{
54+
$request = Request::create('/');
55+
56+
$session = new Session(new MockArraySessionStorage());
57+
$session->set(Security::AUTHENTICATION_ERROR, 'session error');
58+
$request->setSession($session);
59+
60+
$requestStack = new RequestStack();
61+
$requestStack->push($request);
62+
63+
$utils = new AuthenticationUtils($requestStack);
64+
$this->assertSame('session error', $utils->getLastAuthenticationError(false));
65+
$this->assertTrue($session->has(Security::AUTHENTICATION_ERROR));
66+
}
67+
68+
public function testLastUserNameIsDefinedButNull()
69+
{
70+
$request = Request::create('/');
71+
$request->attributes->set(Security::LAST_USERNAME, null);
72+
73+
$requestStack = new RequestStack();
74+
$requestStack->push($request);
75+
76+
$utils = new AuthenticationUtils($requestStack);
77+
$this->assertSame('', $utils->getLastUsername());
78+
}
79+
80+
public function testLastUserNameIsDefined()
81+
{
82+
$request = Request::create('/');
83+
$request->attributes->set(Security::LAST_USERNAME, 'user');
84+
85+
$requestStack = new RequestStack();
86+
$requestStack->push($request);
87+
88+
$utils = new AuthenticationUtils($requestStack);
89+
$this->assertSame('user', $utils->getLastUsername());
90+
}
91+
92+
public function testLastUserNameIsDefinedInSessionButNull()
93+
{
94+
$request = Request::create('/');
95+
96+
$session = new Session(new MockArraySessionStorage());
97+
$session->set(Security::LAST_USERNAME, null);
98+
$request->setSession($session);
99+
100+
$requestStack = new RequestStack();
101+
$requestStack->push($request);
102+
103+
$utils = new AuthenticationUtils($requestStack);
104+
$this->assertSame('', $utils->getLastUsername());
105+
}
106+
107+
public function testLastUserNameIsDefinedInSession()
108+
{
109+
$request = Request::create('/');
110+
111+
$session = new Session(new MockArraySessionStorage());
112+
$session->set(Security::LAST_USERNAME, 'user');
113+
$request->setSession($session);
114+
115+
$requestStack = new RequestStack();
116+
$requestStack->push($request);
117+
118+
$utils = new AuthenticationUtils($requestStack);
119+
$this->assertSame('user', $utils->getLastUsername());
120+
}
121+
}

src/Symfony/Component/String/Inflector/EnglishInflector.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,9 @@ final class EnglishInflector implements InflectorInterface
166166
// Fourth entry: Whether the suffix may succeed a consonant
167167
// Fifth entry: plural suffix, normal
168168

169+
// axes (axis)
170+
['sixa', 4, false, false, 'axes'],
171+
169172
// criterion (criteria)
170173
['airetirc', 8, false, false, 'criterion'],
171174

@@ -384,6 +387,9 @@ final class EnglishInflector implements InflectorInterface
384387

385388
// traffic
386389
'ciffart',
390+
391+
// aircraft
392+
'tfarcria',
387393
];
388394

389395
public function singularize(string $plural): array

src/Symfony/Component/String/Tests/Inflector/EnglishInflectorTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,13 +178,15 @@ public static function pluralizeProvider()
178178
['access', 'accesses'],
179179
['address', 'addresses'],
180180
['agenda', 'agendas'],
181+
['aircraft', 'aircraft'],
181182
['alumnus', 'alumni'],
182183
['analysis', 'analyses'],
183184
['antenna', 'antennas'], // antennae
184185
['appendix', ['appendicies', 'appendixes']],
185186
['arch', 'arches'],
186187
['atlas', 'atlases'],
187188
['axe', 'axes'],
189+
['axis', 'axes'],
188190
['baby', 'babies'],
189191
['bacterium', 'bacteria'],
190192
['base', 'bases'],

0 commit comments

Comments
 (0)