• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

keradus / PHP-CS-Fixer / 17678835382

12 Sep 2025 03:24PM UTC coverage: 94.69% (-0.06%) from 94.75%
17678835382

push

github

keradus
fix typo

1 of 1 new or added line in 1 file covered. (100.0%)

1042 existing lines in 177 files now uncovered.

28424 of 30018 relevant lines covered (94.69%)

45.5 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

83.08
/src/Console/Command/SelfUpdateCommand.php
1
<?php
2

3
declare(strict_types=1);
4

5
/*
6
 * This file is part of PHP CS Fixer.
7
 *
8
 * (c) Fabien Potencier <fabien@symfony.com>
9
 *     Dariusz Rumiński <dariusz.ruminski@gmail.com>
10
 *
11
 * This source file is subject to the MIT license that is bundled
12
 * with this source code in the file LICENSE.
13
 */
14

15
namespace PhpCsFixer\Console\Command;
16

17
use PhpCsFixer\Console\Application;
18
use PhpCsFixer\Console\SelfUpdate\NewVersionCheckerInterface;
19
use PhpCsFixer\PharCheckerInterface;
20
use PhpCsFixer\Preg;
21
use PhpCsFixer\ToolInfoInterface;
22
use Symfony\Component\Console\Attribute\AsCommand;
23
use Symfony\Component\Console\Command\Command;
24
use Symfony\Component\Console\Input\InputInterface;
25
use Symfony\Component\Console\Input\InputOption;
26
use Symfony\Component\Console\Output\ConsoleOutputInterface;
27
use Symfony\Component\Console\Output\OutputInterface;
28

29
/**
30
 * @author Igor Wiedler <igor@wiedler.ch>
31
 * @author Stephane PY <py.stephane1@gmail.com>
32
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
33
 * @author Dariusz Rumiński <dariusz.ruminski@gmail.com>
34
 *
35
 * @internal
36
 *
37
 * @no-named-arguments Parameter names are not covered by the backward compatibility promise.
38
 */
