Skip to content

Commit 77f8ec8

Browse files
authored
[FEATURE] Symfony console application (#39)
1 parent ffbc6ec commit 77f8ec8

37 files changed

+2543
-142
lines changed

README.md

Lines changed: 85 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@ working on your TYPO3 project.
1616

1717
## Installation
1818

19-
As this is a composer package, execute `composer req --dev typo3/coding-standards`
20-
in your composer project.
19+
Since this is a Composer package, run `composer require --dev typo3/coding-standards`
20+
in your Composer project, which of course includes TYPO3 project or extension or
21+
any other Composer project.
2122

2223
## What's in the package?
2324

@@ -27,37 +28,47 @@ certain rules to other projects as well. TYPO3 is more than just TYPO3 Core!
2728

2829
### PHP-CS-Fixer rules
2930

30-
Making sure your PHP files apply to the same rules.
31+
Ensures that your PHP files are subject to the same rules.
3132

3233
### .editorconfig
3334

3435
If you work on a team, and you use different IDE settings, `.editorconfig`
3536
helps you to have the same settings across all editors. It does not matter if
36-
it is VS-Code, vim or PhpStorm.
37+
it is VS-Code, vim or PhpStorm, almost every editor supports the `.editorconfig`
38+
nowadays.
3739

38-
### Setting up the TYPO3 rulesets as boilerplate
40+
### Setting up the TYPO3 rule sets as boilerplate
3941

4042
Our coding standards file can set this up for you. Run
4143

4244
```bash
43-
composer exec typo3-coding-standards project
45+
composer exec typo3-coding-standards setup
4446
```
4547

46-
or
48+
or via the shortcut, which of course works for every command:
49+
50+
```bash
51+
composer exec t3-cs s
52+
```
53+
54+
The type `project` or `extension` is automatically detected. If the detection
55+
does not work for you (please also tell us about your case at
56+
<https://github.com/TYPO3/coding-standards/issues>), you can specify the
57+
desired type as parameter like this:
4758

4859
```bash
49-
composer exec typo3-coding-standards extension
60+
composer exec typo3-coding-standards setup project
5061
```
5162

52-
or if you want to update the rules, use the `-f` option
63+
or
5364

5465
```bash
55-
composer exec -- typo3-coding-standards extension -f
66+
composer exec typo3-coding-standards setup extension
5667
```
5768

5869
Have a look at the newly created files in your root folder:
5970

60-
* .php-cs-fixer.php
71+
* .php-cs-fixer.dist.php
6172
* .editorconfig
6273

6374
For projects, the folder `src` is configured by default, but you can
@@ -70,6 +81,67 @@ configurations just like with PHP-CS-Fixer.
7081
You can decide to commit them to your Git repository, which is the recommended
7182
way.
7283

84+
### Updating the TYPO3 rule sets
85+
86+
To update the rule sets, run `composer update typo3/coding-standards`. An updated
87+
PHP-CS-Fixer rule set is applied immediately, but changes to the `.editorconfig`
88+
file must be applied manually by running `composer exec typo3-coding-standards update`.
89+
90+
This will overwrite your changes in the `.editorconfig` and reset it to the
91+
TYPO3 default values. Please make sure that your file has been properly
92+
committed to your repository before proceeding with the update.
93+
94+
You can also reset all files to the TYPO3 defaults by providing the `--force`
95+
option to the `setup` command:
96+
97+
```bash
98+
composer exec -- typo3-coding-standards setup --force
99+
```
100+
101+
Don't forget to provide the two dashes after `exec` if you use options.
102+
103+
### Advanced usage examples
104+
105+
Show a command specific help e.g. with `composer exec typo3-coding-standards help setup`.
106+
107+
It is possible to specify a destination folder for the files or to set up only
108+
a part of the TYPO3 coding standards, here are some examples.
109+
110+
Setup `.editorconfig` only:
111+
112+
```bash
113+
composer exec -- typo3-coding-standards setup --rule-set=editorconfig
114+
```
115+
116+
Setup `.php-cs-fixer.dist.php` in the `Build` folder:
117+
118+
```bash
119+
composer exec -- typo3-coding-standards setup --target-dir=Build --rule-set=php-cs-fixer
120+
```
121+
122+
Symfony comes with a great shortcut support for all commands e.g. this is the
123+
same like the last command above:
124+
125+
```bash
126+
composer exec -- t3-cs s -d=Build -r=php-cs-fixer
127+
```
128+
129+
Update the `.editorconfig`:
130+
131+
```bash
132+
composer exec t3-cs u
133+
```
134+
135+
Running the script directly not using Composer:
136+
137+
```bash
138+
vendor/bin/typo3-coding-standards setup
139+
```
140+
141+
Of course this assumes the binaries are installed by Composer at the default
142+
location `vendor/bin`. That's why we recommend using `composer exec` in the
143+
first place becaue Composer is aware of the correct location.
144+
73145
## Executing the PHP-CS-Fixer
74146

75147
Once you've followed the step above, running PHP CS Fixer works like this:
@@ -78,8 +150,8 @@ Once you've followed the step above, running PHP CS Fixer works like this:
78150
composer exec php-cs-fixer
79151
```
80152

81-
Leave a note on how you set it up on GitHub Actions or GitLab CI/CD so this
82-
document can be even more helpful for everybody.
153+
Have a look at our GitHub Actions [Continuous Integration workflow](https://github.com/TYPO3/coding-standards/blob/main/.github/workflows/continuous-integration.yml)
154+
to get an idea on how to automate your testing workflows using this package.
83155

84156
## What's next?
85157

composer.json

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,15 @@
3030
},
3131
"require": {
3232
"php": "^7.2 || ^8.0",
33-
"friendsofphp/php-cs-fixer": "^3.0"
33+
"ext-json": "*",
34+
"friendsofphp/php-cs-fixer": "^3.0",
35+
"symfony/console": "^4.4.30 || ^5.3.7 || ^6.0",
36+
"symfony/filesystem": "^4.4 || ^5.0 || ^6.0"
3437
},
3538
"require-dev": {
3639
"composer/package-versions-deprecated": "^1.11.99.4",
3740
"ergebnis/composer-normalize": "*",
41+
"keradus/cli-executor": "^1.5",
3842
"maglnet/composer-require-checker": "*",
3943
"nikic/php-parser": "^4.13.1",
4044
"overtrue/phplint": "^3.0",
@@ -44,7 +48,8 @@
4448
"phpstan/phpstan-strict-rules": "^1.0",
4549
"phpstan/phpstan-symfony": "^1.0",
4650
"phpunit/phpunit": "^8.5.24 || ^9.5.18",
47-
"symfony/finder": ">=4.4.30"
51+
"symfony/finder": ">=4.4",
52+
"symfony/process": ">=4.4"
4853
},
4954
"autoload": {
5055
"psr-4": {
@@ -56,7 +61,10 @@
5661
"TYPO3\\CodingStandards\\Tests\\": "tests"
5762
}
5863
},
59-
"bin": "typo3-coding-standards",
64+
"bin": [
65+
"t3-cs",
66+
"typo3-coding-standards"
67+
],
6068
"config": {
6169
"allow-plugins": {
6270
"ergebnis/composer-normalize": true,

phpstan.neon

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,10 @@ parameters:
77
- src
88
- tests
99
- typo3-coding-standards
10+
11+
excludePaths:
12+
analyse:
13+
- tests/Console/Style/SimpleStyle.php
14+
15+
stubFiles:
16+
- stubs/Command.stub

rector.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
use Rector\Set\ValueObject\DowngradeLevelSetList;
2222
use Rector\Set\ValueObject\LevelSetList;
2323
use Rector\Set\ValueObject\SetList;
24+
use Rector\Symfony\Set\SymfonyLevelSetList;
25+
use Rector\Symfony\Set\SymfonySetList;
2426

2527
return static function (RectorConfig $rectorConfig): void {
2628
$rectorConfig->paths([
@@ -29,6 +31,7 @@
2931
]);
3032

3133
$rectorConfig->skip([
34+
__DIR__ . '/tests/Console/Style/SimpleStyle.php',
3235
__DIR__ . '/tests/Unit/Fixtures',
3336

3437
FinalizeClassesWithoutChildrenRector::class => [
@@ -50,6 +53,11 @@
5053
SetList::TYPE_DECLARATION_STRICT,
5154
SetList::EARLY_RETURN,
5255

56+
// Symfony rules
57+
SymfonyLevelSetList::UP_TO_SYMFONY_44,
58+
SymfonySetList::SYMFONY_STRICT,
59+
SymfonySetList::SYMFONY_CODE_QUALITY,
60+
5361
// PHPUnit rules
5462
PHPUnitLevelSetList::UP_TO_PHPUNIT_80,
5563
PHPUnitSetList::PHPUNIT_CODE_QUALITY,

src/Console/Application.php

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the TYPO3 project.
7+
*
8+
* (c) 2019-2022 Benni Mack
9+
* Simon Gilli
10+
*
11+
* For the full copyright and license information, please view
12+
* the LICENSE file that was distributed with this source code.
13+
*
14+
* The TYPO3 project - inspiring people to share!
15+
*/
16+
17+
namespace TYPO3\CodingStandards\Console;
18+
19+
use RuntimeException;
20+
use Symfony\Component\Console\Application as BaseApplication;
21+
use Symfony\Component\Console\Input\InputDefinition;
22+
use Symfony\Component\Console\Input\InputInterface;
23+
use Symfony\Component\Console\Input\InputOption;
24+
use Symfony\Component\Filesystem\Filesystem;
25+
use TYPO3\CodingStandards\Console\Command\SetupCommand;
26+
use TYPO3\CodingStandards\Console\Command\SetupExtensionCommand;
27+
use TYPO3\CodingStandards\Console\Command\SetupProjectCommand;
28+
use TYPO3\CodingStandards\Console\Command\UpdateCommand;
29+
30+
/**
31+
* @internal
32+
*/
33+
final class Application extends BaseApplication
34+
{
35+
/**
36+
* @var string
37+
*/
38+
public const VERSION = '0.6.0-DEV';
39+
40+
/**
41+
* getcwd() equivalent which always returns a string
42+
*
43+
* @throws RuntimeException
44+
*/
45+
private static function getCwd(bool $allowEmpty = false): string
46+
{
47+
$cwd = getcwd();
48+
49+
// @codeCoverageIgnoreStart
50+
// fallback to realpath('') just in case this works but odds are it would break as well if we are in a case
51+
// where getcwd fails
52+
if ($cwd === false) {
53+
$cwd = realpath('');
54+
}
55+
56+
// crappy state, assume '' and hopefully relative paths allow things to continue
57+
if ($cwd === false) {
58+
if ($allowEmpty) {
59+
return '';
60+
}
61+
62+
throw new RuntimeException('Could not determine the current working directory');
63+
}
64+
65+
// @codeCoverageIgnoreEnd
66+
67+
return $cwd;
68+
}
69+
70+
public static function getProjectDir(): string
71+
{
72+
return self::getCwd(true);
73+
}
74+
75+
/**
76+
* @throws RuntimeException
77+
*/
78+
public static function getTargetDir(InputInterface $input): string
79+
{
80+
/** @var string|null $targetDir */
81+
$targetDir = $input->getParameterOption(['--target-dir', '-d'], null, true);
82+
83+
if ($targetDir === null) {
84+
$targetDir = self::getProjectDir();
85+
}
86+
87+
if (!(new Filesystem())->isAbsolutePath($targetDir)) {
88+
$targetDir = self::getProjectDir() . '/' . $targetDir;
89+
}
90+
91+
if (!is_dir($targetDir)) {
92+
throw new RuntimeException(\sprintf('Invalid target directory specified, %s does not exist.', $targetDir));
93+
}
94+
95+
return $targetDir;
96+
}
97+
98+
public function __construct()
99+
{
100+
parent::__construct('TYPO3 Coding Standards', self::VERSION);
101+
102+
// in alphabetical order
103+
$this->add(new SetupCommand());
104+
$this->add(new SetupExtensionCommand());
105+
$this->add(new SetupProjectCommand());
106+
$this->add(new UpdateCommand());
107+
108+
//$this->setDefaultCommand('setup', false);
109+
}
110+
111+
protected function getDefaultInputDefinition(): InputDefinition
112+
{
113+
$inputDefinition = parent::getDefaultInputDefinition();
114+
$inputDefinition->addOption(new InputOption(
115+
'--target-dir',
116+
'-d',
117+
InputOption::VALUE_REQUIRED,
118+
'If specified, use the given directory as target directory',
119+
self::getProjectDir()
120+
));
121+
122+
return $inputDefinition;
123+
}
124+
}

0 commit comments

Comments
 (0)