Skip to content

Navigation Menu

Sign in
Appearance settings
Sign up
Appearance settings

Commit bb0c01f

Browse filesBrowse the repository at this point in the historyBrowse files
Merge branch '8.1' into 8.2
* 8.1: [Notifier] Fix escaping of MarkdownV2 markup in TelegramTransport [Serializer] Let DISABLE_TYPE_ENFORCEMENT keep strings that cannot be converted [Console][FrameworkBundle] Fix profiling a command stopped at ConsoleEvents::COMMAND [HttpKernel] Fix regression when a locale aware service is never initialized [HttpClient] Fix GuzzleHttpHandler consuming responses out of band [Cache] Fix authenticating to the master when using Redis Sentinel [Validator] reviewed Polish translation units 147 and 148 [Validator] Improve Serbian translation messages; synchronized latin and cyrillic messages; consistent use of 'ispravan'; few grammar errors and typos corrected #65566 [Validator] Review Turkish (tr) translations [PropertyInfo] Do not prefer a static named constructor as the property mutator [PropertyInfo] Do not prefer a static named constructor as the property accessor [Console] Fix service arguments not resolved when a command is invoked by alias or abbreviation [Validator] Review translations for Russian (ru) #65560 # Conflicts: # src/Symfony/Component/Console/Tests/Command/InvokableCommandTest.php # src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php
2 parents d334117 + 1ad3a65 commit bb0c01f
Copy full SHA for bb0c01f

30 files changed

+877-305Lines changed: 877 additions & 305 deletions

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎src/Symfony/Bundle/FrameworkBundle/EventListener/ConsoleProfilerListener.php‎

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/EventListener/ConsoleProfilerListener.php
+11-2Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,17 @@ public function profile(ConsoleTerminateEvent $event): void
122122
}
123123
}
124124

125-
$request->command->exitCode = $event->getExitCode();
126-
$request->command->interruptedBySignal = $event->getInterruptingSignal();
125+
$command = $request->command;
126+
$command->exitCode = $event->getExitCode();
127+
$command->interruptedBySignal = $event->getInterruptingSignal();
128+
129+
if (!isset($command->input)) {
130+
// the command was stopped before it could run and record what it was given
131+
$command->input = $input = $event->getInput();
132+
$command->output = $event->getOutput();
133+
$command->arguments = $input->getArguments();
134+
$command->options = $input->getOptions();
135+
}
127136

