├── .github
└── dependabot.yml
├── .gitignore
├── CHANGELOG.md
├── README.md
├── composer.json
├── grumphp.yml.dist
├── phpcs.xml.dist
├── phpmd.xml.dist
├── phpstan.neon.dist
├── resources
├── grumpy.txt
├── happy-ext.txt
├── happy-large.txt
└── happy.txt
└── src
└── Composer
└── AxelerantDQCPlugin.php
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: "composer"
4 | directory: "/"
5 | schedule:
6 | interval: "weekly"
7 | # Use Indian Standard Time (UTC +05:30)
8 | timezone: "Asia/Kolkata"
9 | time: "09:00"
10 | versioning-strategy: auto
11 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | composer.lock
2 | /vendor/
3 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | ## 1.2.0 / 2021-10-31
4 |
5 | * Add a branch alias for 1.0.x
6 | * Enable a PHP 8 compatible version of TwigCS to be installed
7 | * Exclude "\Drupal\Core\Render\Element\Checkboxes" class of PHPMD StaticAccess rule (#17)
8 | * Exclude "\Drupal\Component\Plugin\Factory\DefaultFactory" static access
9 | * Exclude "\Drupal\Core\Site\Settings" static access
10 | * Add common ignores to PHPCS
11 | * Modify readme file to change syntax for copying all dist files
12 | * Explicitly set twigcs ruleset
13 | * Exclude MissingImport from cleancode rules
14 |
15 | ## 1.1.0 / 2020-11-06
16 |
17 | * Allow more versions of phpcpd to be installed
18 | * Allow twigcs 4.0 to be used
19 | * Remove composer from require-dev
20 | * Fixes #6. Use GrumPHP stable version release
21 | * Merge pull request #5 from mohit-rocks/master
22 | * Adding support for twigcs so it gets automatically downloaded
23 |
24 | ## 1.0.0 / 2020-07-12
25 |
26 | * Replace abandoned package with replacement
27 | * Add video of upgrade to README
28 |
29 | ## 1.0.0-beta9 / 2020-06-10
30 |
31 | * Update README for changes from GrumPHP 0.19
32 | * Introduce smaller versions of ASCII art
33 | * Move to grumphp-shim's latest version (**breaking release**, read documentation)
34 |
35 | ## 1.0.0-beta8 / 2020-06-10
36 |
37 | * Update phpcs.xml.dist with one matching Drupal core
38 |
39 | ## 1.0.0-beta7 / 2020-04-24
40 |
41 | * Move composer to require-dev
42 |
43 | ## 1.0.0-beta6 / 2020-04-21
44 |
45 | * Use the scaffold plugin to copy files
46 | * Upgrade to GrumPHP 0.18
47 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Package for Drupal Code Quality presets
2 |
3 | This has been customised from [vijaycs85/drupal-quality-checker](https://packagist.org/packages/vijaycs85/drupal-quality-checker) for Axelerant needs. Apart from a different template file, it uses the Axelerant logo.
4 |
5 | ## Installation
6 |
7 | _Upgrading from Beta 8?_ Read [the instructions for changes](#upgrading-from-beta-8) you need to make to grumphp.yml.dist.
8 |
9 | ```bash
10 | composer require --dev axelerant/drupal-quality-checker
11 | ```
12 |
13 | This will add the plugin to your project and copy the default configuration files. These files are:
14 |
15 | * grumphp.yml.dist
16 | * phpcs.xml.dist
17 | * phpmd.xml.dist
18 | * phpstan.neon.dist
19 |
20 | Since these are `.dist` files, the plugin will overwrite them on every `composer install`. If you mean to customize the default settings, then we recommend that you rename them to remove the `.dist` suffix. As such, it is a good idea to add these `.dist` files to your `.gitignore` file.
21 |
22 | ## Usage
23 |
24 | No additional steps required, but if git hooks aren't fired, run `php ./vendor/bin/grumphp git:init`. For additional commands, look at [grumhp's documentation](https://github.com/phpro/grumphp/blob/master/doc/commands.md).
25 |
26 | ## Customising
27 |
28 | Almost all customising begins with first copying the `grumphp.yml.dist` file to your project. Make sure you have the file.
29 |
30 | ### Adding tasks
31 |
32 | There are various tasks you can add and customise in your grumphp.yml. Read the [online documentation for GrumPHP tasks](https://github.com/phpro/grumphp/blob/master/doc/tasks.md) to see the tasks you can use and configure.
33 |
34 | ### Forcing commit message format
35 |
36 | To configure commit message structure, use the [git_commit_message task](https://github.com/phpro/grumphp/blob/master/doc/tasks/git_commit_message.md). For example, to enforce the commit message contains the Jira issue ID, use the rule as the following snippet. More options are [documented online](https://github.com/phpro/grumphp/blob/master/doc/tasks/git_commit_message.md).
37 |
38 | ```yaml
39 | # grumphp.yml
40 | grumphp:
41 | tasks:
42 | git_commit_message:
43 | matchers:
44 | Must contain issue number: /JIRA-\d+/
45 | ```
46 |
47 | ### Disable commit banners
48 |
49 | GrumPHP supports banners to celebrate (or scold) on your commit. This is fun but it is possible it gets on your nerves. If you don’t want it, edit the grumphp.yml file and replace the following parameters:
50 |
51 | ```yaml
52 | # grumphp.yml
53 | grumphp:
54 | ascii: ~
55 | ```
56 |
57 | You could even disable specific ones like this:
58 |
59 | ```yaml
60 | # grumphp.yml
61 | grumphp:
62 | ascii:
63 | succeeded: ~
64 | ```
65 |
66 | ### Overwrite phpmd ruleset
67 |
68 | Copy the ruleset to the project root first
69 |
70 | ```bash
71 | cp vendor/axelerant/drupal-quality-checker/phpmd.xml.dist phpmd.xml
72 | ```
73 |
74 | Edit it as per your needs and commit. Remember to modify the grumphp.yml file with the new path.
75 |
76 | ```yaml
77 | # grumphp.yml
78 | grumphp:
79 | tasks:
80 | phpmd:
81 | ruleset: ['phpmd.xml']
82 | ```
83 |
84 | ### Customise phpcs rules
85 |
86 | Copy the ruleset to the project root first
87 |
88 | ```bash
89 | cp vendor/axelerant/drupal-quality-checker/phpcs.xml.dist phpcs.xml
90 | ```
91 |
92 | Edit it as per your needs and commit. Remember to modify the grumphp.yml file with the new path.
93 |
94 | ```yaml
95 | # grumphp.yml
96 | grumphp:
97 | tasks:
98 | phpcs:
99 | standard: ['phpcs.xml']
100 | ```
101 |
102 | ### Customise phpstan rules
103 |
104 | Copy the ruleset to the project root first
105 |
106 | ```bash
107 | cp vendor/axelerant/drupal-quality-checker/phpstan.neon.dist phpstan.neon
108 | ```
109 |
110 | Edit it as per your needs and commit. Remember to modify the grumphp.yml file with the new path.
111 |
112 | ```yaml
113 | # grumphp.yml
114 | grumphp:
115 | tasks:
116 | phpstan:
117 | configuration: phpstan.neon
118 | ```
119 |
120 | ## More about scaffolding
121 |
122 | As described before, this package uses [`drupal/core-composer-scaffold`](https://github.com/drupal/core-composer-scaffold) plugin to scaffold a few files to the project root. This is not required but there is a good chance you are already using it if you're building a Drupal site.
123 |
124 | The scaffolding operation runs with every composer operation and overwrites files. Only the file `grumphp.yml.dist` is not overwritten during subsequent operations. If you are customising any of the other configuration files and don't want the updates to overwrite your changes, you can override the behaviour in your composer.json file. For example, to skip `phpmd.xml.dist` from being overwritten, add this to your `composer.json`:
125 |
126 | ```json
127 | "name": "my/project",
128 | ...
129 | "extra": {
130 | "drupal-scaffold": {
131 | "file-mapping": {
132 | "[project-root]/phpmd.xml.dist": false
133 | }
134 | }
135 | }
136 | ```
137 |
138 | For more details, read the ["Excluding Scaffold files"](https://github.com/drupal/core-composer-scaffold#excluding-scaffold-files) section of the [documentation](https://github.com/drupal/core-composer-scaffold/blob/8.8.x/README.md) for the core-composer-scaffold plugin.
139 |
140 | ## Upgrading from Beta 8
141 |
142 | GrumPHP 0.19 introduced [a breaking change](https://github.com/phpro/grumphp/releases/tag/v0.19.0) to the structure of the YAML file. The template in this repository is updated as per the new structure. However, you would need to change the YML files on your projects before you update to Beta 9 or later.
143 |
144 | Fortunately, the change is simple and in many cases would only require a one line change. Rename the `parameters` section to `grumphp`. Our default template contains two parameters which still need to remain under `parameters`. They are `git_dir` and `bin_dir`. Look at [the diff of the change](https://github.com/axelerant/drupal-quality-checker/commit/e8d9414ce6ea046b0386115764db68e5251d8a58#diff-94c8df1b4af91d80f7417cad14bbe0e5) to understand what needs to be changed in your grumphp.yml file. Also, read more at the [release page for GrumPHP 0.19](https://github.com/phpro/grumphp/releases/tag/v0.19.0).
145 |
146 | Lastly, you can [watch this video](https://youtu.be/XoFJfBcZF58) where I upgrade this on a project. Link: https://youtu.be/XoFJfBcZF58
147 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "axelerant/drupal-quality-checker",
3 | "type": "composer-plugin",
4 | "description": "Code quality checking tools for Drupal project.",
5 | "homepage": "https://github.com/axelerant/drupal-quality-checker",
6 | "license": "proprietary",
7 | "authors": [
8 | {
9 | "name": "Hussain Abbas",
10 | "role": "Maintainer"
11 | }
12 | ],
13 | "require": {
14 | "composer-plugin-api": "^2.0",
15 | "dealerdirect/phpcodesniffer-composer-installer": "*",
16 | "drupal/coder": "^8.3.7",
17 | "friendsoftwig/twigcs": "^4.0 || ^5.0 || ^6.0",
18 | "mglaman/phpstan-drupal": "^1.2 || ^2.0",
19 | "php-parallel-lint/php-parallel-lint": "^1.2",
20 | "phpcompatibility/php-compatibility": "^9.0",
21 | "phpmd/phpmd": "^2.8",
22 | "phpro/grumphp-shim": "^2.0"
23 | },
24 | "support": {
25 | "issues": "https://github.com/axelerant/drupal-quality-checker/issues",
26 | "source": "https://github.com/axelerant/drupal-quality-checker"
27 | },
28 | "config": {
29 | "sort-packages": true,
30 | "allow-plugins": {
31 | "phpro/grumphp-shim": true,
32 | "dealerdirect/phpcodesniffer-composer-installer": true
33 | }
34 | },
35 | "extra": {
36 | "branch-alias": {
37 | "dev-main": "1.0.x-dev"
38 | },
39 | "class": "AxelerantDQC\\Composer\\AxelerantDQCPlugin"
40 | },
41 | "autoload": {
42 | "psr-4": {
43 | "AxelerantDQC\\": "src"
44 | }
45 | },
46 | "require-dev": {
47 | "composer/composer": "^2.7"
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/grumphp.yml.dist:
--------------------------------------------------------------------------------
1 | parameters:
2 | git_dir: .
3 | bin_dir: vendor/bin
4 | grumphp:
5 | ascii:
6 | failed: vendor/axelerant/drupal-quality-checker/resources/grumpy.txt
7 | succeeded: vendor/axelerant/drupal-quality-checker/resources/happy.txt
8 | tasks:
9 | phplint:
10 | exclude:
11 | - web/core
12 | - web/modules/contrib
13 | - web/themes/contrib
14 | - web/profiles/contrib
15 | - web/sites/default
16 | - vendor
17 | triggered_by:
18 | - php
19 | - module
20 | - theme
21 | - inc
22 | yamllint: ~
23 | composer: ~
24 | jsonlint: ~
25 | twigcs:
26 | path: 'web'
27 | ruleset: 'FriendsOfTwig\Twigcs\Ruleset\Official'
28 | exclude:
29 | - core
30 | - modules/contrib
31 | - themes/contrib
32 | - profiles/contrib
33 | phpcs:
34 | standard:
35 | - phpcs.xml.dist
36 | ignore_patterns:
37 | - /\.github
38 | - /\.gitlab
39 | - /\.ddev
40 | - /^config\/(.*)/
41 | - /drush
42 | - /^web\/sites\/default/
43 | triggered_by:
44 | - php
45 | - module
46 | - inc
47 | - install
48 | - test
49 | - profile
50 | - theme
51 | - css
52 | - info
53 | phpmd:
54 | whitelist_patterns:
55 | - /^web\/modules\/custom\/(.*)/
56 | - /^web\/themes\/custom\/(.*)/
57 | ruleset:
58 | - phpmd.xml.dist
59 | triggered_by:
60 | - php
61 | - module
62 | - theme
63 | phpstan:
64 | configuration: phpstan.neon.dist
65 | ignore_patterns:
66 | - /\.github
67 | - /\.gitlab
68 | - /\.ddev
69 | - /^config\/(.*)/
70 | - /drush
71 | - /^web\/sites\/default/
72 | triggered_by:
73 | - php
74 | - module
75 | - theme
76 | - inc
77 | memory_limit: "-1"
78 | use_grumphp_paths: true
79 |
--------------------------------------------------------------------------------
/phpcs.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 | Axelerant baseline rules for PHP CodeSniffer
9 |
10 |
11 | */bower_components/*
12 | */node_modules/*
13 |
14 | ./assets/vendor/*
15 |
16 | .
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | settings(\.[a-zA-Z0-9]+)?\.php
25 |
26 |
27 |
28 |
29 | settings(\.[a-zA-Z0-9]+)?\.php
30 |
31 |
32 | settings(\.[a-zA-Z0-9]+)?\.php
33 |
34 |
35 | settings(\.[a-zA-Z0-9]+)?\.php
36 |
37 |
38 | settings(\.[a-zA-Z0-9]+)?\.php
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
63 |
65 |
66 |
67 |
68 |
69 |
70 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 | *.yml
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 | 0
196 |
197 |
198 | 0
199 |
200 |
201 | 0
202 |
203 |
204 | 0
205 |
206 |
207 |
208 |
209 |
210 |
213 |
214 |
215 | 0
216 |
217 |
218 | 0
219 |
220 |
221 |
222 | 0
223 |
224 |
225 | 0
226 |
227 |
228 | 0
229 |
230 |
231 | 0
232 |
233 |
234 | 0
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 | 0
255 |
256 |
257 | 0
258 |
259 |
260 | 0
261 |
262 |
263 | 0
264 |
265 |
266 | 0
267 |
268 |
269 | 0
270 |
271 |
272 | 0
273 |
274 |
275 | 0
276 |
277 |
278 | 0
279 |
280 |
281 | 0
282 |
283 |
284 | 0
285 |
286 |
287 |
288 |
289 | 0
290 |
291 |
292 | 0
293 |
294 |
295 | 0
296 |
297 |
298 |
299 |
300 | 0
301 |
302 |
303 | 0
304 |
305 |
306 |
307 | 0
308 |
309 |
310 | 0
311 |
312 |
313 |
314 | 0
315 |
316 |
317 | 0
318 |
319 |
320 | 0
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 | 0
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
--------------------------------------------------------------------------------
/phpmd.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 | Custom ruleset for Drupal projects at Axelerant
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/phpstan.neon.dist:
--------------------------------------------------------------------------------
1 | includes:
2 | - vendor/mglaman/phpstan-drupal/extension.neon
3 | - vendor/mglaman/phpstan-drupal/rules.neon
4 | parameters:
5 | customRulesetUsed: true
6 |
--------------------------------------------------------------------------------
/resources/grumpy.txt:
--------------------------------------------------------------------------------
1 | ___ _ __ _ __ ___ _ __
2 | / _ \ '__| '__/ _ \| '__|
3 | | __/ | | | | (_) | |
4 | \___|_| |_| \___/|_|
5 |
--------------------------------------------------------------------------------
/resources/happy-ext.txt:
--------------------------------------------------------------------------------
1 | ,
2 |
3 | ╠▒
4 |
5 | ╠▒╖
6 |
7 | ╔ ╚╠▒╖
8 |
9 | ╚▒╖ ╠╠╠╬ε
10 |
11 | @▒╖ ╠╠µ╠╠╠╠╙
12 |
13 | ╙╠╠╬╠╠╠╠╠╬
14 |
15 | ╚╠╠╠╗ `╬╠╠╠╠╠╩
16 |
17 | └╠╠╠╬, ╚╠╠╠╙
18 |
19 | ╚╠╠╠▒ `╬
20 |
21 | └╠╠╠╬ç
22 |
23 | ╠╠╠╠▒
24 |
25 | ╬╠╠╠╩
26 |
27 | ,╬╠╠╠╙ φ
28 |
29 | ╔╠╠╠╬ ╬╠╠ε
30 |
31 | ╬╠╠╠╩ ╚╠╠╠▒
32 |
33 | ╓╬╠╠╠` `╬╠╠╠ε
34 |
35 | ╚╠╠╠▒
36 |
37 |
--------------------------------------------------------------------------------
/resources/happy-large.txt:
--------------------------------------------------------------------------------
1 | /
2 | /
3 | ///
4 | ///*
5 | ////*
6 | /////
7 | //////
8 | //////,
9 | ///////*
10 | // ////////
11 | /// /////////*
12 | ////* ,//////////
13 | ,////// ///////////*
14 | ./ /////// *///////////
15 | //// *////// ////////////
16 | /////// *//////*////////////
17 | //////// //////////////////*
18 | ,/////////////////////////*
19 | ///////////////////////
20 | //////////// /////////////////////
21 | //////////// *//////////////////
22 | ////////////, ,///////////////*
23 | //////////// /////////////
24 | //////////// *//////////
25 | *//////////// ////////
26 | //////////// //////
27 | ////////////* //*
28 | ,//////////// *
29 | ////////////.
30 | ////////////*
31 | ////////////
32 | ////////////,
33 | /////////////
34 | ////////////*
35 | ,////////////
36 | *////////////
37 | ///////////// *
38 | ////////////, ///
39 | //////////// /////
40 | //////////// ///////*
41 | ////////////* ,//////////
42 | ////////////, ////////////
43 | //////////// ,////////////
44 | ,//////////// ////////////
45 | *///////////* ////////////.
46 | ////////////* ,////////////
47 | //////////// ////////////
48 | ////////////.
49 | ////////////
50 | ////////////
51 |
--------------------------------------------------------------------------------
/resources/happy.txt:
--------------------------------------------------------------------------------
1 | /
2 | //
3 | //
4 | * .///
5 | // /////
6 | /// ////////
7 | #//// /////////
8 | ///// //////
9 | ///// (//
10 | #////\ *
11 | /////
12 | /////
13 | ///// //
14 | ///// ////
15 | ///// /////
16 | /////
--------------------------------------------------------------------------------
/src/Composer/AxelerantDQCPlugin.php:
--------------------------------------------------------------------------------
1 | composer = $composer;
35 | $this->io = $io;
36 | }
37 |
38 | /**
39 | * {@inheritdoc}
40 | */
41 | public function deactivate(Composer $composer, IOInterface $io): void
42 | {
43 |
44 | }
45 |
46 | /**
47 | * {@inheritdoc}
48 | */
49 | public function uninstall(Composer $composer, IOInterface $io): void
50 | {
51 |
52 | }
53 |
54 | /**
55 | * Attach package installation events. Priority of 10 is added to tigger it before GrumPHP plugin.
56 | *
57 | * {@inheritdoc}
58 | */
59 | public static function getSubscribedEvents(): array
60 | {
61 | return [
62 | ScriptEvents::POST_INSTALL_CMD => ['copyFilesToProjectRoot', 10],
63 | ScriptEvents::POST_UPDATE_CMD => ['copyFilesToProjectRoot', 10],
64 | ];
65 | }
66 |
67 | /**
68 | * Copies configuration files to the project root directory.
69 | *
70 | * @param Event $event The Composer event.
71 | */
72 | public function copyFilesToProjectRoot(Event $event): void
73 | {
74 | $destination = $this->locateProjectRoot();
75 | if ($destination === FALSE) {
76 | $this->io->writeError('Copying configuration file failed. Unable to determine project root dir. Please copy configuration files manually.');
77 | return;
78 | }
79 | $pluginDirectory = realpath(__DIR__ . '/../../');
80 |
81 | // Copy each file to the project root.
82 | $configFiles = ['grumphp.yml.dist', 'phpcs.xml.dist', 'phpmd.xml.dist', 'phpstan.neon.dist'];
83 | foreach ($configFiles as $filename) {
84 | $sourcePath = $pluginDirectory . '/' . $filename;
85 | $destinationPath = $destination . '/' . $filename;
86 | if (file_exists($destinationPath)) {
87 | $this->io->write('Configuration file ' . $filename . ' is overwritten. Please watchout for any change!');
88 | }
89 | copy($sourcePath, $destinationPath);
90 | }
91 | $this->io->write('Configuration files are copied successfully.');
92 | }
93 |
94 | /**
95 | * Locates the project root path.
96 | *
97 | * Since there is no API available in Composer to directly retrieve the project root path,
98 | * we rely on the presence of `composer.json` in the directory to guess the project root.
99 | * GrumPHP also utilizes a similar approach to identify the project root.
100 | *
101 | * @return string|bool The project root path or FALSE if not found.
102 | */
103 | private function locateProjectRoot(): string|bool {
104 | $paths = [
105 | getcwd(),
106 | dirname($this->composer->getConfig()->get('bin-dir'), 2),
107 | dirname($this->composer->getConfig()->get('vendor-dir'), 1),
108 | ];
109 | return $this->guessPath($paths, 'composer.json');
110 | }
111 |
112 | /**
113 | * Builds a path.
114 | *
115 | * @param string $baseDir The base directory.
116 | * @param string $path The path.
117 | * @return string The built path.
118 | */
119 | private function buildPath(string $baseDir, string $path): string
120 | {
121 | return $baseDir.DIRECTORY_SEPARATOR.$path;
122 | }
123 |
124 | /**
125 | * Guesses the path using the filename.
126 | *
127 | * @param array $paths The paths to search.
128 | * @param string $filename The filename to search for.
129 | * @return string|bool The guessed path or FALSE if not found.
130 | */
131 | private function guessPath(array $paths, string $filename): string|bool
132 | {
133 | $paths = array_filter($paths);
134 |
135 | foreach ($paths as $path) {
136 | if (!is_dir($path)) {
137 | continue;
138 | }
139 |
140 | $filePath = $this->buildPath($path, $filename);
141 | if (file_exists($filePath)) {
142 | return $path;
143 | }
144 | }
145 | return FALSE;
146 | }
147 |
148 | }
149 |
--------------------------------------------------------------------------------