Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
96.55% covered (success)
96.55%
28 / 29
66.67% covered (warning)
66.67%
2 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
ECSConfig
96.55% covered (success)
96.55%
28 / 29
66.67% covered (warning)
66.67%
2 / 3
5
0.00% covered (danger)
0.00%
0 / 1
 configure
85.71% covered (warning)
85.71%
6 / 7
0.00% covered (danger)
0.00%
0 / 1
2.01
 applyDefaultPathsAndSkips
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
 applyDefaultRulesAndSets
100.00% covered (success)
100.00%
17 / 17
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3declare(strict_types=1);
4
5/**
6 * Fast Forward Development Tools for PHP projects.
7 *
8 * This file is part of fast-forward/dev-tools project.
9 *
10 * @author   Felipe SayĆ£o Lobato Abreu <github@mentordosnerds.com>
11 * @license  https://opensource.org/licenses/MIT MIT License
12 *
13 * @see      https://github.com/php-fast-forward/
14 * @see      https://github.com/php-fast-forward/dev-tools
15 * @see      https://github.com/php-fast-forward/dev-tools/issues
16 * @see      https://php-fast-forward.github.io/dev-tools/
17 * @see      https://datatracker.ietf.org/doc/html/rfc2119
18 */
19
20namespace FastForward\DevTools\Config;
21
22use FastForward\DevTools\Path\WorkingProjectPathResolver;
23use PhpCsFixer\Fixer\Import\GlobalNamespaceImportFixer;
24use PhpCsFixer\Fixer\Phpdoc\GeneralPhpdocAnnotationRemoveFixer;
25use PhpCsFixer\Fixer\Phpdoc\PhpdocAlignFixer;
26use PhpCsFixer\Fixer\Phpdoc\NoEmptyPhpdocFixer;
27use PhpCsFixer\Fixer\Phpdoc\NoSuperfluousPhpdocTagsFixer;
28use PhpCsFixer\Fixer\Phpdoc\PhpdocAddMissingParamAnnotationFixer;
29use PhpCsFixer\Fixer\Phpdoc\PhpdocNoEmptyReturnFixer;
30use PhpCsFixer\Fixer\Phpdoc\PhpdocToCommentFixer;
31use PhpCsFixer\Fixer\PhpUnit\PhpUnitTestCaseStaticMethodCallsFixer;
32use Symplify\EasyCodingStandard\Configuration\ECSConfigBuilder;
33
34use function Safe\getcwd;
35
36/**
37 * Provides the default ECS configuration.
38 *
39 * Consumers can use this as a starting point and extend it:
40 *
41 *     $config = \FastForward\DevTools\Config\ECSConfig::configure();
42 *     $config->withRules([CustomRule::class]);
43 *     $config->withConfiguredRule(PhpdocAlignFixer::class, ['align' => 'right']);
44 *     return $config;
45 *
46 * @see https://github.com/symplify/easy-coding-standard
47 */
48 class ECSConfig
49{
50    /**
51     * @var array{symfony: bool, symfonyRisky: bool, auto: bool, autoRisky: bool} the PHP-CS-Fixer sets applied by default
52     */
53    public const array DEFAULT_PHP_CS_FIXER_SETS = [
54        'symfony' => true,
55        'symfonyRisky' => true,
56        'auto' => true,
57        'autoRisky' => true,
58    ];
59
60    /**
61     * @var array{psr12: bool, common: bool, symplify: bool, cleanCode: bool} the prepared ECS sets applied by default
62     */
63    public const array DEFAULT_PREPARED_SETS = [
64        'psr12' => true,
65        'common' => true,
66        'symplify' => true,
67        'cleanCode' => true,
68    ];
69
70    /**
71     * @var list<class-string> the ECS/CS Fixer rules that SHOULD be skipped by default
72     */
73    public const array DEFAULT_SKIPPED_RULES = [
74        PhpdocToCommentFixer::class,
75        NoSuperfluousPhpdocTagsFixer::class,
76        NoEmptyPhpdocFixer::class,
77        PhpdocNoEmptyReturnFixer::class,
78        GlobalNamespaceImportFixer::class,
79        GeneralPhpdocAnnotationRemoveFixer::class,
80    ];
81
82    /**
83     * @var array<class-string, array<string, mixed>> the configured ECS rules applied by default
84     */
85    public const array DEFAULT_CONFIGURED_RULES = [
86        PhpdocAlignFixer::class => [
87            'align' => 'left',
88        ],
89        PhpUnitTestCaseStaticMethodCallsFixer::class => [
90            'call_type' => 'self',
91        ],
92        PhpdocAddMissingParamAnnotationFixer::class => [
93            'only_untyped' => false,
94        ],
95    ];
96
97    /**
98     * Creates the default ECS configuration.
99     *
100     * @param callable|null $customize optional callback to customize the configuration builder
101     *
102     * @return ECSConfigBuilder the configured ECS configuration builder
103     */
104    public static function configure(?callable $customize = null): ECSConfigBuilder
105    {
106        $workingDirectory = getcwd();
107        $config = new ECSConfigBuilder();
108
109        self::applyDefaultPathsAndSkips($config, $workingDirectory);
110        self::applyDefaultRulesAndSets($config);
111
112        if (null !== $customize) {
113            $customize($config);
114        }
115
116        return $config;
117    }
118
119    /**
120     * Applies the default repository paths and skipped rules to an ECS builder.
121     *
122     * @param ECSConfigBuilder $config
123     * @param string $workingDirectory
124     */
125    public static function applyDefaultPathsAndSkips(
126        ECSConfigBuilder $config,
127        string $workingDirectory
128    ): ECSConfigBuilder {
129        $paths = WorkingProjectPathResolver::getToolingSourcePaths($workingDirectory);
130        $skipPaths = WorkingProjectPathResolver::getToolingExcludedDirectories();
131
132        return $config
133            ->withPaths($paths)
134            ->withSkip([...$skipPaths, ...self::DEFAULT_SKIPPED_RULES]);
135    }
136
137    /**
138     * Applies the default ECS sets, root files, and configured rules to an ECS builder.
139     *
140     * @param ECSConfigBuilder $config
141     */
142    public static function applyDefaultRulesAndSets(ECSConfigBuilder $config): ECSConfigBuilder
143    {
144        $config
145            ->withRootFiles()
146            ->withPhpCsFixerSets(
147                symfony: self::DEFAULT_PHP_CS_FIXER_SETS['symfony'],
148                symfonyRisky: self::DEFAULT_PHP_CS_FIXER_SETS['symfonyRisky'],
149                auto: self::DEFAULT_PHP_CS_FIXER_SETS['auto'],
150                autoRisky: self::DEFAULT_PHP_CS_FIXER_SETS['autoRisky'],
151            )
152            ->withPreparedSets(
153                psr12: self::DEFAULT_PREPARED_SETS['psr12'],
154                common: self::DEFAULT_PREPARED_SETS['common'],
155                symplify: self::DEFAULT_PREPARED_SETS['symplify'],
156                cleanCode: self::DEFAULT_PREPARED_SETS['cleanCode'],
157            );
158
159        foreach (self::DEFAULT_CONFIGURED_RULES as $rule => $configuration) {
160            $config->withConfiguredRule($rule, $configuration);
161        }
162
163        return $config;
164    }
165}