128137
$profile = $this->profiler->collect($request, $request->getResponse(), $error);
129138
$this->profiles[$request] = $profile;
Collapse file
+108Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
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+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bundle\FrameworkBundle\Tests\Functional;
13+
14+
use Symfony\Bundle\FrameworkBundle\Console\Application;
15+
use Symfony\Component\Console\Command\Command;
16+
use Symfony\Component\Console\ConsoleEvents;
17+
use Symfony\Component\Console\Event\ConsoleCommandEvent;
18+
use Symfony\Component\Console\Input\ArrayInput;
19+
use Symfony\Component\Console\Input\InputArgument;
20+
use Symfony\Component\Console\Output\NullOutput;
21+
use Symfony\Component\HttpKernel\Profiler\Profile;
22+
23+
class ConsoleProfilerTest extends AbstractWebTestCase
24+
{
25+
protected function setUp(): void
26+
{
27+
static::bootKernel(['test_case' => 'ConsoleProfiler', 'debug' => true]);
28+
static::getContainer()->get('public_profiler')->purge();
29+
}
30+
31+
public function testProfileCommandDisabledByListener()
32+
{
33+
$application = $this->createApplication();
34+
$this->stopCommandWith(static fn (ConsoleCommandEvent $event) => $event->disableCommand());
35+
36+
$exitCode = $application->run(new ArrayInput(['command' => 'app:profiled', 'name' => 'Fabien', '--profile' => true]), new NullOutput());
37+
38+
$this->assertSame(ConsoleCommandEvent::RETURN_CODE_DISABLED, $exitCode);
39+
40+
$profile = $this->loadProfile();
41+
42+
$this->assertStringContainsString('app:profiled', $profile->getUrl());
43+
$this->assertSame(ConsoleCommandEvent::RETURN_CODE_DISABLED, $profile->getStatusCode());
44+
$this->assertSame('Fabien', $profile->getCollector('command')->getArguments()['name']->getValue());
45+
}
46+
47+
public function testProfileCommandStoppedByThrowingListener()
48+
{
49+
$application = $this->createApplication();
50+
$this->stopCommandWith(static fn () => throw new \RuntimeException('Access denied.'));
51+
52+
try {
53+
$application->run(new ArrayInput(['command' => 'app:profiled', 'name' => 'Fabien', '--profile' => true]), new NullOutput());
54+
$this->fail('The listener should have stopped the command.');
55+
} catch (\RuntimeException $e) {
56+
$this->assertSame('Access denied.', $e->getMessage());
57+
}
58+
59+
$profile = $this->loadProfile();
60+
61+
$this->assertSame(1, $profile->getStatusCode());
62+
$this->assertSame('Fabien', $profile->getCollector('command')->getArguments()['name']->getValue());
63+
$this->assertTrue($profile->getCollector('exception')->hasException());
64+
}
65+
66+
public function testProfileCommandThatRuns()
67+
{
68+
$application = $this->createApplication();
69+
70+
$exitCode = $application->run(new ArrayInput(['command' => 'app:profiled', 'name' => 'Fabien', '--profile' => true]), new NullOutput());
71+
72+
$this->assertSame(Command::SUCCESS, $exitCode);
73+
74+
$profile = $this->loadProfile();
75+
76+
$this->assertSame(Command::SUCCESS, $profile->getStatusCode());
77+
$this->assertSame('Fabien', $profile->getCollector('command')->getArguments()['name']->getValue());
78+
}
79+
80+
private function createApplication(): Application
81+
{
82+
$command = new Command('app:profiled');
83+
$command->addArgument('name', InputArgument::REQUIRED);
84+
$command->setCode(static fn (): int => Command::SUCCESS);
85+
86+
$application = new Application(static::$kernel);
87+
$application->setAutoExit(false);
88+
$application->setCatchExceptions(false);
89+
$application->addCommand($command);
90+
91+
return $application;
92+
}
93+
94+
private function stopCommandWith(callable $listener): void
95+
{
96+
static::getContainer()->get('event_dispatcher')->addListener(ConsoleEvents::COMMAND, $listener);
97+
}
98+
99+
private function loadProfile(): Profile
100+
{
101+
$profiler = static::getContainer()->get('public_profiler');
102+
$tokens = $profiler->find('', '', 2, '', '', '');
103+
104+
$this->assertCount(1, $tokens);
105+
106+
return $profiler->loadProfile($tokens[0]['token']);
107+
}
108+
}
Collapse file
+16Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
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+
* file that was distributed with this source code.
10+
*/
11+
12+
use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
13+
14+
return [
15+
new FrameworkBundle(),
16+
];
Collapse file
+13Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
imports:
2+
- { resource: ../config/default.yml }
3+
4+
framework:
5+
http_method_override: false
6+
profiler:
7+
enabled: true
8+
collect: true
9+
10+
services:
11+
public_profiler:
12+
alias: profiler
13+
public: true
Collapse file

‎src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/config/schema.json‎

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/config/schema.json
-159Lines changed: 0 additions & 159 deletions
Original file line numberDiff line numberDiff line change
@@ -4733,153 +4733,6 @@
47334733
},
47344734
"additionalProperties": false
47354735
},
4736-
"mercure": {
4737-
"$ref": "#/$defs/types/object_null",
4738-
"properties": {
4739-
"hubs": {
4740-
"$ref": "#/$defs/types/object_null",
4741-
"additionalProperties": {
4742-
"$ref": "#/$defs/types/object_null",
4743-
"properties": {
4744-
"url": {
4745-
"$ref": "#/$defs/types/scalar",
4746-
"description": "URL of the hub's publish endpoint",
4747-
"examples": [
4748-
"https://demo.mercure.rocks/.well-known/mercure"
4749-
]
4750-
},
4751-
"public_url": {
4752-
"$ref": "#/$defs/types/scalar",
4753-
"default": null,
4754-
"description": "URL of the hub's public endpoint",
4755-
"examples": [
4756-
"https://demo.mercure.rocks/.well-known/mercure"
4757-
]
4758-
},
4759-
"jwt": {
4760-
"anyOf": [
4761-
{
4762-
"$ref": "#/$defs/types/object_null",
4763-
"properties": {
4764-
"value": {
4765-
"$ref": "#/$defs/types/scalar",
4766-
"description": "JSON Web Token to use to publish to this hub."
4767-
},
4768-
"provider": {
4769-
"$ref": "#/$defs/types/scalar",
4770-
"description": "The ID of a service to call to provide the JSON Web Token."
4771-
},
4772-
"factory": {
4773-
"$ref": "#/$defs/types/scalar",
4774-
"description": "The ID of a service to call to create the JSON Web Token."
4775-
},
4776-
"publish": {
4777-
"$ref": "#/$defs/types/array_null",
4778-
"items": {
4779-
"$ref": "#/$defs/types/scalar"
4780-
},
4781-
"description": "A list of topics to allow publishing to when using the given factory to generate the JWT."
4782-
},
4783-
"subscribe": {
4784-
"$ref": "#/$defs/types/array_null",
4785-
"items": {
4786-
"$ref": "#/$defs/types/scalar"
4787-
},
4788-
"description": "A list of topics to allow subscribing to when using the given factory to generate the JWT."
4789-
},
4790-
"secret": {
4791-
"$ref": "#/$defs/types/scalar",
4792-
"description": "The JWT Secret to use.",
4793-
"examples": [
4794-
"!ChangeMe!"
4795-
]
4796-
},
4797-
"passphrase": {
4798-
"$ref": "#/$defs/types/scalar",
4799-
"default": "",
4800-
"description": "The JWT secret passphrase."
4801-
},
4802-
"algorithm": {
4803-
"$ref": "#/$defs/types/scalar",
4804-
"default": "hmac.sha256",
4805-
"description": "The algorithm to use to sign the JWT"
4806-
}
4807-
},
4808-
"additionalProperties": false
4809-
},
4810-
{
4811-
"type": [
4812-
"string"
4813-
]
4814-
}
4815-
],
4816-
"description": "JSON Web Token configuration."
4817-
},
4818-
"jwt_provider": {
4819-
"$ref": "#/$defs/types/scalar",
4820-
"description": "Deprecated since symfony/mercure-bundle 0.3: The child node \"jwt_provider\" at path \"mercure.hubs..jwt_provider\" is deprecated, use \"jwt.provider\" instead.\n\nThe ID of a service to call to generate the JSON Web Token.",
4821-
"deprecated": true
4822-
},
4823-
"bus": {
4824-
"$ref": "#/$defs/types/scalar",
4825-
"description": "Name of the Messenger bus where the handler for this hub must be registered. Default to the default bus if Messenger is enabled."
4826-
}
4827-
},
4828-
"additionalProperties": false
4829-
}
4830-
},
4831-
"default_hub": {
4832-
"$ref": "#/$defs/types/scalar"
4833-
},
4834-
"default_cookie_lifetime": {
4835-
"$ref": "#/$defs/types/integer",
4836-
"default": null,
4837-
"description": "Default lifetime of the cookie containing the JWT, in seconds. Defaults to the value of \"framework.session.cookie_lifetime\"."
4838-
},
4839-
"enable_profiler": {
4840-
"$ref": "#/$defs/types/boolean",
4841-
"description": "Deprecated since symfony/mercure-bundle 0.3: The child node \"enable_profiler\" at path \"mercure.enable_profiler\" is deprecated.\n\nEnable Symfony Web Profiler integration.",
4842-
"deprecated": true
4843-
}
4844-
},
4845-
"additionalProperties": false
4846-
},
4847-
"test": {
4848-
"$ref": "#/$defs/types/object_null",
4849-
"properties": {
4850-
"custom": {
4851-
"$ref": "#/$defs/types/scalar"
4852-
},
4853-
"array": {
4854-
"$ref": "#/$defs/types/object_null",
4855-
"properties": {
4856-
"child1": {
4857-
"$ref": "#/$defs/types/scalar"
4858-
},
4859-
"child2": {
4860-
"$ref": "#/$defs/types/scalar"
4861-
}
4862-
},
4863-
"additionalProperties": false
4864-
},
4865-
"options": {
4866-
"$ref": "#/$defs/types/object_null",
4867-
"additionalProperties": {
4868-
"$ref": "#/$defs/types/object_null",
4869-
"properties": {
4870-
"key": {
4871-
"$ref": "#/$defs/types/scalar"
4872-
},
4873-
"data": {
4874-
"$ref": "#/$defs/types/scalar"
4875-
}
4876-
},
4877-
"additionalProperties": false
4878-
}
4879-
}
4880-
},
4881-
"additionalProperties": false
4882-
},
48834736
"test_dump": {
48844737
"$ref": "#/$defs/types/object_null",
48854738
"properties": {
@@ -4900,12 +4753,6 @@
49004753
"framework": {
49014754
"$ref": "#/$defs/nodes/framework"
49024755
},
4903-
"mercure": {
4904-
"$ref": "#/$defs/nodes/mercure"
4905-
},
4906-
"test": {
4907-
"$ref": "#/$defs/nodes/test"
4908-
},
49094756
"test_dump": {
49104757
"$ref": "#/$defs/nodes/test_dump"
49114758
}
@@ -4920,12 +4767,6 @@
49204767
"framework": {
49214768
"$ref": "#/$defs/nodes/framework"
49224769
},
4923-
"mercure": {
4924-
"$ref": "#/$defs/nodes/mercure"
4925-
},
4926-
"test": {
4927-
"$ref": "#/$defs/nodes/test"
4928-
},
49294770
"test_dump": {
49304771
"$ref": "#/$defs/nodes/test_dump"
49314772
}
Collapse file

‎src/Symfony/Component/Cache/Tests/Traits/RedisTraitTest.php‎

Copy file name to clipboardExpand all lines: src/Symfony/Component/Cache/Tests/Traits/RedisTraitTest.php
+14Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,13 @@ public function testPredisSentinelAuthResolution(string $dsn, array $options, st
269269

270270
public static function providePredisSentinelAuthResolution(): \Generator
271271
{
272+
yield 'master userinfo, no sentinel auth' => [
273+
'redis://master-user:master-pass@localhost?redis_sentinel=mymaster',
274+
[],
275+
['master-user', 'master-pass'],
276+
null,
277+
];
278+
272279
yield 'sentinel query auth, master userinfo' => [
273280
'redis://master-user:master-pass@localhost?redis_sentinel=mymaster&auth[]=sentinel-user&auth[]=sentinel-pass',
274281
[],
@@ -289,6 +296,13 @@ public static function providePredisSentinelAuthResolution(): \Generator
289296
'master-pass',
290297
['query-user', 'query-pass'],
291298
];
299+
300+
yield 'auth shared by master and sentinel when no userinfo' => [
301+
'redis://localhost?redis_sentinel=mymaster&auth=shared-pass',
302+
[],
303+
'shared-pass',
304+
'shared-pass',
305+
];
292306
}
293307

294308
private function assertAuthMatchesExpected(string|array|null $expectedAuth, array $parameters): void
Collapse file

‎src/Symfony/Component/Cache/Traits/RedisTrait.php‎

Copy file name to clipboardExpand all lines: src/Symfony/Component/Cache/Traits/RedisTrait.php
+4-2Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -220,8 +220,10 @@ public static function createConnection(#[\SensitiveParameter] string $dsn, arra
220220
$params['auth'] = $auth ?? $params['auth'];
221221
}
222222

223-
if (\is_array($params['auth']) && (!array_is_list($params['auth']) || 2 !== \count($params['auth']))) {
224-
throw new InvalidArgumentException('Invalid Redis DSN: the "auth" parameter must be a string, or a list of exactly two elements for ACL, "[username, password]".');
223+
foreach ([$params['auth'], $sentinelAuth] as $v) {
224+
if (\is_array($v) && (!array_is_list($v) || 2 !== \count($v))) {
225+
throw new InvalidArgumentException('Invalid Redis DSN: the "auth" parameter must be a string, or a list of exactly two elements for ACL, "[username, password]".');
226+
}
225227
}
226228

227229
foreach (['lazy', 'persistent', 'cluster'] as $option) {
Collapse file

‎src/Symfony/Component/Console/ArgumentResolver/ValueResolver/ServiceValueResolver.php‎

Copy file name to clipboardExpand all lines: src/Symfony/Component/Console/ArgumentResolver/ValueResolver/ServiceValueResolver.php
+3-1Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ public function __construct(
3232

3333
public function resolve(string $argumentName, InputInterface $input, ReflectionMember $member): iterable
3434
{
35-
$command = $input->getFirstArgument();
35+
// the "command" argument is normalized to the resolved command name by Command::run(),
36+
// while getFirstArgument() may return an abbreviation or an alias of it
37+
$command = ($input->hasArgument('command') ? $input->getArgument('command') : null) ?? $input->getFirstArgument();
3638

3739
if ($command && $this->container->has($command)) {
3840
$locator = $this->container->get($command);

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.