Skip to content

Commit d6518fe

Browse files
committed
style: Apply code style fixes
1 parent d255819 commit d6518fe

9 files changed

Lines changed: 1060 additions & 163 deletions

File tree

src/Console/Command/CodeStyleCommand.php

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,14 @@
1818

1919
namespace FastForward\DevTools\Console\Command;
2020

21+
use Composer\Command\BaseCommand;
22+
use FastForward\DevTools\Process\ProcessBuilderInterface;
23+
use FastForward\DevTools\Process\ProcessQueueInterface;
24+
use Symfony\Component\Config\FileLocatorInterface;
2125
use Symfony\Component\Console\Attribute\AsCommand;
2226
use Symfony\Component\Console\Input\InputInterface;
2327
use Symfony\Component\Console\Input\InputOption;
2428
use Symfony\Component\Console\Output\OutputInterface;
25-
use Symfony\Component\Process\Process;
2629

2730
/**
2831
* Represents the command responsible for checking and fixing code style issues.
@@ -33,13 +36,33 @@
3336
description: 'Checks and fixes code style issues using EasyCodingStandard and Composer Normalize.',
3437
help: 'This command runs EasyCodingStandard and Composer Normalize to check and fix code style issues.'
3538
)]
36-
final class CodeStyleCommand extends AbstractCommand
39+
final class CodeStyleCommand extends BaseCommand
3740
{
3841
/**
3942
* @var string the default configuration file used for EasyCodingStandard
4043
*/
4144
public const string CONFIG = 'ecs.php';
4245