39
#[AsCommand(name: 'self-update', description: 'Update php-cs-fixer.phar to the latest stable version.')]
40
final class SelfUpdateCommand extends Command
41
{
42
    /** @TODO PHP 8.0 - remove the property */
43
    protected static $defaultName = 'self-update';
44

45
    /** @TODO PHP 8.0 - remove the property */
46
    protected static $defaultDescription = 'Update php-cs-fixer.phar to the latest stable version.';
47

48
    private NewVersionCheckerInterface $versionChecker;
49

50
    private ToolInfoInterface $toolInfo;
51

52
    private PharCheckerInterface $pharChecker;
53

54
    public function __construct(
55
        NewVersionCheckerInterface $versionChecker,
56
        ToolInfoInterface $toolInfo,
57
        PharCheckerInterface $pharChecker
58
    ) {
59
        parent::__construct();
60✔
60

61
        $this->versionChecker = $versionChecker;
60✔
62
        $this->toolInfo = $toolInfo;
60✔
63
        $this->pharChecker = $pharChecker;
60✔
64
    }
65

66
    /**
67
     * {@inheritdoc}
68
     *
69
     * Override here to only generate the help copy when used.
70
     */
71
    public function getHelp(): string
72
    {
73
        return <<<'EOT'
74
            The <info>%command.name%</info> command replace your php-cs-fixer.phar by the
75
            latest version released on:
76
            <comment>https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/releases</comment>
77

78
            <info>$ php php-cs-fixer.phar %command.name%</info>
79

80
            EOT;
81
    }
82

83
    protected function configure(): void
84
    {
85
        $this
60✔
86
            ->setAliases(['selfupdate'])
60✔
87
            ->setDefinition(
60✔
88
                [
60✔
89
                    new InputOption('--force', '-f', InputOption::VALUE_NONE, 'Force update to next major version if available.'),
60✔
90
                ]
60✔
91
            )
60✔
92
        ;
60✔
93
    }
94

95
    protected function execute(InputInterface $input, OutputInterface $output): int
96
    {
97
        if ($output instanceof ConsoleOutputInterface) {
58✔
UNCOV
98
            $stdErr = $output->getErrorOutput();
×
UNCOV
99
            $stdErr->writeln(Application::getAboutWithRuntime(true));
×
100
        }
101

102
        if (!$this->toolInfo->isInstalledAsPhar()) {
58✔
103
            $output->writeln('<error>Self-update is available only for PHAR version.</error>');
6✔
104

105
            return 1;
6✔
106
        }
107

108
        $currentVersion = $this->getApplication()->getVersion();
52✔
109
        Preg::match('/^v?(?<major>\d+)\./', $currentVersion, $matches);
52✔
110
        $currentMajor = (int) $matches['major'];
52✔
111

112
        try {
113
            $latestVersion = $this->versionChecker->getLatestVersion();
52✔
114
            $latestVersionOfCurrentMajor = $this->versionChecker->getLatestVersionOfMajor($currentMajor);
40✔
115
        } catch (\Exception $exception) {
18✔
116
            $output->writeln(\sprintf(
18✔
117
                '<error>Unable to determine newest version: %s</error>',
18✔
118
                $exception->getMessage()
18✔
119
            ));
18✔
120

121
            return 1;
18✔
122
        }
123

124
        if (1 !== $this->versionChecker->compareVersions($latestVersion, $currentVersion)) {
34✔
125
            $output->writeln('<info>PHP CS Fixer is already up-to-date.</info>');
20✔
126

127
            return 0;
20✔
128
        }
129

130
        $remoteTag = $latestVersion;
14✔
131

132
        if (
133
            0 !== $this->versionChecker->compareVersions($latestVersionOfCurrentMajor, $latestVersion)
14✔
134
            && true !== $input->getOption('force')
14✔
135
        ) {
136
            $output->writeln(\sprintf('<info>A new major version of PHP CS Fixer is available</info> (<comment>%s</comment>)', $latestVersion));
4✔
137
            $output->writeln(\sprintf('<info>Before upgrading please read</info> https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/blob/%s/UPGRADE-v%s.md', $latestVersion, $currentMajor + 1));
4✔
138
            $output->writeln('<info>If you are ready to upgrade run this command with</info> <comment>-f</comment>');
4✔
139
            $output->writeln('<info>Checking for new minor/patch version...</info>');
4✔
140

141
            if (1 !== $this->versionChecker->compareVersions($latestVersionOfCurrentMajor, $currentVersion)) {
4✔
142
                $output->writeln('<info>No minor update for PHP CS Fixer.</info>');
2✔
143

144
                return 0;
2✔
145
            }
146

147
            $remoteTag = $latestVersionOfCurrentMajor;
2✔
148
        }
149

150
        $localFilename = $_SERVER['argv'][0];
12✔
151
        $realPath = realpath($localFilename);
12✔
152
        if (false !== $realPath) {
12✔
UNCOV
153
            $localFilename = $realPath;
×
154
        }
155

156
        if (!is_writable($localFilename)) {
12✔
157
            $output->writeln(\sprintf('<error>No permission to update</error> "%s" <error>file.</error>', $localFilename));
×
158

UNCOV
159
            return 1;
×
160
        }
161

162
        $tempFilename = \dirname($localFilename).'/'.basename($localFilename, '.phar').'-tmp.phar';
12✔
163
        $remoteFilename = $this->toolInfo->getPharDownloadUri($remoteTag);
12✔
164

165
        if (false === @copy($remoteFilename, $tempFilename)) {
12✔
166
            $output->writeln(\sprintf('<error>Unable to download new version</error> %s <error>from the server.</error>', $remoteTag));
×
167

UNCOV
168
            return 1;
×
169
        }
170

171
        chmod($tempFilename, 0777 & ~umask());
12✔
172

173
        $pharInvalidityReason = $this->pharChecker->checkFileValidity($tempFilename);
12✔
174
        if (null !== $pharInvalidityReason) {
12✔
175
            unlink($tempFilename);
×
UNCOV
176
            $output->writeln(\sprintf('<error>The download of</error> %s <error>is corrupt (%s).</error>', $remoteTag, $pharInvalidityReason));
×
177
            $output->writeln('<error>Please re-run the "self-update" command to try again.</error>');
×
178

UNCOV
179
            return 1;
×
180
        }
181

182
        rename($tempFilename, $localFilename);
12✔
183

184
        $output->writeln(\sprintf('<info>PHP CS Fixer updated</info> (<comment>%s</comment> -> <comment>%s</comment>)', $currentVersion, $remoteTag));
12✔
185

186
        return 0;
12✔
187
    }
188
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc