Skip to content

Commit 481b8c2

Browse files
Add PHP-CS-Fixer Config and Rules classes (#30)
* feat: add PHP-CS-Fixer Config and Rules classes for shared configuration Provides a proper API for sharing php-cs-fixer config across projects, replacing the hacky vendor path require approach. * #15000 🪄️ Apply coding style fixes to PHP * feat: add new rules from phpyh/coding-standard - blank_line_before_statement: blank lines before return, throw, try, etc. - multiline_whitespace_before_semicolons: no_multi_line strategy - no_superfluous_phpdoc_tags: remove redundant @inheritdoc - nullable_type_declaration_for_default_null_value: explicit nullability - numeric_literal_separator: 1_000_000 instead of 1000000 - ordered_imports: class, function, const order * docs: clarify that PHPCS and PHP-CS-Fixer can be used independently * docs: add composer scripts examples to Usage section * docs: update Usage with combined cs:check/cs:fix scripts * docs: add direct vendor/bin usage before composer scripts * revert: remove no_superfluous_phpdoc_tags rule It removes @inheritdoc which is needed by PHPStan. * revert: remove numeric_literal_separator rule * fix: remove return/throw from blank_line_before_statement These add noise in short methods where the blank line is unnecessary. * revert: remove blank_line_before_statement rule * fix: suppress mixed type hint warnings in PhpCsFixer classes --------- Co-authored-by: GitHub Actions <actions@github.com>
1 parent e4e3e4e commit 481b8c2

File tree

5 files changed

+133
-63
lines changed

5 files changed

+133
-63
lines changed

.php-cs-fixer-rules.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
],
4545
'modernize_types_casting' => true,
4646
'mb_str_functions' => true,
47+
'multiline_whitespace_before_semicolons' => ['strategy' => 'no_multi_line'],
4748
'no_alias_functions' => true,
4849
'no_binary_string' => true,
4950
'no_empty_comment' => true,
@@ -69,7 +70,9 @@
6970
'no_whitespace_before_comma_in_array' => true,
7071
'normalize_index_brace' => true,
7172
'nullable_type_declaration' => ['syntax' => 'question_mark'],
73+
'nullable_type_declaration_for_default_null_value' => true,
7274
'object_operator_without_whitespace' => true,
75+
'ordered_imports' => ['imports_order' => ['class', 'function', 'const']],
7376
/*
7477
* @see https://github.com/slevomat/coding-standard/issues/1620#issuecomment-1758006718
7578
* 'ordered_class_elements' => [
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace IxDFCodingStandard\PhpCsFixer;
4+
5+
use PhpCsFixer\Config as BaseConfig;
6+
use PhpCsFixer\Finder;
7+
use PhpCsFixer\Runner\Parallel\ParallelConfigFactory;
8+
9+
/**
10+
* Pre-configured PHP-CS-Fixer config factory for IxDF projects.
11+
* @see README.md for usage examples
12+
*/
13+
final class Config
14+
{
15+
// phpcs:ignore SlevomatCodingStandard.TypeHints.DisallowMixedTypeHint.DisallowedMixedTypeHint
16+
/** @param array<string, array<string, mixed>|bool> $ruleOverrides Rules to merge on top of the shared ruleset */
17+
public static function create(string $projectDir, array $ruleOverrides = [], ?Finder $finder = null): BaseConfig
18+
{
19+
$finder ??= self::defaultFinder($projectDir);
20+
21+
return (new BaseConfig())
22+
->setParallelConfig(ParallelConfigFactory::detect())
23+
->setUsingCache(true)
24+
->setCacheFile($projectDir.'/.cache/.php-cs-fixer.cache')
25+
->setRiskyAllowed(true)
26+
->setIndent(' ')
27+
->setLineEnding("\n")
28+
->setRules(array_merge(Rules::get(), $ruleOverrides))
29+
->setFinder($finder);
30+
}
31+
32+
private static function defaultFinder(string $projectDir): Finder
33+
{
34+
return Finder::create()
35+
->in($projectDir)
36+
->exclude([
37+
'.cache',
38+
'.docker',
39+
'bootstrap/cache',
40+
'node_modules',
41+
'public',
42+
'storage',
43+
'vendor',
44+
])
45+
->name('*.php')
46+
->notName('*.blade.php')
47+
->notName('_ide_helper.php')
48+
->notName('.phpstorm.meta.php')
49+
->ignoreDotFiles(false)
50+
->ignoreVCS(true)
51+
->ignoreVCSIgnored(true);
52+
}
53+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace IxDFCodingStandard\PhpCsFixer;
4+
5+
/**
6+
* Shared PHP-CS-Fixer rules for IxDF projects.
7+
* @see https://mlocati.github.io/php-cs-fixer-configurator/
8+
*/
9+
final class Rules
10+
{
11+
// phpcs:ignore SlevomatCodingStandard.TypeHints.DisallowMixedTypeHint.DisallowedMixedTypeHint
12+
/** @var array<string, array<string, mixed>|bool>|null */
13+
private static ?array $rules = null;
14+
15+
// phpcs:ignore SlevomatCodingStandard.TypeHints.DisallowMixedTypeHint.DisallowedMixedTypeHint
16+
/** @return array<string, array<string, mixed>|bool> */
17+
public static function get(): array
18+
{
19+
return self::$rules ??= require dirname(__DIR__, 2).'/.php-cs-fixer-rules.php';
20+
}
21+
}

README.md

Lines changed: 54 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -3,107 +3,100 @@
33
[![PHP Psalm Level](https://shepherd.dev/github/InteractionDesignFoundation/coding-standard/level.svg)](https://shepherd.dev/github/InteractionDesignFoundation/coding-standard)
44
[![PHP Psalm Type Coverage](https://shepherd.dev/github/InteractionDesignFoundation/coding-standard/coverage.svg)](https://shepherd.dev/github/InteractionDesignFoundation/coding-standard)
55

6-
# IxDF Coding Standard for Laravel
6+
# IxDF Coding Standard
77

8-
An opinionated ruleset focused on strict types.
9-
Suitable for both applications and packages.
8+
An opinionated coding standard for PHP/Laravel projects. Provides two independent tools — use either one or both together:
9+
10+
- **PHP_CodeSniffer** — custom sniffs for strict types and Laravel conventions
11+
- **PHP-CS-Fixer** — shared config with 80+ rules based on PER-CS 3.0
1012

1113
## Installation
1214

13-
1. Install the package via composer by running:
1415
```shell
1516
composer require --dev interaction-design-foundation/coding-standard
1617
```
1718

18-
2. Add composer scripts into your `composer.json`:
19-
```json
20-
"scripts": {
21-
"cs:check": "phpcs -p -s --colors --report-full --report-summary",
22-
"cs:fix": "phpcbf -p --colors"
23-
}
24-
```
19+
## PHP_CodeSniffer
2520

26-
3. Create file `phpcs.xml` on the base path of your repository with content
21+
Create `phpcs.xml` in your project root:
2722
```xml
2823
<?xml version="1.0"?>
2924
<ruleset name="My Coding Standard">
30-
<!-- Include all rules from the IxDF Coding Standard -->
3125
<rule ref="IxDFCodingStandard"/>
32-
33-
<!-- Paths to check -->
3426
<file>app</file>
3527
<file>config</file>
3628
<file>database</file>
37-
<file>lang</file>
3829
<file>routes</file>
3930
<file>tests</file>
4031
</ruleset>
4132
```
4233

43-
## Usage
34+
## PHP-CS-Fixer
4435

45-
- To run checks only:
36+
Create `.php-cs-fixer.php` in your project root:
4637

47-
```shell
48-
composer cs:check
49-
```
38+
```php
39+
<?php declare(strict_types=1);
5040

51-
- To automatically fix many CS issues:
41+
use IxDFCodingStandard\PhpCsFixer\Config;
5242

53-
```shell
54-
composer cs:fix
43+
return Config::create(__DIR__);
5544
```
5645

57-
## Ignoring parts of a File
58-
59-
Disable parts of a file:
46+
With rule overrides:
6047

6148
```php
62-
$xmlPackage = new XMLPackage;
63-
// phpcs:disable
64-
$xmlPackage['error_code'] = get_default_error_code_value();
65-
$xmlPackage->send();
66-
// phpcs:enable
49+
return Config::create(__DIR__, ruleOverrides: [
50+
'final_public_method_for_abstract_class' => false,
51+
]);
6752
```
6853

69-
Disable a specific rule:
54+
With a custom Finder:
7055

7156
```php
72-
// phpcs:disable Generic.Commenting.Todo.Found
73-
$xmlPackage = new XMLPackage;
74-
$xmlPackage['error_code'] = get_default_error_code_value();
75-
// TODO: Add an error message here.
76-
$xmlPackage->send();
77-
// phpcs:enable
78-
```
57+
use IxDFCodingStandard\PhpCsFixer\Config;
58+
use PhpCsFixer\Finder;
7959

80-
Ignore a specific violation:
60+
$finder = Finder::create()->in(__DIR__)->name('*.php');
8161

62+
return Config::create(__DIR__, finder: $finder);
63+
```
64+
65+
If you only need the rules array:
8266
```php
83-
$xmlPackage = new XMLPackage;
84-
$xmlPackage['error_code'] = get_default_error_code_value();
85-
// phpcs:ignore Generic.Commenting.Todo.Found
86-
// TODO: Add an error message here.
87-
$xmlPackage->send();
67+
$rules = \IxDFCodingStandard\PhpCsFixer\Rules::get();
8868
```
8969

90-
## Development
70+
## Usage
71+
72+
```shell
73+
vendor/bin/phpcs # check with PHP_CodeSniffer
74+
vendor/bin/phpcbf # fix with PHP_CodeSniffer
75+
vendor/bin/php-cs-fixer fix --dry-run --diff # check with PHP-CS-Fixer
76+
vendor/bin/php-cs-fixer fix # fix with PHP-CS-Fixer
77+
```
9178

92-
### Versioning
93-
> **New rules or Sniffs may not be introduced in minor or bugfix releases and should always be based on the develop
94-
branch and queued for the next major release, unless considered a bugfix for existing rules.**
79+
### Composer scripts (recommended)
9580

81+
Add to your `composer.json`:
9682

97-
## Reference
83+
```json
84+
"scripts": {
85+
"cs": "@cs:fix",
86+
"cs:check": ["@php-cs-fixer:dry", "@phpcs"],
87+
"cs:fix": ["@php-cs-fixer", "@phpcbf"],
88+
"phpcs": "phpcs -p -s --colors --report-full --report-summary",
89+
"phpcbf": "phpcbf -p --colors",
90+
"php-cs-fixer": "php-cs-fixer fix --no-interaction --ansi --quiet",
91+
"php-cs-fixer:dry": "php-cs-fixer fix --no-interaction --ansi --verbose --dry-run"
92+
}
93+
```
9894

99-
Rules can be added, excluded or tweaked locally, depending on your preferences.
100-
More information on how to do this can be found here:
95+
Then run:
10196

102-
- [Coding Standard Tutorial](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Coding-Standard-Tutorial)
103-
- [Configuration Options](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Configuration-Options)
104-
- [Selectively Applying Rules](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Annotated-Ruleset#selectively-applying-rules)
105-
- [Customisable Sniff Properties](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Customisable-Sniff-Properties)
106-
- Other coding standards (inspiring us):
107-
- [Slevomat coding standard](https://github.com/slevomat/coding-standard)
108-
- [Doctrine coding standard](https://github.com/doctrine/coding-standard)
109-
- [Laminas coding standard](https://github.com/laminas/laminas-coding-standard)
97+
```shell
98+
composer cs:check # run both tools in check mode
99+
composer cs:fix # run both tools in fix mode
100+
composer phpcs # PHP_CodeSniffer only
101+
composer php-cs-fixer # PHP-CS-Fixer only
102+
```

composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
{
22
"name": "interaction-design-foundation/coding-standard",
3-
"description": "IxDF Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.",
3+
"description": "IxDF coding standard: PHP_CodeSniffer rules and shared PHP-CS-Fixer configuration.",
44
"license": "MIT",
55
"type": "phpcodesniffer-standard",
66
"require": {
77
"php": "^8.3",
88
"dealerdirect/phpcodesniffer-composer-installer": "^1.0",
9+
"friendsofphp/php-cs-fixer": "^3.89",
910
"slevomat/coding-standard": "^8.25",
1011
"squizlabs/php_codesniffer": "^4.0"
1112
},
1213
"require-dev": {
13-
"friendsofphp/php-cs-fixer": "^3.89",
1414
"phpunit/phpunit": "^12.4",
1515
"vimeo/psalm": "^6.13"
1616
},

0 commit comments

Comments
 (0)