46+
/**
47+
* Constructs a new command instance responsible for orchestrating code style checks.
48+
*
49+
* The provided collaborators SHALL be used to locate the ECS configuration,
50+
* build process definitions, and execute the resulting process queue. These
51+
* dependencies MUST be valid service instances capable of supporting the
52+
* command lifecycle expected by this class.
53+
*
54+
* @param FileLocatorInterface $fileLocator locates the configuration file required by EasyCodingStandard
55+
* @param ProcessBuilderInterface $processBuilder builds the process instances used to execute Composer and ECS commands
56+
* @param ProcessQueueInterface $processQueue queues and executes the generated processes in the required order
57+
*/
58+
public function __construct(
59+
private readonly FileLocatorInterface $fileLocator,
60+
private readonly ProcessBuilderInterface $processBuilder,
61+
private readonly ProcessQueueInterface $processQueue,
62+
) {
63+
parent::__construct();
64+
}
65+
4366
/**
4467
* Configures the current command.
4568
*
@@ -74,20 +97,30 @@ protected function execute(InputInterface $input, OutputInterface $output): int
7497
{
7598
$output->writeln('<info>Running code style checks and fixes...</info>');
7699

77-
$command = new Process(['composer', 'update', '--lock', '--quiet']);
100+
$composerUpdate = $this->processBuilder
101+
->withArgument('--lock')
102+
->withArgument('--quiet')
103+
->build('composer update');
104+
105+
$composerNormalize = $this->processBuilder
106+
->withArgument('--ansi')
107+
->withArgument($input->getOption('fix') ? '--quiet' : '--dry-run')
108+
->build('composer normalize');
78109

79-
parent::runProcess($command, $output);
110+
$processBuilder = $this->processBuilder
111+
->withArgument('--no-progress-bar')
112+
->withArgument('--config', $this->fileLocator->locate(self::CONFIG));
80113

81-
$command = new Process(['composer', 'normalize', $input->getOption('fix') ? '--quiet' : '--dry-run']);
114+
if ($input->getOption('fix')) {
115+
$processBuilder = $processBuilder->withArgument('--fix');
116+
}
82117

83-
parent::runProcess($command, $output);
118+
$ecs = $processBuilder->build('vendor/bin/ecs');
84119

85-
$command = new Process([
86-
$this->getAbsolutePath('vendor/bin/ecs'),
87-
'--config=' . parent::getConfigFile(self::CONFIG),
88-
$input->getOption('fix') ? '--fix' : '--clear-cache',
89-
]);
120+
$this->processQueue->add($composerUpdate);
121+
$this->processQueue->add($composerNormalize);
122+
$this->processQueue->add($ecs);
90123

91-
return parent::runProcess($command, $output);
124+
return $this->processQueue->run($output);
92125
}
93126
}

src/Process/ProcessBuilder.php

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* This file is part of fast-forward/dev-tools.
7+
*
8+
* This source file is subject to the license bundled
9+
* with this source code in the file LICENSE.
10+
*
11+
* @copyright Copyright (c) 2026 Felipe Sayão Lobato Abreu <github@mentordosnerds.com>
12+
* @license https://opensource.org/licenses/MIT MIT License
13+
*
14+
* @see https://github.com/php-fast-forward/dev-tools
15+
* @see https://github.com/php-fast-forward
16+
* @see https://datatracker.ietf.org/doc/html/rfc2119
17+
*/
18+
19+
namespace FastForward\DevTools\Process;
20+
21+
use Symfony\Component\Process\Process;
22+
23+
/**
24+
* Builds immutable process definitions from a command and a collection of arguments.
25+
*
26+
* This builder SHALL preserve previously supplied arguments by returning a new
27+
* instance on each mutation-like operation. Implementations of this concrete
28+
* builder MUST keep argument ordering stable so that the generated process
29+
* reflects the exact sequence in which arguments were provided.
30+
*/
31+
final readonly class ProcessBuilder implements ProcessBuilderInterface
32+
{
33+
/**
34+
* Creates a new immutable process builder instance.
35+
*
36+
* The provided arguments SHALL be stored in the same order in which they are
37+
* received and MUST be used when building the final process instance.
38+
*
39+
* @param list<string> $arguments the arguments already collected by the builder
40+
*/
41+
public function __construct(
42+
private array $arguments = [],
43+
) {}
44+
45+
/**
46+
* Returns a new builder instance with an additional argument appended.
47+
*
48+
* When a value is provided, the argument SHALL be normalized to the
49+
* "{argument}={value}" format before being appended. When no value is
50+
* provided, the raw argument token MUST be appended as-is.
51+
*
52+
* This method MUST NOT mutate the current builder instance and SHALL return
53+
* a new instance containing the accumulated arguments.
54+
*
55+
* @param string $argument the argument name or token to append
56+
* @param string|null $value the optional value associated with the argument
57+
*
58+
* @return ProcessBuilderInterface a new builder instance containing the appended argument
59+
*/
60+
public function withArgument(string $argument, ?string $value = null): ProcessBuilderInterface
61+
{
62+
if (null !== $value) {
63+
$argument = \sprintf('%s=%s', $argument, $value);
64+
}
65+
66+
return new self([...$this->arguments, $argument]);
67+
}
68+
69+
/**
70+
* Returns the arguments currently collected by the builder.
71+
*
72+
* The returned list SHALL preserve insertion order and MAY be used for
73+
* inspection, debugging, or testing purposes.
74+
*
75+
* @return list<string> the collected process arguments
76+
*/
77+
public function getArguments(): array
78+
{
79+
return $this->arguments;
80+
}
81+
82+
/**
83+
* Builds a process instance for the specified command.
84+
*
85+
* The command string SHALL be split into tokens using a space separator and
86+
* combined with all previously collected builder arguments. The resulting
87+
* process MUST preserve the final token order exactly as assembled by this
88+
* method.
89+
*
90+
* @param string $command the base command used to initialize the process
91+
*
92+
* @return Process the configured process instance ready for execution
93+
*/
94+
public function build(string $command): Process
95+
{
96+
return new Process([...explode(' ', $command), ...$this->arguments]);
97+
}
98+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* This file is part of fast-forward/dev-tools.
7+
*
8+
* This source file is subject to the license bundled
9+
* with this source code in the file LICENSE.
10+
*
11+
* @copyright Copyright (c) 2026 Felipe Sayão Lobato Abreu <github@mentordosnerds.com>
12+
* @license https://opensource.org/licenses/MIT MIT License
13+
*
14+
* @see https://github.com/php-fast-forward/dev-tools
15+
* @see https://github.com/php-fast-forward
16+
* @see https://datatracker.ietf.org/doc/html/rfc2119
17+
*/
18+
19+
namespace FastForward\DevTools\Process;
20+
21+
use Symfony\Component\Process\Process;
22+
23+
/**
24+
* Defines a fluent builder responsible for constructing process instances.
25+
*
26+
* Implementations MUST preserve the builder state consistently across chained
27+
* calls and SHALL return a process configured according to all previously
28+
* supplied arguments when build() is invoked.
29+
*/
30+
interface ProcessBuilderInterface
31+
{
32+
/**
33+
* Adds an argument to the process being built.
34+
*
35+
* Implementations MUST append or register the provided argument for later
36+
* use when build() is called. When a non-empty value is provided, the
37+
* implementation SHALL associate that value with the argument according to
38+
* its command-building strategy.
39+
*
40+
* @param string $argument the argument name or token that SHALL be added to the process definition
41+
* @param ?string $value an optional value associated with the argument
42+
*
43+
* @return self the current builder instance for fluent chaining
44+
*/
45+
public function withArgument(string $argument, ?string $value = null): self;
46+
47+
/**
48+
* Builds a process instance for the specified command.
49+
*
50+
* Implementations MUST return a Process configured with the provided
51+
* command and all arguments previously collected by the builder. The
52+
* returned process SHOULD be ready for execution by the caller.
53+
*
54+
* @param string $command the base command that SHALL be used to create the process
55+
*
56+
* @return Process the configured process instance
57+
*/
58+
public function build(string $command): Process;
59+
}

0 commit comments

Comments
 (0)