Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
23 / 23
100.00% covered (success)
100.00%
4 / 4
CRAP
100.00% covered (success)
100.00%
1 / 1
ComposerDependencyAnalyserConfig
100.00% covered (success)
100.00%
23 / 23
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%
10 / 10
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        'pyrech/composer-changelogs',
66        'rector/swiss-knife',
67        'saggre/phpdocumentor-markdown',
68        'symfony/var-dumper',
69    ];
70
71    /**
72     * Production dependencies intentionally kept in require for the packaged toolchain.
73     *
74     * These dependencies are only exercised in test and development paths inside
75     * this repository, but they MUST remain available to the packaged DevTools
76     * runtime for consumer projects that choose to use those capabilities.
77     *
78     * @var array<int, string>
79     */
80    public const array DEFAULT_PACKAGED_PROD_ONLY_IN_DEV_DEPENDENCIES = [
81        'phpspec/prophecy',
82        'phpspec/prophecy-phpunit',
83        'symfony/var-exporter',
84    ];
85
86    /**
87     * Creates the default Composer Dependency Analyser configuration.
88     *
89     * @param callable|null $customize optional callback to customize the configuration
90     * @param EnvironmentInterface|null $environment optional environment reader used to resolve overrides
91     *
92     * @return Configuration the configured analyser configuration
93     */
94    public static function configure(
95        ?callable $customize = null,
96        ?EnvironmentInterface $environment = null,
97    ): Configuration {
98        $environment ??= new Environment();
99        $configuration = new Configuration();
100
101        if (! self::shouldShowShadowDependencies($environment)) {
102            self::applyIgnoresShadowDependencies($configuration);
103        }
104
105        if (DevToolsPathResolver::isRepositoryCheckout()) {
106            self::applyPackagedRepositoryIgnores($configuration);
107        }
108
109        if (null !== $customize) {
110            $customize($configuration);
111        }
112
113        return $configuration;
114    }
115
116    /**
117     * The default configuration ignores shadow dependencies because Fast
118     * Forward packages MAY intentionally require dependency groups. For example,
119     * ecosystem or meta packages can require related PSR or framework packages
120     * so consumers do not need to install every package one by one.
121     *
122     * @param Configuration $configuration the analyser configuration to customize
123     *
124     * @return Configuration the modified configuration with shadow dependencies ignored
125     */
126    public static function applyIgnoresShadowDependencies(Configuration $configuration): Configuration
127    {
128        $configuration->ignoreErrors([ErrorType::SHADOW_DEPENDENCY]);
129
130        return $configuration;
131    }
132
133    /**
134     * Determines whether shadow dependency reports SHOULD remain visible.
135     *
136     * @param EnvironmentInterface|null $environment optional environment reader used to resolve overrides
137     *
138     * @return bool
139     */
140    public static function shouldShowShadowDependencies(?EnvironmentInterface $environment = null): bool
141    {
142        $environment ??= new Environment();
143
144        return '1' === $environment->get(self::ENV_SHOW_SHADOW_DEPENDENCIES);
145    }
146
147    /**
148     * Applies the ignores required only by the packaged DevTools repository.
149     *
150     * @param Configuration $configuration the analyser configuration to customize
151     *
152     * @return Configuration the modified configuration with packaged repository ignores applied
153     */
154    public static function applyPackagedRepositoryIgnores(Configuration $configuration): Configuration
155    {
156        $configuration->ignoreErrorsOnExtension('ext-pcntl', [ErrorType::SHADOW_DEPENDENCY]);
157        $configuration->ignoreErrorsOnPackages(
158            self::DEFAULT_PACKAGED_UNUSED_DEPENDENCIES,
159            [ErrorType::UNUSED_DEPENDENCY]
160        );
161        $configuration->ignoreErrorsOnPackages(
162            self::DEFAULT_PACKAGED_PROD_ONLY_IN_DEV_DEPENDENCIES,
163            [ErrorType::PROD_DEPENDENCY_ONLY_IN_DEV],
164        );
165
166        return $configuration;
167    }
168}