├── .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 | --------------------------------------------------------------------------------