Installation

Back to the README

Install the package

composer require --dev festi-team/coding-standard

The package is published on the Festi Satis mirror every Festi composer.json already lists:

"repositories": [
    { "type": "composer", "url": "https://packages.festi.io/" }
]

Allow the Composer plugin. The standard registers itself with phpcs through a Composer plugin, and Composer refuses to run a plugin the root project has not allowed. Skipping this is the usual reason --standard=Festi "does not exist":

"config": {
    "allow-plugins": {
        "dealerdirect/phpcodesniffer-composer-installer": true
    }
}

Check the install: vendor/bin/phpcs -i must list Festi. There is no --config-set installed_paths step.

One install brings the whole toolchain: vendor/bin/phpcs, vendor/bin/phpmd, vendor/bin/phan, vendor/bin/festi-quality and vendor/bin/festi-phpcs-diff.

Requirement Constraint Note
PHP >=8.1 Phan 6 needs it. A project on 8.0 gets a Composer resolution error.
squizlabs/php_codesniffer ^3.7.1 \|\| ^4.0 The rules report identically on both majors.
phan/phan ^6.0 Phan 5 crashes on current PHP versions.
ext-ast suggested Without it, pass --allow-polyfill-parser to Phan: slower, but it works. Install it on runners that analyse large projects.

Set up Phan

Copy the template, edit the two lines marked EDIT, and run:

mkdir -p .phan
cp vendor/festi-team/coding-standard/phan/project-config.dist.php .phan/config.php
vendor/bin/phan --config-file .phan/config.php

The template merges the shared baseline with the project's own source directories and enables the Festi plugins. To write it by hand:

$base = require __DIR__.'/../vendor/festi-team/coding-standard/phan/config.php';

return array_merge($base, [
    // Keep the baseline's entry: the bundled stubs live inside the package,
    // and array_merge replaces this key rather than appending to it.
    'directory_list' => array_merge($base['directory_list'], [
        'src',
        'vendor/festi-team',
    ]),
]);

The same applies to plugins: array_merge replaces the key, so the project's list is the only place a plugin is enabled. Configuration covers tuning and baselines.

Set up SonarQube

Add sonar-project.properties to the project root:

sonar.projectKey=com.festi:<project>
sonar.projectName=festi/<project>

sonar.sources=./src/
sonar.tests=./tests
sonar.exclusions=tests/**,vendor/**

sonar.language=php

The scan itself runs in the project's pipeline. festi-quality only reads what the last scan found, and needs SONAR_TOKEN, plus SONAR_HOST_URL unless the properties file sets sonar.host.url.

Add the pipeline jobs

See GitLab CI.

Migrating an existing project

  1. composer require --dev festi-team/coding-standard and add the allow-plugins entry above.
  2. Delete the project's own copy of the standard: a .phan/ruleset.xml (a phpcs ruleset that lived in the Phan directory) or a vendored .phpcs/Festi directory.
  3. Set up Phan from the template, as above.
  4. Replace the project's style job with the include: from GitLab CI, and set FESTI_RUNNER_TAG.

Expect the full-tree run to go from green to a large report. It was green because the rules were not running. Do not try to fix the backlog in one merge request: gate on changed lines (festi-phpcs-diff), and work the backlog down as files are edited. Configuration describes the options.

One conflict to expect: festi-team/festi-framework-async pins phan/phan: 4.x, which does not resolve against this package's ^6.0. The pin has to be bumped as part of adoption.

Using it without Composer

Composer is the supported path. A git submodule works for the phpcs standard alone, for a tool that analyses code with no vendor/ install:

git submodule add [email protected]:FestiCore/php_festi_codingstandard.git \
    vendor/php_festi_codingstandard

vendor/bin/phpcs --standard=vendor/php_festi_codingstandard/Festi/ruleset.xml \
    --extensions=php --ignore='vendor/**' ./src

Pointing --standard at ruleset.xml needs no installed_paths for the Festi sniffs. The cognitive-complexity rule comes from slevomat/coding-standard, which phpcs must be told about when Composer did not register it: add --runtime-set installed_paths <path to slevomat>. festi-quality and festi-phpcs-diff need the Composer autoloader, so they are Composer-only.