Skip to content

Commit a13c74c

Browse files
ycerutonicolas-grekas
authored andcommitted
Remove deprecated methods and legacy code
1 parent 8364823 commit a13c74c

File tree

10 files changed

+75
-144
lines changed

10 files changed

+75
-144
lines changed

UPGRADE-8.0.md

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,66 @@ release process, both versions have the same features, but Symfony 8.0 doesn't i
66
To upgrade, make sure to resolve all deprecation notices.
77
Read more about this in the [Symfony documentation](https://symfony.com/doc/8.0/setup/upgrade_major.html).
88

9+
Console
10+
-------
11+
12+
* Remove methods `Command::getDefaultName()` and `Command::getDefaultDescription()` in favor of the `#[AsCommand]` attribute
13+
14+
*Before*
15+
```php
16+
use Symfony\Component\Console\Command\Command;
17+
18+
class CreateUserCommand extends Command
19+
{
20+
public static function getDefaultName(): ?string
21+
{
22+
return 'app:create-user';
23+
}
24+
25+
public static function getDefaultDescription(): ?string
26+
{
27+
return 'Creates users';
28+
}
29+
30+
// ...
31+
}
32+
```
33+
34+
*After*
35+
```php
36+
use Symfony\Component\Console\Attribute\AsCommand;
37+
use Symfony\Component\Console\Command\Command;
38+
39+
#[AsCommand('app:create-user', 'Creates users')]
40+
class CreateUserCommand
41+
{
42+
// ...
43+
}
44+
```
45+
46+
* Ensure closures set via `Command::setCode()` method have proper parameter and return types
47+
48+
*Before*
49+
```php
50+
$command->setCode(function ($input, $output) {
51+
// ...
52+
});
53+
```
54+
55+
*After*
56+
```php
57+
use Symfony\Component\Console\Input\InputInterface;
58+
use Symfony\Component\Console\Output\OutputInterface;
59+
60+
$command->setCode(function (InputInterface $input, OutputInterface $output): int {
61+
// ...
62+
63+
return 0;
64+
});
65+
```
66+
67+
* Add method `isSilent()` to `OutputInterface`
68+
969
HttpClient
1070
----------
1171

src/Symfony/Component/Console/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
CHANGELOG
22
=========
33

4+
8.0
5+
---
6+
7+
* Remove methods `Command::getDefaultName()` and `Command::getDefaultDescription()` in favor of the `#[AsCommand]` attribute
8+
* Ensure closures set via `Command::setCode()` method have proper parameter and return types
9+
* Add method `isSilent()` to `OutputInterface`
10+
411
7.3
512
---
613

src/Symfony/Component/Console/Command/Command.php

Lines changed: 2 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -54,34 +54,6 @@ class Command implements SignalableCommandInterface
5454
private array $usages = [];
5555
private ?HelperSet $helperSet = null;
5656

57-
/**
58-
* @deprecated since Symfony 7.3, use the #[AsCommand] attribute instead
59-
*/
60-
public static function getDefaultName(): ?string
61-
{
62-
trigger_deprecation('symfony/console', '7.3', 'Method "%s()" is deprecated and will be removed in Symfony 8.0, use the #[AsCommand] attribute instead.', __METHOD__);
63-
64-
if ($attribute = (new \ReflectionClass(static::class))->getAttributes(AsCommand::class)) {
65-
return $attribute[0]->newInstance()->name;
66-
}
67-
68-
return null;
69-
}
70-
71-
/**
72-
* @deprecated since Symfony 7.3, use the #[AsCommand] attribute instead
73-
*/
74-
public static function getDefaultDescription(): ?string
75-
{
76-
trigger_deprecation('symfony/console', '7.3', 'Method "%s()" is deprecated and will be removed in Symfony 8.0, use the #[AsCommand] attribute instead.', __METHOD__);
77-
78-
if ($attribute = (new \ReflectionClass(static::class))->getAttributes(AsCommand::class)) {
79-
return $attribute[0]->newInstance()->description;
80-
}
81-
82-
return null;
83-
}
84-
8557
/**
8658
* @param string|null $name The name of the command; passing null means it must be set in configure()
8759
*
@@ -94,13 +66,7 @@ public function __construct(?string $name = null)
9466
$attribute = ((new \ReflectionClass(static::class))->getAttributes(AsCommand::class)[0] ?? null)?->newInstance();
9567

9668
if (null === $name) {
97-
if (self::class !== (new \ReflectionMethod($this, 'getDefaultName'))->class) {
98-
trigger_deprecation('symfony/console', '7.3', 'Overriding "Command::getDefaultName()" in "%s" is deprecated and will be removed in Symfony 8.0, use the #[AsCommand] attribute instead.', static::class);
99-
100-
$defaultName = static::getDefaultName();
101-
} else {
102-
$defaultName = $attribute?->name;
103-
}
69+
$defaultName = $attribute?->name;
10470
}
10571

10672
if (null === $name && null !== $name = $defaultName) {
@@ -119,15 +85,7 @@ public function __construct(?string $name = null)
11985
}
12086

12187
if ('' === $this->description) {
122-
if (self::class !== (new \ReflectionMethod($this, 'getDefaultDescription'))->class) {
123-
trigger_deprecation('symfony/console', '7.3', 'Overriding "Command::getDefaultDescription()" in "%s" is deprecated and will be removed in Symfony 8.0, use the #[AsCommand] attribute instead.', static::class);
124-
125-
$defaultDescription = static::getDefaultDescription();
126-
} else {
127-
$defaultDescription = $attribute?->description;
128-
}
129-
130-
$this->setDescription($defaultDescription ?? '');
88+
$this->setDescription($attribute?->description ?? '');
13189
}
13290

13391
if ('' === $this->help) {

src/Symfony/Component/Console/Command/InvokableCommand.php

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ class InvokableCommand implements SignalableCommandInterface
3333
private readonly \Closure $code;
3434
private readonly ?SignalableCommandInterface $signalableCommand;
3535
private readonly \ReflectionFunction $reflection;
36-
private bool $triggerDeprecations = false;
3736

3837
public function __construct(
3938
private readonly Command $command,
@@ -52,12 +51,6 @@ public function __invoke(InputInterface $input, OutputInterface $output): int
5251
$statusCode = ($this->code)(...$this->getParameters($input, $output));
5352

5453
if (!\is_int($statusCode)) {
55-
if ($this->triggerDeprecations) {
56-
trigger_deprecation('symfony/console', '7.3', \sprintf('Returning a non-integer value from the command "%s" is deprecated and will throw an exception in Symfony 8.0.', $this->command->getName()));
57-
58-
return 0;
59-
}
60-
6154
throw new \TypeError(\sprintf('The command "%s" must return an integer value in the "%s" method, but "%s" was returned.', $this->command->getName(), $this->reflection->getName(), get_debug_type($statusCode)));
6255
}
6356

@@ -87,8 +80,6 @@ private function getClosure(callable $code): \Closure
8780
return $code(...);
8881
}
8982

90-
$this->triggerDeprecations = true;
91-
9283
if (null !== (new \ReflectionFunction($code))->getClosureThis()) {
9384
return $code;
9485
}
@@ -124,12 +115,6 @@ private function getParameters(InputInterface $input, OutputInterface $output):
124115
$type = $parameter->getType();
125116

126117
if (!$type instanceof \ReflectionNamedType) {
127-
if ($this->triggerDeprecations) {
128-
trigger_deprecation('symfony/console', '7.3', \sprintf('Omitting the type declaration for the parameter "$%s" is deprecated and will throw an exception in Symfony 8.0.', $parameter->getName()));
129-
130-
continue;
131-
}
132-
133118
throw new LogicException(\sprintf('The parameter "$%s" must have a named type. Untyped, Union or Intersection types are not supported.', $parameter->getName()));
134119
}
135120

src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -61,14 +61,7 @@ public function process(ContainerBuilder $container): void
6161

6262
/** @var AsCommand|null $attribute */
6363
$attribute = ($r->getAttributes(AsCommand::class)[0] ?? null)?->newInstance();
64-
65-
if (Command::class !== (new \ReflectionMethod($class, 'getDefaultName'))->class) {
66-
trigger_deprecation('symfony/console', '7.3', 'Overriding "Command::getDefaultName()" in "%s" is deprecated and will be removed in Symfony 8.0, use the #[AsCommand] attribute instead.', $class);
67-
68-
$defaultName = $class::getDefaultName();
69-
} else {
70-
$defaultName = $attribute?->name;
71-
}
64+
$defaultName = $attribute?->name;
7265

7366
$aliases = str_replace('%', '%%', $tags[0]['command'] ?? $defaultName ?? '');
7467
$aliases = explode('|', $aliases);
@@ -124,17 +117,7 @@ public function process(ContainerBuilder $container): void
124117
$definition->addMethodCall('setHelp', [str_replace('%', '%%', $help)]);
125118
}
126119

