Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
24 / 24
100.00% covered (success)
100.00%
4 / 4
CRAP
100.00% covered (success)
100.00%
1 / 1
ComposerDependencyAnalyserConfig
100.00% covered (success)
100.00%
24 / 24
100.00% covered (success)
100.00%
4 / 4
7
100.00% covered (success)
100.00%
1 / 1
 configure
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
4
 applyIgnoresShadowDependencies
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 shouldShowShadowDependencies
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 applyPackagedRepositoryIgnores
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
1
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\Environment\Environment;
23use FastForward\DevTools\Environment\EnvironmentInterface;
24use FastForward\DevTools\Path\DevToolsPathResolver;
25use ShipMonk\ComposerDependencyAnalyser\Config\Configuration;
26use ShipMonk\ComposerDependencyAnalyser\Config\ErrorType;
27
28/**
29 * Provides the default Composer Dependency Analyser configuration.
30 *
31 * Consumers can use this as a starting point and extend it:
32 *
33 *     return \FastForward\DevTools\Config\ComposerDependencyAnalyserConfig::configure(
34 *         static function (\ShipMonk\ComposerDependencyAnalyser\Config\Configuration $configuration): void {
35 *             $configuration->ignoreErrorsOnPackage(
36 *                 'vendor/package',
37 *                 [\ShipMonk\ComposerDependencyAnalyser\Config\ErrorType::UNUSED_DEPENDENCY]
38 *             );
39 *         }
40 *     );
41 *
42 * @see https://github.com/shipmonk-rnd/composer-dependency-analyser
43 */
44 class ComposerDependencyAnalyserConfig
45{
46    public const string ENV_SHOW_SHADOW_DEPENDENCIES = 'FAST_FORWARD_DEV_TOOLS_SHOW_SHADOW_DEPENDENCIES';
47
48    /**
49     * Dependencies that are only required by the packaged DevTools distribution itself.
50     *
51     * These packages MUST only be ignored when the analyser runs against the
52     * DevTools repository, because consumer repositories do not inherit them as
53     * direct requirements automatically.
54     *
55     * @var array<int, string>
56     */
57    public const array DEFAULT_PACKAGED_UNUSED_DEPENDENCIES = [
58        'ergebnis/phpunit-agent-reporter',
59        'ergebnis/composer-normalize',
60        'fakerphp/faker',
61        'fast-forward/phpdoc-bootstrap-template',
62        'php-parallel-lint/php-parallel-lint',
63        'phpdocumentor/shim',
64        'phpmetrics/phpmetrics',
65        'phpro/grumphp-shim',
66        'pyrech/composer-changelogs',
67        'rector/jack',
68        'saggre/phpdocumentor-markdown',
69        'symfony/var-dumper',
70    ];
71
72    /**
73     * Production dependencies intentionally kept in require for the packaged toolchain.
74     *
75     * These dependencies are only exercised in test and development paths inside
76     * this repository, but they MUST remain available to the packaged DevTools
77     * runtime for consumer projects that choose to use those capabilities.
78     *
79     * @var array<int, string>
80     */
81    public const array DEFAULT_PACKAGED_PROD_ONLY_IN_DEV_DEPENDENCIES = [
82        'phpspec/prophecy',
83        'phpspec/prophecy-phpunit',
84        'symfony/var-exporter',
85    ];
86
87    /**
88     * Creates the default Composer Dependency Analyser configuration.
89     *
90     * @param callable|null $customize optional callback to customize the configuration
91     * @param EnvironmentInterface|null $environment optional environment reader used to resolve overrides
92     *
93     * @return Configuration the configured analyser configuration
94     */
95    public static function configure(
96        ?callable $customize = null,
97        ?EnvironmentInterface $environment = null,
98    ): Configuration {
99        $environment ??= new Environment();
100        $configuration = new Configuration();
101
102        if (! self::shouldShowShadowDependencies($environment)) {
103            self::applyIgnoresShadowDependencies($configuration);
104        }
105
106        if (DevToolsPathResolver::isRepositoryCheckout()) {
107            self::applyPackagedRepositoryIgnores($configuration);
108        }
109
110        if (null !== $customize) {
111            $customize($configuration);
112        }
113
114        return $configuration;
115    }
116
117    /**
118     * The default configuration ignores shadow dependencies because Fast
119     * Forward packages MAY intentionally require dependency groups. For example,
120     * ecosystem or meta packages can require related PSR or framework packages
121     * so consumers do not need to install every package one by one.
122     *
123     * @param Configuration $configuration the analyser configuration to customize
124     *
125     * @return Configuration the modified configuration with shadow dependencies ignored
126     */
127    public static function applyIgnoresShadowDependencies(Configuration $configuration): Configuration
128    {
129        $configuration->ignoreErrors([ErrorType::SHADOW_DEPENDENCY]);
130
131        return $configuration;
132    }
133
134    /**
135     * Determines whether shadow dependency reports SHOULD remain visible.
136     *
137     * @param EnvironmentInterface|null $environment optional environment reader used to resolve overrides
138     *
139     * @return bool
140     */
141    public static function shouldShowShadowDependencies(?EnvironmentInterface $environment = null): bool
142    {
143        $environment ??= new Environment();
144
145        return '1' === $environment->get(self::ENV_SHOW_SHADOW_DEPENDENCIES);
146    }
147
148    /**
149     * Applies the ignores required only by the packaged DevTools repository.
150     *
151     * @param Configuration $configuration the analyser configuration to customize
152     *
153     * @return Configuration the modified configuration with packaged repository ignores applied
154     */
155    public static function applyPackagedRepositoryIgnores(Configuration $configuration): Configuration
156    {
157        $configuration->ignoreErrorsOnExtension('ext-pcntl', [ErrorType::SHADOW_DEPENDENCY]);
158        $configuration->ignoreErrorsOnPackages(
159            self::DEFAULT_PACKAGED_UNUSED_DEPENDENCIES,
160            [ErrorType::UNUSED_DEPENDENCY]
161        );
162        $configuration->ignoreErrorsOnPackages(
163            self::DEFAULT_PACKAGED_PROD_ONLY_IN_DEV_DEPENDENCIES,
164            [ErrorType::PROD_DEPENDENCY_ONLY_IN_DEV],
165        );
166        $configuration->ignoreErrorsOnPackage('composer/composer', [ErrorType::DEV_DEPENDENCY_IN_PROD]);
167
168        return $configuration;
169    }
170}