This directory contains some files that can be used for CiviCRM extensions.
It provides configurations for PHP_CodeSniffer, PHPStan, and PHPUnit (via Symfony PHPUnit Bridge). Additionally there are workflows to run this tools in GitHub actions. The worklows are configured to run on git push (might be changed).
(Note: The tools are installed in individual directories to avoid potential conflicting requirements.)
Apart from that it contains the basic files to start a documentation with MkDocs.
In addition there are the following helper scripts:
tools/create-release.shHelps to create a new release of the extension.tools/update-pot.shExtracts translatable strings and updates the.potfile.
See the help of the scripts for more details.
This template allows to add civicrm/civicrm-core as requirement to the
composer.json to specify the minimum required CiviCRM version as well as other
CiviCRM extensions that are available as composer package. This makes it
possible to install a CiviCRM extension via composer with all its
dependencies. When running composer update in the extension directory itself,
the installation of civicrm/civicrm-core and CiviCRM extensions is
prevented.
To install/update the files from this template into an existing or newly
created CiviCRM extension first make sure that the info.xml is up to date.
Then run:
./install.sh <extension directory> [<file or directory in extension template> ...]This will copy all non template files (excluding this file and install.sh
itself) to the extension directory. In files with the extension .template
the placeholders will be replaced appropriately and the extension will be
dropped. If files are specified only those will be installed.
Only the file phpstan.neon.template won't be renamed, but just copied.
If a file already exists you'll be asked how to proceed. So it is safe to run this script in any case. You might also want to run this script after a file of this template has been updated.
(Hint: You might want to use the option --update. See script usage for
details via install.sh --help.)
The script automatically executes
tools/git/init-hooks.sh to initialize the git
hooks.
After running install.sh:
-
Change the vendor name systopia in
composer.jsonif necessary. -
Copy
phpstan.neon.templatetophpstan.neonand replace the placeholder{VENDOR_DIR}with the vendor-path of the root composer project. -
Adapt
php-versionsin.github/workflows/phpstan.yml- Recommendation: Earliest and latest supported minor version of each supported major version.
-
If elements from
civicrm/civicrm-packagesare used in your extension,scanFilesorscanDirectoriesin the phpstan configuration might need to be adapted. -
Adjust the directories to analyze in
phpstan.neon.distandphpcs.xml.dist.- Remove directories if not existent, e.g.
api. - Add directories like
angif used. (Note: The directorymanagedusually should be added only tophpstan.neon.distbecause the code exported by CiviCRM doesn't match all rules inphpcs.xml.dist.)
- Remove directories if not existent, e.g.
-
If you have (or plan to have) dependencies in the extension's
composer.jsonadd the following code to{EXT_SHORT_NAME}.php:function _{EXT_SHORT_NAME}_composer_autoload(): void { if (file_exists(__DIR__ . '/vendor/autoload.php')) { require_once __DIR__ . '/vendor/autoload.php'; } }
Call this function at the beginning of
{EXT_SHORT_NAME}_civicrm_config()and{EXT_SHORT_NAME}_civicrm_container()(if used).
Additionally, in some cases it makes sense to replace README.md with a symlink
to docs/index.md. (Usually if both files would contain basically the same
information.)
Now install the different tools (might be run later for updates of the tools as well):
composer composer-tools updateIf this template already exists in a freshly cloned repository, you need to initialize the git hooks and install the various tools.
To initialize the git hooks execute
./tools/git/init-hooks.shThe following steps are necessary in order to get the composer-tools running
again:
- Copy
phpstan.neon.templatetophpstan.neonand replace the placeholder{VENDOR_DIR}with the vendor-path of the root composer project.
Install all project dependencies, that are listed in the repos composer.json
file (if there are any) either in the extension directory or in the root
composer.json. They are necessary for phpstan to resolve symbols of external
library code:
composer update # or add requirements to root composer.jsonInstall composer-tools in order to locally run phpcs, phpcbf, phpstan
and phpunit.
composer composer-tools updateMake sure that in your local CiviCRM instance, all those extensions have been
installed, that the current project is depending on (if there are any).
Otherwise, phpstan may complain about missing symbols.
Run the tests with composer test or each tool on its own:
composer phpcs
composer phpstan
composer phpunitTo fix code style issues with phpcbf run composer phpcbf.
If you add this template to an existing extension it might lead to many errors and warnings that you cannot handle immediately. Here you can find some recommendations for that case. Make sure the tests run successfully before enabling them in the CI system (GitHub Actions).
Recommended approach:
- Fix style violations automatically with
composer phpcbf. - Run
composer phpcsand fix the remaining issues by hand. - If there are still too many issues to handle immediately:
- Ignore parts of files (be specific about ignored sniffs, if possible).
- Exclude files or directories from validation in
phpcs.xml.dist.
In general it should be shortly mentioned when validation is disabled for that reason.
Recommended approach:
- Run phpstan with the lowest level (
composer run -- phpstan --level=0) and fix the reported errors. - Gradually increase the level and fix the reported errors until the important issues are fixed or the number of messages is overwhelming.
- Create a baseline for the
remaining errors:
- Run
composer run -- phpstan --generate-baseline. - Include
phpstan-baseline.neoninphpstan.neon.dist:
includes: - phpstan-baseline.neon - Run
Consider opening an issue saying that errors in the baseline should be checked.
If any tool reports an error or warning it has to be resolved!
In case it's a false positive or there exists no practicable way to resolve it, errors can be ignored.
Errors reported by phpcs can be ignored with // phpcs:ignore <sniffs> above
the problematic line. See the
manual
for more details. If you make use of // phpcs:disable <sniffs> always enable
the sniffs again with // phpcs:enable. (Always state the ignored sniffs.)
Errors reported by phpstan can be ignored with // @phpstan-ignore <error identifiers> above the problematic line. See the
manual for more details.
(Always state the ignored error identifiers and don't use
// @phpstan-ignore-next-line.)
Add an explanation if it's not obvious why an error is ignored.
In some cases it might make sense to ignore errors in the phpstan.neon.dist
configuration
file.
Though the ignored errors should always be as specific as possible, i.e. actual
issues must never be covered that way.
It is possible to test GitHub actions for phpcs and phpstan locally using
nektos/act and
shivammathur/node docker
images:
act -P ubuntu-latest=shivammathur/node:latest -j phpcs
act -P ubuntu-latest=shivammathur/node:latest -j phpstan
# Network "bridge" is necessary to start MySQL service in the container.
# (act uses host network by default.)
act -P ubuntu-latest=shivammathur/node:latest -j phpunit --network bridgeIt is possible to limit the matrix like this:
act workflow_dispatch -P ubuntu-latest=shivammathur/node:latest -j phpstan --matrix php-versions:8.4 --matrix prefer:prefer-stableThe phpunit workflow allows to specify a composer version constraint for CiviCRM
in the workflow_dispatch trigger:
act workflow_dispatch -P ubuntu-latest=shivammathur/node:latest -j phpunit --network bridge --input civicrm-version="6.7.8"act might be installed via Homebrew.
PhpStorm allows only one phpcs and phpstan configuration per project. If you have a project with multiple CiviCRM extensions you might use the scripts in https://github.com/systopia/phpstorm-scripts
If the CiviCRM extension depends on other extensions they have to be installed
when running phpunit and also phpstan, if it directly uses code from another
extension. The following describes how to handle that case. The placeholder
{OTHER} represents the name of the other extension.
When running as GitHub action the code of the other extension has to be
available. In the best case they can be installed via composer. Otherwise, the
run part of the Install dependencies step in .github/workflows/phpstan.yml
has to be modified accordingly. To use the base branch of an extension developed
on GitHub the additional line would look like this:
git clone --depth=1 https://github.com/{ORGANIZATION}/{OTHER}.git ../{OTHER}To test with different versions when a dependent extension cannot be installed
via composer ${{ matrix.prefer }} could be checked:
if [ "${{ matrix.prefer }}" = "prefer-lowest" ]; then
git clone ...
else
git clone ...
fi- Add
../{OTHER}toscanDirectoriesinphpstan.neon.dist.
Note: Depending on which code is used it might be enough to only scan a
subfolder of the other extension e.g. Civi.
It has to be ensured that dependent extensions are available in the ext folder
when running phpunit. In the best case extensions can be installed via
composer. Otherwise, the run part of the Set up CiviCRM step in
.github/workflows/phpunit.yml has to be modified accordingly. For example
an extension can be fetched with cv ext:download:
cv ext:download "{OTHER}@https://github.com/{ORGANIZATION}/{OTHER}/releases/download/${OTHER}_VERSION/{OTHER}-${OTHER}_VERSION.zip"In this example the version is defined in the environment variable
{OTHER}_VERSION.
To test with different versions when a dependent extension cannot be installed
via composer ${{ matrix.prefer }} could be checked:
if [ "${{ matrix.prefer }}" = "prefer-lowest" ]; then
{OTHER}_VERSION=1.0.0
else
{OTHER}_VERSION=1.2.3
fiBasic files for a documentation with MkDocs are installed by this template.
When editing the documentation you can use mkdocs to verify the changes.
Ensure you have mkdocs installed (apt install mkdocs). Then you can run
mkdocs serve in the extension directory and open the URL printed on the
console. Changes will be applied immediately to the served website.
How to get the documentation up on docs.civicrm.org is explained in the developer guide.
The following files have to be adapted accordingly if the minimal PHP version changes:
info.xml:<php_compatibility>(if used)composer.json:composer require --no-update php:^{VERSION}.github/workflows/phpstan.yml.github/workflows/phpunit.yml
The following files have to be adapted accordingly if the minimal CiviCRM version changes:
info.xml:<compatiblity>composer.json:composer require --no-update civicrm/civicrm-core:>={VERSION} civicrm/civicrm-packages:>={VERSION}
To test with the latest version of PHP the following files have to be adapted accordingly, if a new version of PHP (minor or major) is released:
.github/workflows/phpstan.yml.github/workflows/phpunit.yml