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

PHP-CS-Fixer / PHP-CS-Fixer / 3721300657

pending completion
3721300657

push

github

GitHub
minor: Follow PSR12 ordered imports in Symfony ruleset (#6712)

9 of 9 new or added lines in 2 files covered. (100.0%)

22674 of 24281 relevant lines covered (93.38%)

39.08 hits per line

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

61.72
/src/Console/Command/FixCommand.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\Config;
18
use PhpCsFixer\ConfigInterface;
19
use PhpCsFixer\ConfigurationException\InvalidConfigurationException;
20
use PhpCsFixer\Console\ConfigurationResolver;
21
use PhpCsFixer\Console\Output\ErrorOutput;
22
use PhpCsFixer\Console\Output\NullOutput;
23
use PhpCsFixer\Console\Output\ProcessOutput;
24
use PhpCsFixer\Console\Report\FixReport\ReportSummary;
25
use PhpCsFixer\Error\ErrorsManager;
26
use PhpCsFixer\Runner\Runner;
27
use PhpCsFixer\ToolInfoInterface;
28
use Symfony\Component\Console\Attribute\AsCommand;
29
use Symfony\Component\Console\Command\Command;
30
use Symfony\Component\Console\Input\InputArgument;
31
use Symfony\Component\Console\Input\InputInterface;
32
use Symfony\Component\Console\Input\InputOption;
33
use Symfony\Component\Console\Output\ConsoleOutputInterface;
34
use Symfony\Component\Console\Output\OutputInterface;
35
use Symfony\Component\Console\Terminal;
36
use Symfony\Component\EventDispatcher\EventDispatcher;
37
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
38
use Symfony\Component\Stopwatch\Stopwatch;
39

40
/**
41
 * @author Fabien Potencier <fabien@symfony.com>
42
 * @author Dariusz Rumiński <dariusz.ruminski@gmail.com>
43
 *
44
 * @internal
45
 */
46
#[AsCommand(name: 'fix')]
47
final class FixCommand extends Command
48
{
49
    /**
50
     * @var string
51
     */
52
    protected static $defaultName = 'fix';
53

54
    private EventDispatcherInterface $eventDispatcher;
55

56
    private ErrorsManager $errorsManager;
57

58
    private Stopwatch $stopwatch;
59

60
    private ConfigInterface $defaultConfig;
61

62
    private ToolInfoInterface $toolInfo;
63

64
    public function __construct(ToolInfoInterface $toolInfo)
65
    {
66
        parent::__construct();
2✔
67

68
        $this->eventDispatcher = new EventDispatcher();
2✔
69
        $this->errorsManager = new ErrorsManager();
2✔
70
        $this->stopwatch = new Stopwatch();
2✔
71
        $this->defaultConfig = new Config();
2✔
72
        $this->toolInfo = $toolInfo;
2✔
73
    }
74

75
    /**
76
     * {@inheritdoc}
77
     *
78
     * Override here to only generate the help copy when used.
79
     */
80
    public function getHelp(): string
81
    {
82
        return <<<'EOF'
83
The <info>%command.name%</info> command tries to fix as much coding standards
84
problems as possible on a given file or files in a given directory and its subdirectories:
85

86
    <info>$ php %command.full_name% /path/to/dir</info>
87
    <info>$ php %command.full_name% /path/to/file</info>
88

89
By default <comment>--path-mode</comment> is set to `override`, which means, that if you specify the path to a file or a directory via
90
command arguments, then the paths provided to a `Finder` in config file will be ignored. You can use <comment>--path-mode=intersection</comment>
91
to merge paths from the config file and from the argument:
92

93
    <info>$ php %command.full_name% --path-mode=intersection /path/to/dir</info>
94

95
The <comment>--format</comment> option for the output format. Supported formats are `txt` (default one), `json`, `xml`, `checkstyle`, `junit` and `gitlab`.
96

97
NOTE: the output for the following formats are generated in accordance with schemas
98

99
* `checkstyle` follows the common `"checkstyle" XML schema </doc/schemas/fix/checkstyle.xsd>`_
100
* `json` follows the `own JSON schema </doc/schemas/fix/schema.json>`_
101
* `junit` follows the `JUnit XML schema from Jenkins </doc/schemas/fix/junit-10.xsd>`_
102
* `xml` follows the `own XML schema </doc/schemas/fix/xml.xsd>`_
103

104
The <comment>--quiet</comment> Do not output any message.
105

106
The <comment>--verbose</comment> option will show the applied rules. When using the `txt` format it will also display progress notifications.
107

108
NOTE: if there is an error like "errors reported during linting after fixing", you can use this to be even more verbose for debugging purpose
109

110
* `-v`: verbose
111
* `-vv`: very verbose
112
* `-vvv`: debug
113

114
The <comment>--rules</comment> option limits the rules to apply to the
115
project:
116

117
EOF. /* @TODO: 4.0 - change to @PER */ <<<'EOF'
118

119
    <info>$ php %command.full_name% /path/to/project --rules=@PSR12</info>
120

121
By default the PSR-12 rules are used.
122

123
The <comment>--rules</comment> option lets you choose the exact rules to
124
apply (the rule names must be separated by a comma):
125

126
    <info>$ php %command.full_name% /path/to/dir --rules=line_ending,full_opening_tag,indentation_type</info>
127

128
You can also exclude the rules you don't want by placing a dash in front of the rule name, if this is more convenient,
129
using <comment>-name_of_fixer</comment>:
130

131
    <info>$ php %command.full_name% /path/to/dir --rules=-full_opening_tag,-indentation_type</info>
132

133
When using combinations of exact and exclude rules, applying exact rules along with above excluded results:
134

135
    <info>$ php %command.full_name% /path/to/project --rules=@Symfony,-@PSR1,-blank_line_before_statement,strict_comparison</info>
136

137
Complete configuration for rules can be supplied using a `json` formatted string.
138

139
    <info>$ php %command.full_name% /path/to/project --rules='{"concat_space": {"spacing": "none"}}'</info>
140

141
The <comment>--dry-run</comment> flag will run the fixer without making changes to your files.
142

143
The <comment>--diff</comment> flag can be used to let the fixer output all the changes it makes.
144

145
The <comment>--allow-risky</comment> option (pass `yes` or `no`) allows you to set whether risky rules may run. Default value is taken from config file.
146
A rule is considered risky if it could change code behaviour. By default no risky rules are run.
147

148
The <comment>--stop-on-violation</comment> flag stops the execution upon first file that needs to be fixed.
149

150
The <comment>--show-progress</comment> option allows you to choose the way process progress is rendered:
151

152
* <comment>none</comment>: disables progress output;
153
* <comment>dots</comment>: multiline progress output with number of files and percentage on each line.
154

155
If the option is not provided, it defaults to <comment>dots</comment> unless a config file that disables output is used, in which case it defaults to <comment>none</comment>. This option has no effect if the verbosity of the command is less than <comment>verbose</comment>.
156

157
    <info>$ php %command.full_name% --verbose --show-progress=dots</info>
158

159
By using <command>--using-cache</command> option with `yes` or `no` you can set if the caching
160
mechanism should be used.
161

162
The command can also read from standard input, in which case it won't
163
automatically fix anything:
164

165
    <info>$ cat foo.php | php %command.full_name% --diff -</info>
166

167
Finally, if you don't need BC kept on CLI level, you might use `PHP_CS_FIXER_FUTURE_MODE` to start using options that
168
would be default in next MAJOR release and to forbid using deprecated configuration:
169

170
    <info>$ PHP_CS_FIXER_FUTURE_MODE=1 php %command.full_name% -v --diff</info>
171

172
Exit code
173
---------
174

175
Exit code of the fix command is built using following bit flags:
176

177
*  0 - OK.
178
*  1 - General error (or PHP minimal requirement not matched).
179
*  4 - Some files have invalid syntax (only in dry-run mode).
180
*  8 - Some files need fixing (only in dry-run mode).
181
* 16 - Configuration error of the application.
182
* 32 - Configuration error of a Fixer.
183
* 64 - Exception raised within the application.
184

185
EOF
186
        ;
187
    }
188

189
    /**
190
     * {@inheritdoc}
191
     */
192
    protected function configure(): void
193
    {
194
        $this
2✔
195
            ->setDefinition(
2✔
196
                [
2✔
197
                    new InputArgument('path', InputArgument::IS_ARRAY, 'The path.'),
2✔
198
                    new InputOption('path-mode', '', InputOption::VALUE_REQUIRED, 'Specify path mode (can be override or intersection).', ConfigurationResolver::PATH_MODE_OVERRIDE),
2✔
199
                    new InputOption('allow-risky', '', InputOption::VALUE_REQUIRED, 'Are risky fixers allowed (can be yes or no).'),
2✔
200
                    new InputOption('config', '', InputOption::VALUE_REQUIRED, 'The path to a .php-cs-fixer.php file.'),
2✔
201
                    new InputOption('dry-run', '', InputOption::VALUE_NONE, 'Only shows which files would have been modified.'),
2✔
202
                    new InputOption('rules', '', InputOption::VALUE_REQUIRED, 'The rules.'),
2✔
203
                    new InputOption('using-cache', '', InputOption::VALUE_REQUIRED, 'Does cache should be used (can be yes or no).'),
2✔
204
                    new InputOption('cache-file', '', InputOption::VALUE_REQUIRED, 'The path to the cache file.'),
2✔
205
                    new InputOption('diff', '', InputOption::VALUE_NONE, 'Also produce diff for each file.'),
2✔
206
                    new InputOption('format', '', InputOption::VALUE_REQUIRED, 'To output results in other formats.'),
2✔
207
                    new InputOption('stop-on-violation', '', InputOption::VALUE_NONE, 'Stop execution on first violation.'),
2✔
208
                    new InputOption('show-progress', '', InputOption::VALUE_REQUIRED, 'Type of progress indicator (none, dots).'),
2✔
209
                ]
2✔
210
            )
2✔
211
            ->setDescription('Fixes a directory or a file.')
2✔
212
        ;
2✔
213
    }
214

215
    /**
216
     * {@inheritdoc}
217
     */
218
    protected function execute(InputInterface $input, OutputInterface $output): int
219
    {
220
        $verbosity = $output->getVerbosity();
2✔
221

222
        $passedConfig = $input->getOption('config');
2✔
223
        $passedRules = $input->getOption('rules');
2✔
224

225
        if (null !== $passedConfig && null !== $passedRules) {
2✔
226
            throw new InvalidConfigurationException('Passing both `--config` and `--rules` options is not allowed.');
×
227
        }
228

229
        $resolver = new ConfigurationResolver(
2✔
230
            $this->defaultConfig,
2✔
231
            [
2✔
232
                'allow-risky' => $input->getOption('allow-risky'),
2✔
233
                'config' => $passedConfig,
2✔
234
                'dry-run' => $input->getOption('dry-run'),
2✔
235
                'rules' => $passedRules,
2✔
236
                'path' => $input->getArgument('path'),
2✔
237
                'path-mode' => $input->getOption('path-mode'),
2✔
238
                'using-cache' => $input->getOption('using-cache'),
2✔
239
                'cache-file' => $input->getOption('cache-file'),
2✔
240
                'format' => $input->getOption('format'),
2✔
241
                'diff' => $input->getOption('diff'),
2✔
242
                'stop-on-violation' => $input->getOption('stop-on-violation'),
2✔
243
                'verbosity' => $verbosity,
2✔
244
                'show-progress' => $input->getOption('show-progress'),
2✔
245
            ],
2✔
246
            getcwd(),
2✔
247
            $this->toolInfo
2✔
248
        );
2✔
249

250
        $reporter = $resolver->getReporter();
2✔
251

252
        $stdErr = $output instanceof ConsoleOutputInterface
2✔
253
            ? $output->getErrorOutput()
×
254
            : ('txt' === $reporter->getFormat() ? $output : null)
2✔
255
        ;
2✔
256

257
        if (null !== $stdErr) {
2✔
258
            if (OutputInterface::VERBOSITY_VERBOSE <= $verbosity) {
2✔
259
                $stdErr->writeln($this->getApplication()->getLongVersion());
2✔
260
            }
261

262
            $configFile = $resolver->getConfigFile();
2✔
263
            $stdErr->writeln(sprintf('Loaded config <comment>%s</comment>%s.', $resolver->getConfig()->getName(), null === $configFile ? '' : ' from "'.$configFile.'"'));
2✔
264

265
            if ($resolver->getUsingCache()) {
2✔
266
                $cacheFile = $resolver->getCacheFile();
×
267

268
                if (is_file($cacheFile)) {
×
269
                    $stdErr->writeln(sprintf('Using cache file "%s".', $cacheFile));
×
270
                }
271
            }
272
        }
273

274
        $progressType = $resolver->getProgress();
1✔
275
        $finder = $resolver->getFinder();
1✔
276

277
        if (null !== $stdErr && $resolver->configFinderIsOverridden()) {
1✔
278
            $stdErr->writeln(
1✔
279
                sprintf($stdErr->isDecorated() ? '<bg=yellow;fg=black;>%s</>' : '%s', 'Paths from configuration file have been overridden by paths provided as command arguments.')
1✔
280
            );
1✔
281
        }
282

283
        if ('none' === $progressType || null === $stdErr) {
1✔
284
            $progressOutput = new NullOutput();
1✔
285
        } else {
286
            $finder = new \ArrayIterator(iterator_to_array($finder));
×
287
            $progressOutput = new ProcessOutput(
×
288
                $stdErr,
×
289
                $this->eventDispatcher,
×
290
                (new Terminal())->getWidth(),
×
291
                \count($finder)
×
292
            );
×
293
        }
294

295
        $runner = new Runner(
1✔
296
            $finder,
1✔
297
            $resolver->getFixers(),
1✔
298
            $resolver->getDiffer(),
1✔
299
            'none' !== $progressType ? $this->eventDispatcher : null,
1✔
300
            $this->errorsManager,
1✔
301
            $resolver->getLinter(),
1✔
302
            $resolver->isDryRun(),
1✔
303
            $resolver->getCacheManager(),
1✔
304
            $resolver->getDirectory(),
1✔
305
            $resolver->shouldStopOnViolation()
1✔
306
        );
1✔
307

308
        $this->stopwatch->start('fixFiles');
×
309
        $changed = $runner->fix();
×
310
        $this->stopwatch->stop('fixFiles');
×
311

312
        $progressOutput->printLegend();
×
313

314
        $fixEvent = $this->stopwatch->getEvent('fixFiles');
×
315

316
        $reportSummary = new ReportSummary(
×
317
            $changed,
×
318
            \count($finder),
×
319
            $fixEvent->getDuration(),
×
320
            $fixEvent->getMemory(),
×
321
            OutputInterface::VERBOSITY_VERBOSE <= $verbosity,
×
322
            $resolver->isDryRun(),
×
323
            $output->isDecorated()
×
324
        );
×
325

326
        $output->isDecorated()
×
327
            ? $output->write($reporter->generate($reportSummary))
×
328
            : $output->write($reporter->generate($reportSummary), false, OutputInterface::OUTPUT_RAW)
×
329
        ;
×
330

331
        $invalidErrors = $this->errorsManager->getInvalidErrors();
×
332
        $exceptionErrors = $this->errorsManager->getExceptionErrors();
×
333
        $lintErrors = $this->errorsManager->getLintErrors();
×
334

335
        if (null !== $stdErr) {
×
336
            $errorOutput = new ErrorOutput($stdErr);
×
337

338
            if (\count($invalidErrors) > 0) {
×
339
                $errorOutput->listErrors('linting before fixing', $invalidErrors);
×
340
            }
341

342
            if (\count($exceptionErrors) > 0) {
×
343
                $errorOutput->listErrors('fixing', $exceptionErrors);
×
344
            }
345

346
            if (\count($lintErrors) > 0) {
×
347
                $errorOutput->listErrors('linting after fixing', $lintErrors);
×
348
            }
349
        }
350

351
        $exitStatusCalculator = new FixCommandExitStatusCalculator();
×
352

353
        return $exitStatusCalculator->calculate(
×
354
            $resolver->isDryRun(),
×
355
            \count($changed) > 0,
×
356
            \count($invalidErrors) > 0,
×
357
            \count($exceptionErrors) > 0,
×
358
            \count($lintErrors) > 0
×
359
        );
×
360
    }
361
}
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