127-
if (!$description) {
128-
if (Command::class !== (new \ReflectionMethod($class, 'getDefaultDescription'))->class) {
129-
trigger_deprecation('symfony/console', '7.3', 'Overriding "Command::getDefaultDescription()" in "%s" is deprecated and will be removed in Symfony 8.0, use the #[AsCommand] attribute instead.', $class);
130-
131-
$description = $class::getDefaultDescription();
132-
} else {
133-
$description = $attribute?->description;
134-
}
135-
}
136-
137-
if ($description) {
120+
if ($description ??= $attribute?->description) {
138121
$definition->addMethodCall('setDescription', [str_replace('%', '%%', $description)]);
139122

140123
$container->register('.'.$id.'.lazy', LazyCommand::class)

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@
1717
* OutputInterface is the interface implemented by all Output classes.
1818
*
1919
* @author Fabien Potencier <[email protected]>
20-
*
21-
* @method bool isSilent()
2220
*/
2321
interface OutputInterface
2422
{
@@ -64,6 +62,8 @@ public function setVerbosity(int $level): void;
6462
*/
6563
public function getVerbosity(): int;
6664

65+
public function isSilent(): bool;
66+
6767
/**
6868
* Returns whether verbosity is quiet (-q).
6969
*/

src/Symfony/Component/Console/Style/OutputStyle.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,7 @@ public function getFormatter(): OutputFormatterInterface
8080

8181
public function isSilent(): bool
8282
{
83-
// @deprecated since Symfony 7.2, change to $this->output->isSilent() in 8.0
84-
return method_exists($this->output, 'isSilent') ? $this->output->isSilent() : self::VERBOSITY_SILENT === $this->output->getVerbosity();
83+
return $this->output->isSilent();
8584
}
8685

8786
public function isQuiet(): bool

src/Symfony/Component/Console/Tests/Command/CommandTest.php

Lines changed: 0 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -448,18 +448,6 @@ public function testCommandAttribute()
448448
$this->assertSame(['f'], $command->getAliases());
449449
}
450450

451-
/**
452-
* @group legacy
453-
*/
454-
public function testCommandAttributeWithDeprecatedMethods()
455-
{
456-
$this->expectUserDeprecationMessage('Since symfony/console 7.3: Method "Symfony\Component\Console\Command\Command::getDefaultName()" is deprecated and will be removed in Symfony 8.0, use the #[AsCommand] attribute instead.');
457-
$this->expectUserDeprecationMessage('Since symfony/console 7.3: Method "Symfony\Component\Console\Command\Command::getDefaultDescription()" is deprecated and will be removed in Symfony 8.0, use the #[AsCommand] attribute instead.');
458-
459-
$this->assertSame('|foo|f', Php8Command::getDefaultName());
460-
$this->assertSame('desc', Php8Command::getDefaultDescription());
461-
}
462-
463451
public function testAttributeOverridesProperty()
464452
{
465453
$command = new MyAnnotatedCommand();
@@ -468,18 +456,6 @@ public function testAttributeOverridesProperty()
468456
$this->assertSame('This is a command I wrote all by myself', $command->getDescription());
469457
}
470458

471-
/**
472-
* @group legacy
473-
*/
474-
public function testAttributeOverridesPropertyWithDeprecatedMethods()
475-
{
476-
$this->expectUserDeprecationMessage('Since symfony/console 7.3: Method "Symfony\Component\Console\Command\Command::getDefaultName()" is deprecated and will be removed in Symfony 8.0, use the #[AsCommand] attribute instead.');
477-
$this->expectUserDeprecationMessage('Since symfony/console 7.3: Method "Symfony\Component\Console\Command\Command::getDefaultDescription()" is deprecated and will be removed in Symfony 8.0, use the #[AsCommand] attribute instead.');
478-
479-
$this->assertSame('my:command', MyAnnotatedCommand::getDefaultName());
480-
$this->assertSame('This is a command I wrote all by myself', MyAnnotatedCommand::getDefaultDescription());
481-
}
482-
483459
public function testDefaultCommand()
484460
{
485461
$apl = new Application();
@@ -493,29 +469,6 @@ public function testDefaultCommand()
493469

494470
$this->assertEquals('foo2', $property->getValue($apl));
495471
}
496-
497-
/**
498-
* @group legacy
499-
*/
500-
public function testDeprecatedMethods()
501-
{
502-
$this->expectUserDeprecationMessage('Since symfony/console 7.3: Overriding "Command::getDefaultName()" in "Symfony\Component\Console\Tests\Command\FooCommand" is deprecated and will be removed in Symfony 8.0, use the #[AsCommand] attribute instead.');
503-
$this->expectUserDeprecationMessage('Since symfony/console 7.3: Overriding "Command::getDefaultDescription()" in "Symfony\Component\Console\Tests\Command\FooCommand" is deprecated and will be removed in Symfony 8.0, use the #[AsCommand] attribute instead.');
504-
505-
new FooCommand();
506-
}
507-
508-
/**
509-
* @group legacy
510-
*/
511-
public function testDeprecatedNonIntegerReturnTypeFromClosureCode()
512-
{
513-
$this->expectUserDeprecationMessage('Since symfony/console 7.3: Returning a non-integer value from the command "foo" is deprecated and will throw an exception in Symfony 8.0.');
514-
515-
$command = new Command('foo');
516-
$command->setCode(function () {});
517-
$command->run(new ArrayInput([]), new NullOutput());
518-
}
519472
}
520473

521474
// In order to get an unbound closure, we should create it outside a class
@@ -546,16 +499,3 @@ class MyAnnotatedCommand extends Command
546499

547500
protected static $defaultDescription = 'This description should be ignored.';
548501
}
549-
550-
class FooCommand extends Command
551-
{
552-
public static function getDefaultName(): ?string
553-
{
554-
return 'foo';
555-
}
556-
557-
public static function getDefaultDescription(): ?string
558-
{
559-
return 'foo description';
560-
}
561-
}

src/Symfony/Component/Console/composer.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
],
1818
"require": {
1919
"php": ">=8.4",
20-
"symfony/deprecation-contracts": "^2.5|^3",
2120
"symfony/polyfill-mbstring": "^1.0",
2221
"symfony/service-contracts": "^2.5|^3",
2322
"symfony/string": "^7.4|^8.0"

src/Symfony/Component/Scheduler/DependencyInjection/AddScheduleMessengerPass.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public function process(ContainerBuilder $container): void
6363
if ($serviceDefinition->hasTag('console.command')) {
6464
/** @var AsCommand|null $attribute */
6565
$attribute = ($container->getReflectionClass($serviceDefinition->getClass())->getAttributes(AsCommand::class)[0] ?? null)?->newInstance();
66-
$message = new Definition(RunCommandMessage::class, [$attribute?->name ?? $serviceDefinition->getClass()::getDefaultName().(empty($tagAttributes['arguments']) ? '' : " {$tagAttributes['arguments']}")]);
66+
$message = new Definition(RunCommandMessage::class, [$attribute?->name.(empty($tagAttributes['arguments']) ? '' : " {$tagAttributes['arguments']}")]);
6767
} else {
6868
$message = new Definition(ServiceCallMessage::class, [$serviceId, $tagAttributes['method'] ?? '__invoke', (array) ($tagAttributes['arguments'] ?? [])]);
6969
}

0 commit comments

Comments
 (0)