Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • documentation/docs/dev
  • totten/dev
  • bgm/dev
  • ivan_compucorp/dev
  • seamuslee/dev
  • artfulrobot/dev
  • ufundo/dev
  • wmortada/dev
  • lucky091588/dev
  • DaveD/dev
  • jtwyman/dev
  • rukkykofi/dev
  • JonGold/dev
  • jaapjansma/developer-docs
  • alainb/dev
  • noah/dev
  • justinfreeman/dev
  • pradeep/dev
  • larssg/dev
  • eileen/dev
  • darrick/dev
  • mattwire/dev
  • colemanw/dev
  • homotechsual/dev
  • JoeMurray/dev
  • maynardsmith/dev
  • kurund/dev
  • rocxa/dev
  • AllenShaw/dev
  • bradleyt/dev
  • chrisgaraffa/dev
  • martin.w/dev
  • herbdool/dev
  • MattTrim1/dev
  • Detlev/dev
  • ErikHommel/dev
  • brienne/devdocs
  • pminf/dev
  • SarahFG/dev
  • ayduns/dev
  • JKingsnorth/dev
  • ginkgomzd/dev
  • nicol/dev
  • almeidam/dev
  • arthurm/dev
  • damilare/dev
  • semseysandor/dev
  • major/devdocs
  • usha.makoa/dev
  • yurg/dev
  • shaneonabike/dev
  • andie/dev
  • mmyriam/dev
  • gngn/dev
  • florian-dieckmann/dev
  • jade/dev
  • luke.stewart/dev
  • vinaygawade/dev
58 results
Show changes
# civi-test-run
`civi-test-run` is a script which runs one or more test suites locally. It is compatible with `civibuild`-based deployments.
## Installation
`civi-test-run` is included within [buildkit](buildkit.md).
## Usage
Run without arguments to see the exact usage:
```bash
$ civi-test-run
```
## Test types
The test type is one of:
- `all` - Run all standard CiviCRM test suites
- `karma` - Run the KarmaJS test suite
- `phpunit-api` - Run the `api_v3` test suite
- `phpunit-civi` - Run the `Civi/` test suite
- `phpunit-crm` - Run the `CRM` test suite
- `phpunit-e2e` - Run the `E2E` test suite
- `upgrade` - Run the upgrade test suite
# civibuild
Creating a full development environment for CiviCRM requires a lot of work, e.g.,
* Downloading / installing / configuring a CMS (Backdrop, Drupal, Joomla, WordPress).
* Downloading / installing / configuring CiviCRM.
* Configuring Apache and MySQL.
* Configuring file permissions on data folders.
* Configuring a headless test database for phpunit.
* Configuring Selenium to connect to Civi.
The *civibuild* command automates this process. It includes different build-types that are useful for core development, such as *drupal-clean* (a barebones Drupal+Civi site) and *wp-demo* (a WordPress+Civi site with some example content).
Note: There are a number of build tools on the market which can, e.g., create a Drupal web site (like [drush](http://drush.org/)) or WordPress web site (like [wp-cli](http://wp-cli.org/)). Civibuild does not aim to replace these. Unfortunately, such tools generally require extra work for a Civi developer environment. Civibuild works with these tools and and fills in missing parts.
## Build types
`civibuild` includes a small library of build scripts for different configurations.
For a list of available build-types as well as documentation on writing build scripts, see `app/config` within your buildkit installation.
For example, at time of writing, it includes:
* CiviCRM (standalone)
* `standalone-clean`: A clean "out of the box" installation of CiviCRM. (*Composer-first with private source-tree; more attuned to CiviCRM usage*)
* `standalone-dev`: A clean "out of the box" installation of CiviCRM. (*Git-first with public source-tree; more attuned to CiviCRM development*)
* __TIP__: _Both builds use a mix of `composer` and `git`. In the `dev` build, `git` is the __primary__ mechanism for switching versions/branches/patches. In the `clean` build, `composer` is primary. `composer` requires extra care for switching branches and publishing assets._
* CMS builds
* Backdrop
* `backdrop-clean`: A clean "out of the box" installation of CiviCRM.
* `backdrop-demo`: A demo site running CiviCRM.
* `backdrop-empty`: An empty site without CiviCRM. Useful for testing tarball installation.
* Drupal 7
* `drupal-clean`: Drupal 7 CMS: A clean "out of the box" installation of CiviCRM.
* `drupal-demo`: Drupal 7 CMS: A demo site running CiviCRM.
* `drupal-empty`: Drupal 7 CMS: An empty site without CiviCRM. Useful for testing tarball installation.
* Drupal 10
* `drupal10-clean`: A clean "out of the box" installation of CiviCRM. (Based on `drupal/recommended-project`)
* `drupal10-demo`: A demo site running CiviCRM. (Based on `drupal/recommended-project`)
* `drupal10-empty`: An empty site without CiviCRM. (Based on `drupal/recommended-project`)
* `drupal10-dod`: A minimalist build in the style of Drupal.org development. (Based on `drupal/drupal`)
* Joomla
* ~~`joomla-demo`~~: WIP/incomplete/broken.
* `joomla-empty`: Joomla CMS: An empty Joomla site (without CiviCRM). Useful for testing tarball installation.
* WordPress
* `wp-demo`: WordPress CMS: A demo site running WordPress and CiviCRM.
* `wp-empty`: WordPress CMS: An empty without CiviCRM. Useful for testing tarball installation.
* Special builds
* `cxnapp`: A self-signed CiviConnect app based on the reference implementation.
* `dist`: A website containing nightly builds akin to dist.civicrm.org. Useful for preparing CiviCRM tarballs.
* `distmgr`: A service which manages redirects and report-backs for the download site.
* `extdir`: A mock website akin to civicrm.org/extdir/ . Useful for testing the extension download process.
* `l10n`: WIP - A build environment for creating translation files.
* `messages`: A backend service for delivering in-app messages (eg "Getting Started").
* [`universe`](universe.md): A broad collection of publicly visible repos, extensions, infrastructure, etc.
Build types can be mixed/matched with different versions of Civi, e.g.,
```bash
$ civibuild create my-drupal-civimaster \
--type drupal-demo \
--civi-ver master \
--url http://my-drupal-civimaster.localhost
$ civibuild create my-drupal-civi5.38 \
--type drupal-demo \
--civi-ver 5.38 \
--url http://my-drupal-civi538.localhost
$ civibuild create my-wordpress-civi539 \
--type wp-demo \
--civi-ver 5.39.0 \
--cms-ver 4.0 \
--url http://my-wp-civi539.localhost
```
The `--civi-ver` argument will accept any branch or version tag. The `master` branch is the latest development branch.
You can also specify `--patch` with a pull request URL to apply those changes on top of your CiviCRM version.
### Custom build types
By default, `civibuild` looks for build types in `buildkit/app/config/`.
You may define new build types by creating similar folders. For example,
these steps would make personal folder (`$HOME/src/extra_site_configs`)
and register a custom build type `snazzy` (based on the `wp-demo` type).
```bash
## Make your custom folder
$ mkdir "$HOME/src/extra_site_configs"
## Copy an example build-type. Edit to taste.
$ cp -r buildkit/app/config/wp-demo "$HOME/src/extra_site_configs/snazzy"
$ vi "$HOME/src/extra_site_configs/snazzy/download.sh"
$ vi "$HOME/src/extra_site_configs/snazzy/install.sh"
## Build the site
$ export CIVIBUILD_PATH="$HOME/src/extra_site_configs:$CIVIBUILD_PATH"
$ civibuild create snazzy
```
!!! tip "Put `CIVIBUILD_PATH` in `civibuild.conf`"
You may set `CIVIBUILD_PATH` explicitly. However, it will be easier to use
if you make the change persistent. See: [Settings: civibuild.conf](#settings-civibuild)
## Build aliases
For developers who work with several CMSs and several versions of Civi, it's useful to have a naming convention and shorthand for the most common configurations. Civibuild includes aliases (in `src/civibuild.aliases.sh`) like "d44" and "wpmaster":
Create a build "d44" using build-type "drupal-demo" with Civi "4.4":
```
$ civibuild create d44 --url http://d44.localhost
```
Create a build "d45" using build-type "drupal-demo" with Civi "4.5":
```
$ civibuild create d45 --url http://d45.localhost
```
Create a build "wp45" using build-type "wp-demo" with Civi "4.5":
```
$ civibuild create wp45 --url http://wp45.localhost
```
Create a build "wpmaster" using build-type "wp-demo" with Civi's "master" branch:
```
$ civibuild create wpmaster --url http://wpmaster.localhost
```
These aliases exactly match the demo sites deployed under civicrm.org (e.g. "wp45" produces the demo site "wp45.demo.civicrm.org").
## Upgrading a site you installed with civibuild {:#upgrade-site}
If you have a working civibuild site and you'd like to upgrade CiviCRM to the latest version, follow these steps:
### Begin in the civicrm directory within your site {:#upgrade-site-begin}
```
cd ~/buildkit/build/dmaster/sites/all/modules/civicrm/
```
!!! note
The path to this directory will vary depending on where you installed buildkit and what CMS your site uses.
### Check the status of all git repos {:#upgrade-site-git-scan}
There are multiple git repos in your build (`civicrm-core.git`, `civicrm-packages.git`, etal). Before making a major switch, first double-check that all of these repos are in sane condition — i.e. there shouldn't be any uncommitted changes, and the repos should be on normal branches. For this purpose, use [git-scan](https://github.com/totten/git-scan) (installed with [buildkit](buildkit.md)).
```
git scan status
```
!!! fail "Check for errors"
If you see a message like *"Fast-forwards are not possible"* or *"Modifications have not been committed"*, then you'll need to clean up these git repositories before proceeding.
### Update the git repos {:#upgrade-site-git-scan-up}
To update to the latest version of a particular branch, use `git scan up` which will perform a standard "fast-forward merge" (`git pull --ff-only`) across all the repos:
```
git scan up
```
!!! tip
If you didn't cleanup earlier, then "fast-forward" may not be possible. It takes some judgment to decide what to do — e.g. a "merge" versus "rebase". Rather than risk a wrong decision, `git scan` will skip these repos and display warnings instead.)
Alternatively, if you'd like to hop to a specific tag, you can use `givi` (a tool included with [buildkit](buildkit.md)), but keep in mind that if you hop to a *previous* tag with code that expects a different database scheme, there will be no way to run database downgrades.
```
givi checkout 5.39.0
```
### Update the generated code, config files, databases {:#upgrade-site-update}
Reinstalling will recreate/overwrite all generated-code, config-files, and database content. Any data you put into your site (e.g. test contacts, etc) will be lost.
```
civibuild reinstall dmaster
```
Alternatively, if you care about the content in the database, then don't do a reinstall. Instead, update the generated-code and perform a DB upgrade:
```
./bin/setup.sh -Dg
drush civicrm-upgrade-db
```
## Downgrading a site you installed with civibuild {:#downgrade-site}
If you are [reviewing a pull request](../core/pr-review.md) you may wish to *downgrade* a civibuild site in order to begin replicating the issue and testing the fix. Currently this is **not possible** with civibuild, so instead you will need to do a [rebuild](#rebuild) with the the `--civi-ver` argument to specify your target version of CiviCRM.
## Rebuilds {:#rebuild}
If you're interested in working on the build types or build process, then the workflow will consist of alternating two basic steps: (1) editing build scripts and (2) rebuilding. Rebuilds may take a few minutes, so it's helpful to choose the fastest type of rebuild that will meet your needs.
There are four variations on rebuilding. In order of fastest (least thorough) to slowest (most thorough):
<table>
<thead>
<tr>
<th>Command</th>
<th>Description</th>
<th>Civibuild Metadata</th>
<th>Civi+CMS Code</th>
<th>Civi+CMS Config</th>
<th>Civi+CMS DB</th>
</tr>
</thead>
<tbody>
<tr>
<td><b>civibuild restore &lt;name&gt;</b></td>
<td>Restore DB from pristine SQL snapshot</td>
<td>Preserve</td>
<td>Preserve</td>
<td>Preserve</td>
<td>Destroy / Recreate</td>
</tr>
<tr>
<td><b>civibuild reinstall &lt;name&gt;</b></td>
<td>Rerun CMS+Civi "install" process</td>
<td>Preserve</td>
<td>Preserve</td>
<td>Destroy / Recreate</td>
<td>Destroy / Recreate</td>
</tr>
<tr>
<td><b>civibuild create &lt;name&gt; --force</b></td>
<td>Create site, overwriting any files or DBs</td>
<td>Preserve</td>
<td>Destroy / Recreate</td>
<td>Destroy / Recreate</td>
<td>Destroy / Recreate</td>
</tr>
<tr>
<td><b>civibuild destroy &lt;name&gt; ; civibuild create &lt;name&gt;</b></td>
<td>Thoroughly destroy and recreate everything</td>
<td>Destroy / Recreate</td>
<td>Destroy / Recreate</td>
<td>Destroy / Recreate</td>
<td>Destroy / Recreate</td>
</tr>
</tbody>
</table>
## Settings {:#settings}
### civicrm.settings.d folders {:#settings-civicrm}
Civibuild provides a mechanism to quickly add settings to *all sites* which you've built with civibuild.
For example, you can create a file `/etc/civicrm.settings.d/300-debug.php` with the following content to enable debugging and backtraces for all civibuild sites (useful for local development).
```php
<?php
$GLOBALS['civicrm_setting']['domain']['debug_enabled'] = 1;
$GLOBALS['civicrm_setting']['domain']['backtrace'] = 1;
```
Any settings which you would typically put in your site's `civicrm.settings.php` file can go into a php file (you choose the file name) in a `civicrm.settings.d` folder.
Civibuild will check the following `civicrm.settings.d` folders.
| Folder | Purpose |
| -- | -- |
| `$PRJDIR/app/civicrm.settings.d/` | General defaults provided by upstream buildkit for all civibuild sites |
| `$PRJDIR/app/config/$TYPE/civicrm.settings.d/` | General defaults provided by upstream buildkit for specific types of sites |
| `/etc/civicrm.settings.d/` | Overrides provided by the sysadmin for the local server |
| `$SITE_DIR/civicrm.settings.d/` | Overrides provided for a specific site/build |
!!! note "Load order"
For concrete example, suppose we have these files:
* `$PRJDIR/app/civicrm.settings.d/200-two.php`
* `$PRJDIR/app/civicrm.settings.d/300-three.php`
* `/etc/civicrm.settings.d/100-one.php`
* `/etc/civicrm.settings.d/300-three.php`
Then we would execute/load in this order:
* `100-one.php` (specifically `/etc/civicrm.settings.d/100-one.php`; this is the only version of `100-one.php`)
* `200-two.php` (specifically `$PRJDIR/app/civicrm.settings.d/200-two.php`; this is the only version of `200-two.php`)
* `300-three.php` (specifically `/etc/civicrm.settings.d/300-three.php`; the system configuration in `/etc` overrides the stock code in `$PRJDIR/app/civicrm.settings.d`)
The `$PRJDIR/app/civicrm.settings.d/` also contains some [example configuration files](https://github.com/civicrm/civicrm-buildkit/tree/master/app/civicrm.settings.d). For more advanced logic, one can look at the global `$civibuild` variable or at any of the standard CiviCRM configuration directives.
### settings.php; wp-config.php {:#settings-cms}
Each CMS includes a settings file that is analogous to
`civicrm.settings.php`. These follow a parallel structure -- which
means that you can put extra config files in:
* [backdrop.settings.d](https://github.com/civicrm/civicrm-buildkit/blob/master/app/backdrop.settings.d/README.txt) (Backdrop)
* [drupal.settings.d](https://github.com/civicrm/civicrm-buildkit/blob/master/app/drupal.settings.d/README.txt) (Drupal)
* [wp-config.d](https://github.com/civicrm/civicrm-buildkit/blob/master/app/wp-config.d/README.txt) (WordPress)
### civibuild.conf {:#settings-civibuild}
If you frequently call `civibuild`, you may find that the argument list
becomes fairly long (e.g. `--url http://example.localhost --admin-user
myadmin --admin-pass mypass --demo-user mydemo --demo-pass mypass ...`).
To set default values for these parameters, create and edit the file `civibuild.conf`:
```
cp app/civibuild.conf.tmpl app/civibuild.conf
vi app/civibuild.conf
```
The template includes documentation and examples.
## Examples
### Applying a patch
Using buildkit, you can create a CiviCRM environment with the PR applied.
For example:
```bash
civibuild create dmaster \
--url http://localhost:8001 \
--patch https://github.com/civicrm/civicrm-core/pull/8494 \
--admin-pass s3cr3t
```
This will create a test environment with the Drupal, CiviCRM master branch and the patch in PR 8494.
### Experimental: Multiple demo/training sites {:#demo-training}
When creating a batch of identical sites for training or demonstrations, one may want to create a single source-code-build with several databases/websites running on top (using "Drupal multi-site"). To install extra sites, use the notation "civibuild create buildname/site-id" as in:
Create the original build
```
$ civibuild create training --type drupal-demo --civi-ver 4.5 --url http://demo00.example.org --admin-pass s3cr3t
```
Create additional sites (01 - 03)
```
$ civibuild create training/01 --url http://demo01.example.org --admin-pass s3cr3t
$ civibuild create training/02 --url http://demo02.example.org --admin-pass s3cr3t
$ civibuild create training/03 --url http://demo03.example.org --admin-pass s3cr3t
```
Alternatively, create additional sites (01 - 20)
```bash
$ for num in $(seq -w 1 20) ; do
civibuild create training/${num} --url http://demo${num}.example.org --admin-pass s3cr3t
done
```
## Development/Testing of `civibuild` {:#development}
The tests for `civibuild` are stored in `tests/phpunit`. These are integration tests which create and destroy real builds on the local system. To run them:
* Configure `amp` (as above)
* Ensure that a test site is configured (`civibuild create civibild-test --type empty`)
* Run `phpunit4` or `env DEBUG=1 OFFLINE=1 phpunit4`
* Note that the tests accept some optional environment variables:
* `DEBUG=1` - Display command output as it runs
* `OFFLINE=1` - Try to avoid unnecessary network traffic
## Credits
Some content on this page was migrated from other sources, including:
* "Upgrading a site" from [Tim Otten's StackExchange answer](https://civicrm.stackexchange.com/questions/17717/how-do-i-upgrade-civicrm-on-a-local-site-that-i-installed-with-buildkit-civibuil/17721#17721)
## CiviDist
`cividist` generates a website with tarballs built from the official git repos ([civicrm-core.git](https://github.com/civicrm/civicrm-core.git), [civicrm-packages.git](https://github.com/civicrm/civicrm-packages.git), etc). It manages the CiviCRM [nightly builds](http://dist.civicrm.org).
If you wish to run `cividist` with your own repos, you will need to do the some initial setup and then periodically build new tarballs.
`cividist` expects that branch names match across all repos (e.g. the `4.6` branch in `civicrm-core.git` must match the `4.6` branch in `civicrm-packages.git`). If you use a non-standard branch name, it must exist in all repos.
## Setup: Make the web root
```
civibuild create dist --url http://dist.localhost
```
## Setup: Register your forks
!!! note
If you use forks, you should do so consistently across all repos (even if you don't have any customizations on one repo or another). The goal is to consistently name the `remote`s and `branch`es across all repos.
```
cd build/dist/src
git remote add myfork https://github.com/myfork/civicrm-core.git
cd build/dist/src/drupal
git remote add myfork https://github.com/myfork/civicrm-drupal.git
cd build/dist/src/packages
git remote add myfork https://github.com/myfork/civicrm-packages.git
cd build/dist/src/joomla
git remote add myfork https://github.com/myfork/civicrm-joomla.git
cd build/dist/src/WordPress
git remote add myfork https://github.com/myfork/civicrm-wordpress.git
```
## Setup: Permissions
If your system has specific permission requirements, then apply the permissions as you normally would. For example, if you use chgrp and and set all files as group-writable:
```
sudo git config --system core.filemode false
sudo chgrp -R mygroup build/dist
sudo chmod -R g+w build/dist
```
## Periodic: Update tarballs
This will retrieve the latest code from the remote alias (eg `myfork`) and build new build tarballs:
```
cd build/dist
env GIT_REMOTE=myfork cividist update
cividist build myfork/4.6
```
By default the tarballs will have the date in the name. If you don't want this you can add a FILE_SUFFIX e.g., to this command as used by Fuzion to a) use a remote called 'fuzion', b) use the branch 4.6.4rc1 from those repos & c) output using filenames like civicrm-4.6.5-drupal-nightly.tar.gz
```
env FILE_SUFFIX=nightly cividist build fuzion/4.6.4rc1
```
You can also build multiple tarballs with one command, e.g.
```
cividist build myfork/4.5 myfork/4.6 myfork/master
```
## Periodic: Cleanup old/orphaned tarballs
```
cd build/dist
cividist prune
```
Civilint is a thin wrapper which calls jshint and PHP_CodeSniffer (with the coder ruleset).
Code-style tests ensure a consistent layout across all of the codebase, and they also identify some unsafe or confusing coding patterns. While working on a patch, you should run civilint to determine if the pending changes comply with style guides.
Note that civilint may be invoked a few different ways:
```bash
# (no arguments) – Check style of any uncommitted changes.
civilint
# Check style of a specific file (or list of files).
civilint some/file.php
# Check your last commit
git diff --name-only HEAD~1 | civilint -
# Check for changes in your branch (compared to master)
git diff --name-only master | civilint -
```
See also:
- [CiviCRM Coding Standards](../standards/php.md)
- [CiviCRM Javascript Standards](../standards/javascript.md)
- [Drupal Coding Standards](https://www.drupal.org/docs/develop/standards/coding-standards)
- [PHP_CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer)
- [coder](https://github.com/civicrm/coder)
- [jshint](http://jshint.com/)
# Debugging
When your code isn't doing what you want it to do, it's time to debug. There are lots of options for debugging and there is lots you can do without setting up a sophisticated debugging environment. This chapter contains some simple debugging tips and tricks to get you started and also instructions on setting up XDebug, which is the recommended debugging tool for CiviCRM when you have bugs which are really hard to squish.
!!! danger "Security Alert"
None of these debugging methods should be performed on production sites, as they can expose system configuration and authentication information to unauthorized visitors.
The debugging methods presented here are ordered with the easiest ones first, but you may find the more challenging methods near the end to be more rewarding.
## Changing settings in the UI
CiviCRM has a debug mode which can be enabled via the UI to give you quick access to a couple of useful diagnostic tools, including all the Smarty variables that make up a page. It also provides shortcut methods to empty the file-based cache and session variables.
To use debugging via the UI, first go to **Administer > System Settings > Debugging and Error Handling** to enable these options, and find out more about them.
### Using URL parameters
After enabling debugging, append any of the following name-value pairs to the URL for the page you visit.
- `&smartyDebug=1` opens the Smarty Debug Window which loads all variables available to the current page template into a pop-up window *(make sure you have pop-up blocking disabled)*.
- `&sessionReset=2` resets all values in your client session.
- `&directoryCleanup=1` empties template cache in `civicrm/templates_c`.
- `&directoryCleanup=2` removes temporary upload files in `civicrm/upload`.
- `&directoryCleanup=3` performs both of the above actions.
- `&backtrace=1` displays a stack trace listing at the top of a page.
- `&sessionDebug=1` displays the current users session variables in the browser.
- `&angularDebug=1` displays live variable updates on certain Angular-based pages.
!!! tip "Caveats"
- Sometimes using `&smartyDebug=1` to inspect variables available to a template will not work as expected. An example of this is looking at the Contact Summary page, when using this method will display the variables available only to the summary tab and you might want to see the variables available to one of the other tabs. To do this you will need to debug via code, as explained below.
- If the page you are debugging does not already have a key-value parameter before debugging, you will need to begin the first parameter with a question mark instead of an ampersand.
### Displaying a backtrace
The backtrace can be enabled independently of debugging. If this option is selected, a backtrace will be displayed even if debugging is disabled. **A backtrace is normally displayed only when an error is encountered.** To manually trigger a backtrace in your custom code, see *Changing source code* (below).
A backtrace is a list of all the functions that were run in the execution of the page, and the PHP files that contain these functions. It can be really useful in understanding the path that was taken through code, what gets executed where, etc.
## Viewing log files
CiviCRM's log files are stored in the `ConfigAndLog` directory within CiviCRM's local file storage (see [the File System documentation](/dev/en/latest/framework/filesystem) for details specific to your CMS). Most runtime errors are logged here, as well as data that you explicitly write to log using the `CRM_Core_Error::debug log=true` parameter.
One may also write to the log file without creating an error with:
`Civi::log()->debug(__FUNCTION__);`
This example will write the function-name to ConfigAndLog using the PHP constant, `__FUNCTION__`.
## Changing file-based settings
The following values can be added to your site's settings file `civicrm.settings.php` to assist in debugging. In addition some of them can be passed in via the `env` command - eg.
` env CIVICRM_DEBUG_LOG_QUERY=flush_log drush cvapi System.flush` will log the queries from that command (and only those) to a log file with the name 'flush_log' in the file name. Any value accessed by `CRM_Utils_Constant::value()` can be set on a command-specific basis using `env`
- `define('CIVICRM_MAIL_LOG', 1);` causes all outbound CiviCRM email to be written to a log file. No real emails are sent.
- `define('CIVICRM_MAIL_LOG', '/dev/null');` causes all outbound emails to be discarded. No email is sent and emails are not written to disk.
- `define('CIVICRM_MAIL_LOG_AND_SEND', 1);` causes all outbound CiviCRM email to be written to a log file if `CIVICRM_MAIL_LOG` is set. Email will ALSO be sent using the configured method if this is set.
- `define('CIVICRM_DEBUG_LOG_QUERY', 1);` outputs all SQL queries to a log file.
- `define('CIVICRM_DEBUG_LOG_QUERY', 'n');` outputs all SQL queries to a log file, includes 'n' in the file name (useful if you want to capture some portion of the queries in a separate log file). **Added in CiviCRM 5.30.**
- `define('CIVICRM_DEBUG_LOG_QUERY', 'backtrace');` will include a backtrace of the PHP functions that led to the query.
- `define('CIVICRM_DAO_DEBUG', 1);` writes out various data layer queries to your browser screen.
- `define('CIVICRM_CONTAINER_CACHE', 'never');` causes Civi to rebuild the [container](http://symfony.com/doc/current/service_container.html) from the latest data on every page-load.
- `define('CIVICRM_TEMP_FORCE_DURABLE', 1);` forces temp tables to be created as non temporary tables. Note that you may need to manually delete them very pro-actively while this is on as it will result in errors in some cases
??? tip "Log file locations"
When any sort of "logging stuff to a file" is enabled by one of the above settings, check the `ConfigAndLog` directory within the local files directory to find the log.
(See [the File System documentation](/framework/filesystem.md) for the location in your CMS.)
??? tip "Sites built with CiviBuild"
If you're developing within a site built with [civibuild](/tools/civibuild.md), then you can to apply settings to *all your local sites* by using the [civicrm.settings.d folders](/tools/civibuild.md#settings-civicrm).
??? tip "Parsing logged queries with System Tools"
You can parse the output of the queries logged to the debug log into a csv using the [system tools extension](https://civicrm.org/extensions/system-tools) (in non-backtrace mode)
## Viewing a query log from MySQL
Outside of CiviCRM, the [MySQL General Query Log](https://dev.mysql.com/doc/refman/en/query-log.html) log allows MySQL to log all queries. This is a performance killer, so avoid using it in production!
1. Inspect your current settings
```sql
SHOW VARIABLES
WHERE variable_name IN (
'general_log',
'general_log_file',
'log_output'
);
```
```text
+------------------+------------------------------+
| Variable_name | Value |
+------------------+------------------------------+
| general_log | OFF |
| general_log_file | /var/lib/mysql/localhost.log |
| log_output | FILE |
+------------------+------------------------------+
```
You should see `general_log` set to `OFF` by default.
1. Turn on logging.
```sql
SET GLOBAL general_log = 'ON';
```
* To **log to a file**, leave `log_output` = `FILE`, as it is probably already set.
* To **log to a table** (which can sometimes be easier to sift through), execute the following. Note that you need to leave `'TABLE'` as a string literal here
```sql
SET GLOBAL log_output = 'TABLE';
```
1. Do something with CiviCRM that produces MySQL queries.
1. View the log.
* If logging to a file, then find (or change) the location of the log file with the `general_log_file` variable.
* If logging to a table run:
```sql
SELECT * FROM mysql.general_log
```
1. (If logging to a table) clear the log. (It can be helpful to do this before performing an action that you'd like to inspect).
```sql
TRUNCATE TABLE mysql.general_log;
```
1. When you're finished, turn *off* logging.
```sql
SET GLOBAL general_log = 'OFF';
```
## Changing source code
### In Smarty template files
Add `{debug}` to any part of the `.tpl` file and the Smarty Debug Window (described above) will display all variables in the same scope as the `{debug}` statement.
### Printing PHP variables
Show the contents of a variable:
```php
print_r($variable);
```
Show the contents of a variable, also with information regarding data types and lengths:
```php
var_dump($variable);
```
Another way to show the contents of a variable:
```php
CRM_Core_Error::debug($name, $variable = null, $log = true, $html= true);
```
Stop the script execution at that point.
```php
exit;
```
Print a backtrace:
```php
CRM_Core_Error::backtrace();
```
### In AngularJS HTML templates
```html
<div crm-ui-debug="myData"></div>
```
Then, be sure to add the parameter `angularDebug=1` to the URL.
## Clearing the cache
Clearing the cache is not a debugging technique, specifically. But sometimes it helps, and so is mentioned here for the sake of completeness.
Using a web browser:
- Navigate directly to `civicrm/clearcache`
<!-- FIXME: This page is misleading: Navigate to "Administer => System Settings => Cleanup Caches" -->
Using the command line, you can clear all caches with one of these commands:
- `cv flush` (requires [`cv`](https://github.com/civicrm/cv))
- `drush cc civicrm` (requires [`drush`](https://github.com/drush-ops/drush))
Alternatively, you can call the following methods in PHP code:
- `civicrm_api3('System', 'flush', array());` clears many different caches
- `CRM_Core_Config::clearDBCache();` clears *only* the database cache
- `CRM_Core_Config::cleanup();` clears *only* the file cache
## Running a debugger program
### What is a debugger?
A debugger is a software program that watches your code while it executes and allows you to inspect, interrupt, and step through the code. That means you can stop the execution right before a critical juncture (for example, where something is crashing or producing bad data) and look at the values of all the variables and objects to make sure they are what you expect them to be. You can then step through the execution one line at a time and see exactly where and why things break down. It's no exaggeration to say that a debugger is a developer's best friend. It will save you countless hours of beating your head against your desk while you insert print statements everywhere to track down an elusive bug.
Debugging in PHP is a bit tricky because your code is actually running inside the PHP interpreter, which is itself (usually) running inside a web server. This web server may or may not be on the same machine where you're writing your code. If you're running your CiviCRM development instance on a separate server, you need a debugger that can communicate with you over the network. Luckily such a clever creature already exists: XDebug.
XDebug isn't the only PHP debugger, but it's the one we recommend for CiviCRM debugging.
### Installing XDebug
#### Debian / Ubuntu Linux (System Packages)
```bash
sudo apt-get install php-xdebug
```
#### Red Hat / CentOS Linux (System Packages)
```bash
sudo yum install php-pecl* php-devel php-pear
sudo pecl install Xdebug
```
#### Mac OS X, Windows, and others
Generic instructions are provided with [XDebug's documentation](http://xdebug.org/docs/install).
Specific installation steps vary due to the diversity of PHP installation sources -- Apple's built-in PHP, brew, MAMP, XAMPP, AMPP, WAMP, Vagrant, Bitnami, and MacPorts are all a bit different. The best way to install XDebug is to identify your specific PHP runtime and then search Google, e.g. ["mamp xdebug"](https://www.google.com/#q=mamp+xdebug) or ["macports xdebug"](https://www.google.com/#q=macports+xdebug).
### Setting up PHP to talk to XDebug
Tell XDebug to start automatically (don't do this on a production server!) by adding the following two lines to your `php.ini` file (your `php.ini` file is a php configuration file which is found somewhere on your server. Calling the `phpinfo()` function is probably the easiest way to tell you where this file is in your case.
```php
xdebug.remote_enable = On
xdebug.remote_autostart = 1
```
Once XDebug is installed and enabled in your PHP configuration, you'll need to restart your web server.
### Installing an XDebug Front-End
After you have XDebug running on your PHP web server, you need to install a front-end to actually see what it is telling you about your code. There are a few different options available depending on what operating system you use.
#### NetBeans
[NetBeans](http://www.netbeans.org/) is a cross platform heavyweight Java IDE (Integrated Development Environment). It offers lots of features, but isn't exactly small or fast. However, it is very good at interactive debugging with XDebug. And since it's written in Java, it should run on any operating system you want to run it on.
After installing NetBeans, open your local CiviCRM installation in NetBeans and click the Debug button on the toolbar. It will fire up your web browser and start the debugger on CiviCRM. You may went to set a breakpoint in `CRM/Core/Invoke.php` to make the debugger pause there. For more information, see the NetBeans debugging documentation.
#### MacGDBp
[MacGDBp](http://www.bluestatic.org/software/macgdbp/) is a lighter-weight option, only available for OS X. After installing MacGDBp, launch it and make sure it says "Connecting" at the bottom in the status bar. If it doesn't, click the green **On**
button in the upper-right corner to enable it. The next time you access CiviCRM, the web browser will appear to hang. If you click on MacGDBp, you'll see that it has stopped on the first line of code in CiviCRM. From there you can step through the code to the part you're interested in. But it's probably a better idea to set a breakpoint in the part of the code you're interested in stopping at. See the MacGDBp documentation for more information.
## Error 500, white screen (WSoD), "Internal Server Error" errors
If CiviCRM shows a blank white page or page with "Error 500" with no other messages on screen, follow the steps in this section to diagnose and fix. A white screen (WSoD or "white screen of death") indicates that PHP is configured not to display errors, and has hit an error which it can't recover from. The result is an empty page.
Your next step is not to fix the error, but to first give yourself enough information to identify the source of the error. (Diagnose, then treat.)
**Viewing errors in logfiles**
The webserver can be configured to display errors to screen, but it also logs errors to files on disk. These files vary depending on your hosting environment, so you might consult your webhost's documentation to locate them. You might look for errors in some of these locations depending on webserver/php config:
- `/var/log/nginx/*err*log` NginX webserver error logs
- `/var/log/apache2/*err*log` Apache webserver & mod_php error logs
- `/var/log/*php*log` PHP-FPM & PHP-CGI error logs
- `/var/log/php5/*log` PHP-FPM & PHP-CGI error logs
- `/path/to/site/err*log` Some hosting environments
*(The `*`s above represent a wildcard, not an actual filename. Eg the last entry might be public_html/error_log on Bluehost.)*
And a **CiviCRM specific debug log** file - location varies depending on hosting environment *and* CMS, refer to [this page](/tools/debugging.md#Debuggingfordevelopers-Logfiles) for location -
path/to/site/path/to/civicrm/files/ConfigAndLog/CiviCRM*log
!!! Tip
Buildkit uses [amp](https://github.com/amp-cli/amp) to install sites which means you have to look in `~/.amp`. Log files are in `~/.amp/log` and separated by site.
Once you've located these files, you can download them to view, or you can use tools like `tail` or `less +F` to follow the files. I prefer to follow logfiles because you can watch the error appear each time.
**Displaying errors to screen**
You may prefer to display errors to screen. This is probably disabled on your site because it's a security risk to some degree - an attacker can see more information when errors are visible, so the default configuration is often to restrict visibility to people with server access (via the logfiles above).
To enable error display, either:
**Configure your PHP to display errors for your site** via `php.ini` / `.htaccess` (see [How can I get PHP errors to display](http://stackoverflow.com/questions/1053424/how-do-i-get-php-errors-to-display)), OR
**Add PHP code to enable error display** (you can add it in `civicrm.settings.php` or the top of the `index.php` of your host CMS).
<?php
error_reporting(E_ALL);
ini_set('display_errors', TRUE);
ini_set('display_startup_errors', TRUE);
**Making sense of what you see**
Once you've taken one of the above approaches, try reproducing the actions which led to a white screen. If all's gone well, you should see an error now (on screen, or in your terminal / SSH session).
This is where you can start debugging meaningfully. There's a good chance you're exhausting server resources (timeouts, memory exhaustion) or hitting some coding error, but once you have the relevant error message at hand you'll be much better equipped to track down the source of the problem affecting your site.
**Further reading**
* [Stack Overflow: How do I get PHP errors to display?](http://stackoverflow.com/questions/1053424/how-do-i-get-php-errors-to-display)
* [CiviCRM StackExchange: Where should one look for logs when debugging a new problem](https://civicrm.stackexchange.com/questions/376/where-should-one-look-for-logs-when-debugging-a-new-problem)
* [Drupal.org: Blank pages or White Screen of Death](https://www.drupal.org/node/158043)
* [Joomla SE: What is an efficient way to troubleshoot a White Screen of Death](https://joomla.stackexchange.com/questions/299/what-is-an-efficient-way-to-troubleshoot-a-white-screen-of-death)
**Notes**
If this is the first time you've looked, there may be other errors visible which don't relate to the problem at hand. You may still need to discern what the actual problem is ...
If you're not familiar with UNIX, this may seem like a lot of effort. It's a lot less effort than *guessing* your way through a problem though!
## Debugging Javascript issues
### Symptoms
* Popup forms, tabs, custom fields, and other dynamic content fail to load or save correctly.
* Autocompletes or profile selectors look wrong (like a textbox that doesn't do anything) or fail to get results when you try to search.
* The CiviCRM menubar fails to appear at the top of the page.
* You frequently see error messages like "Network Error - Unable to reach the server."
### Background
Javascript (JS) is what makes web-apps interactive. Without it, nothing on a webpage can change without refreshing or clicking to a new page. The CiviCRM UI, especially in newer versions, uses javascript for everything from popup forms to date and time inputs. If a bug or misconfiguration on your website interferes with some aspect of JS, certain elements of the CiviCRM interface may function badly or not at all.
AJAX is a complicated-sounding acronym for the simple task of loading more stuff from the server on-demand. When you see a spinning triangle or have to wait for autocomplete results, the content is loading via AJAX. The J stands for Javascript, so if your site is having JS toubles, AJAX may not work either.
### Troubleshooting Tools
Most of the time the other debugging methods metioned earlier will solve 90% of the issues. However sometimes you need to use your browser to debug. Your web-browser (Firefox/Chrome/etc.) has a javascript console where you can view error messages. Press F12 to turn it on and then click over to the **Console** tab. With these tools enabled, try triggering the symptom again and watch for error messages on the screen or in the console. If you see an error message, try doing a google search for it to see if others have solved the same problem.
### Problems and Solutions
* Incompatible/buggy extensions for CiviCRM might crash javascript. Try temporarily turning them all off. If your problem is fixed, re-enable them one at a time to find the culprit.
* If your site is accessible from more than one url (e.g. `http://mysite.org` and `http://www.mysite.org`) AJAX requests may fail. Ask your host or sysadmin to restrict access to one url or the other, and ensure the one you choose matches `$civicrm_root` in `civicrm.settings.php`.
* Some people customize CiviCRM by overriding templates and php code. This custom code can become out-of-date and incompatible with the latest version, causing problems after upgrading. To see if your site has custom code, go to `Administer->System Settings->Directories` and check if either Custom Templates or Custom PHP Path Directory has been set (they are both blank by default). If so, try deleting them temporarily (don't forget to copy their values into a text file on your computer so you can restore them later). Check if your problem is solved, and if so, you can conclude that your custom code is in need up updating.
* On-screen php error messages can interfere with dynamic content loading from the server. Ensure the `display_errors` setting is off in your `php.ini` configuration.
* Certain website plugins have been known to cause javascript errors. Check this list of known incompatibilities.
* Ensure you are using the latest version of CiviCRM.
* Clear your site's caches.
* WordPress users may experience some interference by WordFence - especially after CiviCRM or WordFence are newly installed. [Putting WordFence in learning mode may help](https://lab.civicrm.org/dev/core/-/issues/3887)
If none of the above works:
Create a new post on Stack Exchange. Indicate that you have already read this and list what solutions you tried and what happened. List exact steps to reproduce the problem, and paste in the complete error message(s) you are seeing.
## Credits
Some content from this page was migrated from other sources
and contributed by the following authors:
* Chris Burgess
* Sean Madsen
# Git, GitHub, and GitLab
CiviCRM uses git, GitHub, and GitLab to manage changes to the code. A solid understanding of these tools (especially git) is important for developing CiviCRM. This page provides some information about *how CiviCRM uses these tools* &mdash; but, due to the wealth of resources already available elsewhere online, this page does *not* attempt to teach you everything you need know about how to use these tools for CiviCRM development.
!!! tip
If you are new to git, a great way to get started using it within the CiviCRM community is to [contribute to documentation](../documentation/index.md). The editing workflow involves git in the same way that core coding does &mdash; but the stakes are much lower!
## External resources {:#resources}
* Git
* [Official documentation](https://git-scm.com/documentation)
* [15 minute interactive tutorial](https://try.github.io/levels/1/challenges/1)
* [Another site with more interactive tutorials](http://learngitbranching.js.org/)
* GitHub
* [Official help site](https://help.github.com/)
* [20 minute GitHub tutorial video](https://www.youtube.com/watch?v=0fKg7e37bQE)
* [hub](https://hub.github.com/) - a useful commandline tool for GitHub which can speed up your workflow
* GitLab
* [Official documentation](https://docs.gitlab.com/ce/README.html)
## Repositories
* GitHub - **[github.com/civicrm](https://github.com/civicrm/)**
* As of 2017, most of CiviCRM's repositories are hosted on GitHub
* Most of the repositories hosted on GitHub are owned by the "CiviCRM" organization.
* Here are some of the most important repositories hosted on GitHub
* [civicrm-core](https://github.com/civicrm/civicrm-core/) - Core application which can be embedded in different systems (Drupal, Joomla, etc).
* [civicrm-drupal](https://github.com/civicrm/civicrm-drupal/) - Drupal integration modules, with branches for each CiviCRM release & Drupal major version (e.g. 7.x-4.6, 7.x-4.7, 6.x-4.4, 6.x-4.6).
* [civicrm-joomla](https://github.com/civicrm/civicrm-joomla/) - Joomla integration modules.
* [civicrm-wordpress](https://github.com/civicrm/civicrm-wordpress/) - WordPress integration modules.
* [civicrm-backdrop](https://github.com/civicrm/civicrm-backdrop/) - Backdrop integration module.
* [civicrm-packages](https://github.com/civicrm/civicrm-packages/) - External dependencies required by CiviCRM.
* [civicrm-l10n](https://github.com/civicrm/civicrm-l10n/) - Localization data.
* *...and [many others](https://github.com/civicrm/) too!*
* GitLab - **[lab.civicrm.org/explore/projects](http://lab.civicrm.org/explore/projects)**
* CiviCRM also has some repositories hosted on this self-hosted installation of GitLab
## Git workflow overview {:#contributing}
Whether you are contributing to civicrm-core or an ancillary project (using GitHub or GitLab) the process generally goes somewhat like this:
1. Consider [opening an issue on GitLab](issue-tracking.md#gitlab) to describe the change you'd like to make. Not all changes need GitLab issues, but opening an issue is recommended if you are making significant changes, expect discussion, or expect your changes to be grouped into more than one [pull request](#pr).
1. Find the page on GitHub or GitLab for the project to which you would like to contribute. We will call this repository the **upstream repository**.
1. **Clone** the upstream repository to your local machine. (If you are working on core, you should use [civibuild](civibuild.md) for this step.)
1. On the web page for the upstream repository, **fork** the upstream repository to your personal user account.
1. Within your local repository **add your fork** as a second git *remote*. *[Learn more...](#remotes)*
1. **Choose the correct base branch** in the upstream repository as the starting point for your changes. (Usually this will be `master`.) *[Learn more...](#base-branch)*
1. (If it's been some time since you've cloned) **pull or fetch** the latest changes from the *upstream repository* into the appropriate branch of your local repository. *(You might also need to [upgrade your civibuild site](civibuild.md#upgrade-site).)*
1. Create (and checkout) a **new branch** for your changes, based on the correct branch (chosen above) in the upstream repository. *[Learn more...](#branching)*
1. Make your changes. (Take care to follow the guidelines in [contributing to core](../core/contributing.md).)
1. **Commit** your changes. *[Learn more...](#commiting)*
1. **Push** your changes *to your fork*.
1. **Open a pull request**. *[Learn more...](#pr)*
1. Wait for someone else to [review your pull request](../core/pr-review.md).
1. If you need to make more changes later, commit them on the same branch and push your new commits to your fork. The new commits the will automatically appear in the pull request.
1. If other people commit changes to the upstream repository which create *merge conflicts* in your pull request, then **rebase** your branch. *[Learn more...](#rebasing)*
1. Once your changes are merged, delete your local branch
See also: [reviewing someone else's pull request](../core/pr-review.md)
## Pull requests {:#pr}
!!! note "terminology"
The terms "pull request", "merge request", "PR", and "MR" all effectively synonymous. GitHub uses "pull request", and GitLab uses "merge request".
### Creating a pull request {:#pr-submit}
1. In the web browser, navigate to the web page for your fork (e.g. `https://github.com/myuser/civicrm-core` ).
1. Click **Pull Request**
1. There will be two branches specified – the (first) left should be "civicrm" (i.e. where the code is going to). The second (right) should be your branch.
1. Add a [good subject](#pr-subject) and explanation, and submit.
To note: it's not possible to create a pull request for the civicrm-core repo on GitLab ─ use GitHub for this.
### Writing a pull request subject {:#pr-subject}
Pull request titles don't need to be identical to issue titles, and in particular, you may want to focus more positively on the changes in code than on the broader feature changes. Here are some guidelines for writing a good subject line:
When filing a pull-request, use a descriptive subject. These are good examples:
* `dev/core#5555 - Add "It's complicated" relationship type to defaults`
* `CRM-12345 - Fix Paypal IPNs when moon is at half-crescent (waxing)`
* `(WIP) dev/mail#67890 - Refactor SMS callback endpoint`
* `(NFC) CRM_Utils_PDF - Improve docblocks`
* `(REF) CRM_Foo_Form_Edit - Extract method checkFooBar()`
A few elements to include:
* **Acronyms** - You're welcome to use the [acronyms](#acronyms) below to flag your PR with certain characteristics.
* **dev/_project_#_XXXX_** - This is a [GitLab issue reference](issue-tracking.md#gitlab-reference).
* **CRM-_XXXXX_** - This is a reference to the now-deprecated [Jira issue tracker](issue-tracking.md#jira). A bot will set up crosslinks between JIRA and GitHub.
* **Description** - Provide a brief description of what the pull-request does.
### Acronyms within PR subjects {:#acronyms}
You can put these acronyms at the beginning of your PR subject to flag it as such.
#### (WIP) - "Work in Progress" {:#wip}
If you are still developing a set of changes, it may be useful to submit a pull-request and flag it as `(WIP)`. This allows you to have discussion with other developers and check test results. Once the change is ready, update the subject line to remove `(WIP)`.
#### (REF) - "Refactor" {:#ref}
Refactoring is a technique of making small, behavior-preserving changes (see, e.g. [Martin Fowler's *Refactoring*](https://martinfowler.com/books/refactoring.html)).
Because refactoring preserves behavior, it doesn't require as much scrutiny with regard to user-experience or product-scope. Rather, one merely verifies that the change preserves behavior.
Examples:
* Extract a method or field
* Pull-up a method from child-class to parent-class
* Encapsulate a field
#### (NFC) - "Non-Functional Change" {:#nfc}
Most patches are designed to change functionality (e.g. fix an error message or add a new button). However, some changes are non-functional -- they presumptively have no impact on users or integrations at runtime.
The aim of flagging a PR as "(NFC)" is to streamline review on trivial changes.
Here are some examples and counter-examples of NFC:
* _Non-Functional Change_:
* Modify whitespace in PHP code.
* Update a code comment.
* Fix a typo or grammatical error in a help dialog.
* (*Maybe*) Add a new unit-test where there was no coverage before (see below).
* (*Maybe*) Update a PHP doc block (see below).
* _Functional Change_:
* Refactoring, e.g. replacing 20 lines of redundant code with a call to a helper function.
* (__Why?__ A reviewer would consider whether the helper is truly equivalent, better, or worse.)
* Fix a typo in a *symbol* (PHP class-name, PHP function-name, HTML field name, etc).
* (__Why?__ A reviewer would consider dangling references to the symbol.)
* Change the general wording of a help dialog or menu item.
* (__Why?__ A reviewer would consider impact on the user's comprehension.)
* Add or alter an existing unit-test.
* (__Why?__ A reviewer would consider whether the change improves the correctness of the test.)
* Update annotations in a PHP doc block.
* (__Why?__ Some annotations affect functionality, e.g. the `@required` annotation on an APIv4 param.)
* Alter the build process.
* (__Why?__ A reviewer would consider whether the new build will work correctly.)
### Pull request scope {:#pr-scope}
A good pull request addresses a clearly-defined problem. There should be a detailed description logged in the [issue tracker](http://issues.civicrm.org/). Excellent PRs also increase test coverage. If you are tempted to do additional tweaks or code cleanup outside the scope of that issue, you could make a separate commit and include them in the PR if they are minor & non-controversial, or create a separate PR if they are more complex.
There is no size limit for PRs as long as they are focused on completely solving a discreet problem. As a practical matter, though, bigger PRs may take longer to review and merge. When possible, split "epic" issues into bite-sized chunks as long as each seperate PR is functionally complete and does not cause merge conflicts with your other PRs. In the latter case, add commits to an existing PR.
### Reviewing a pull request
See [How to review a core pull request](../core/pr-review.md)
### Who merges pull requests? {:#pr-merge}
A person may be granted the privilege/responsibility of reviewing and merging pull requests who:
* is an active contributor to the CiviCRM project
* responds to communications in a timely fashion
* is familiar with current CiviCRM coding standards and best practices
* is a careful proofreader and tester, and who gives thorough constructive feedback
## Git tasks
### Cloning {:#cloning}
When you want to set up a local copy of a git repo hosted on GitHub or GitLab, you *clone* it. Here are two ways:
* Using the SSH protocol
```bash
$ git clone git@github.com:civicrm/civicrm-core.git
```
* Using the HTTP protocol
```bash
$ git clone https://github.com/civicrm/civicrm-core.git
```
Using SSH is a little bit better because you won't need to enter your password all the time, but it does require some [extra steps](https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent/).
### Managing multiple git remotes {:#remotes}
Your local git repo is typically set up to track at least one *remote* git repo for operations like `fetch`, `pull`, and `push`. But it can be helpful to set up multiple remotes when contributing to repos which you don't own.
Common terminology:
* **Upstream repository** - a repo hosted on GitHub or GitLab which *you don't own* but would like to contribute to
* **Fork repository** - a repo hosted on GitHub or GitLab which *you own* and have created by "forking" an upstream repo
* **Local repository** - the repo that lives on your local computer after [cloning](#cloning)
Show the remotes which your local repo is tracking:
```bash
$ git remote -v
upstream https://github.com/civicrm/civicrm-core.git (fetch)
upstream https://github.com/civicrm/civicrm-core.git (push)
myusername git@github.com:myusername/civicrm-core.git (fetch)
myusername git@github.com:myusername/civicrm-core.git (push)
```
The first column shown in the output is the *name* of the remote. You can rename your remotes however you want. Assuming your GitHub user name is `myusername`, the above output looks pretty good because we have two remotes: one named `upstream` (an *upstream repo*), and another named `myusername` (a *fork repo*). When you first [clone](#cloning) a repository, git will set up a remote called `origin` which refers to the repo you initially cloned. In the above example we don't see `origin`, so that remote has been removed or renamed.
Read about [how to use `git remote`](https://git-scm.com/docs/git-remote) to properly set up your remotes.
!!! tip
If you use [hub](https://hub.github.com/), the command `hub clone` can help with this
### Branching {:#branching}
Git uses branches to separate independent sets of changes. When creating a new branch, here are some things to keep in mind:
* [Choose an appropriate base branch](#base-branch)
* You'll need to keep your local branch until its changes are merged. Sometimes this can take several months. After it's merged, you can delete it.
* Give your branch a good name
* The name of your branch is up to you.
* It should be unique among your other outstanding branches.
* It should only contain letters, numbers, dashes, and underscores.
* If you have a GitLab or Jira issue, you can use its number (e.g `mail-111` or `CRM-1234`) as the name of the branch.
Create a new branch and switch your local repository to it:
```bash
$ git checkout upstream/master -b mail-111
```
* `upstream` is your local name for the [git remote](#remotes) which represents the upstream repository (e.g. `https://github.com/civicrm/civicrm-core`) to which you are contributing changes. Depending on how you have set up your local repo, this remote might have a different name, like `origin` or `civicrm`.
* `master` is the name of the branch in the upstream repository on which you would like to base your changes
* `mail-111` is the name of your new branch
### Choosing a base branch {:#base-branch}
When creating a new branch, you should explicitly declare a starting point.
Most of the time, your base branch should be `master`. In special circumstances, a patch may be accepted for the *Release Candidate* (RC), or *Stable* branch. The table below summarizes the policies for each branch.
| Name | Git branch (example) | Version number (example) | Acceptable patches |
| --- | ---- | --- | --- |
| Master | master | 5.99.alpha1 | This is primary target for most patches, including typical bugfixes, cleanups, and minor features. |
| Release Candidate | 5.98 | 5.98.beta1 | Fixes for critical, recent regressions. The regression should be traced to a specific, recent change. In a typical cycle, only 1-10 RC patches are accepted.|
| Stable | 5.97 | 5.97.1 | Backports of fixes for very critical issues. This is usually only done by the project maintainers. Make your PR against the RC instead and they will backport if necessary. |
If you are unsure about which is the current RC or master branch, you can refer to https://download.civicrm.org/latest/, and look at the numbers in brackets to the right of the filename, e.g. if you see `civicrm-RC-drupal.tar.gz (5.24.beta1-...)` it means the current release candidate branch is the 5.24 branch.
Don't make multiple PRs against multiple branches for the same thing even if the bug is present in both versions, e.g. both the RC and master. Consult the table above and just pick one branch.
### Committing {:#committing}
As much as possible, separate your changes into distinct commits that each make sense on their own. Using smaller commits will make your changes easier for others to review. You can [clean up your commits](#rebasing-interactive) once you have finished getting your code right.
It is often helpful to put your commits in separate smaller PRs as a reviewer might spare 30 minutes to review a function extraction of a variable cleanup and merge the PR fairly quickly but if you put 5 in the same PR they might not be able to find a block of 2 hours to review them all and it might languish. Doing preliminary cleanup PRs while you are still working on a problem can be helpful as you are improving the code as you go rather than creating a huge amount of change that will be hard and/or risky to review. While you are still working on a problem is also a great time to start adding tests for the code around it to core.
#### Writing a commit message {:#commit-messages}
When making commits, remember that this isn't just a small personal project: your audience is hundreds of other developers &mdash; now and ten years from now &mdash; as well as end users trying to understand features and bugs. By leaving a commit history that makes sense &mdash; both in content and in commit messages &mdash; you will make the code more legible for everyone.
Follow these guidelines to write a good commit messages:
* The first line should be a meaningful **subject**, which should:
* be prefixed with a GitLab or Jira issue reference (if the commit is to CiviCRM core)
* mention a "subsystem" after the issue number
* be 72 characters or less, in total
* be in "Sentence case"
* use the imperative mood
* not end in a period
* examples:
* `dev/core#999 - Civi\Angular - Generate modules via AssetBuilder`
* `CRM-19417 - distmaker - Change report to JSON`
* (optionally but recommended) After the subject, include a short **body**, which should:
* have a blank line above it (below the subject)
* be wrapped at 72 characters
* explain *what*, *why*, and *how*
### Rebasing {:#rebasing}
Sometimes when you [make a pull request](#pr) someone else merges a change into the upstream repository that *conflicts* with your change. The best way to resolve this conflict is to rebase. It's a good idea to [read about rebasing](https://git-scm.com/docs/git-rebase) so you understand the theory. Here's the practice:
!!! note
In this example we have two [remotes](#remotes) set up:
* `upstream` which tracks the upstream repo
* `myusername` which tracks the fork repo
Also we are working on changes in a branch called `my-branch`
1. Update your local `master` branch
```bash
$ git checkout master
$ git pull upstream master
```
1. Checkout the branch that has conflicts you'd like to resolve
```bash
$ git checkout my-branch
$ git rebase master
```
1. See which files need attention
```bash
$ git status
```
1. Make changes to the files which resolve the merge conflicts
1. "Add" the files to tell git you have resolved the conflicts
```bash
$ git add CRM/Utils/String.php
```
1. Continue the rebase
```bash
$ git rebase --continue
```
1. Force-push your changes back up to your fork
```bash
$ git push -f myusername my-branch
```
1. Now, if you go to back to the page for your pull request it should no longer show merge conflicts
## Rebasing for cleanup {:#rebasing-interactive}
When you are working on a PR you will often make lots of commits in order to get to the right change - these are your workings. However, when we merge we want the commit history to show the final change - not the workings so we will often ask you to rebase. It's fine to have multiple commits in a PR but each commit should be complete in itself and a logical change in itself. If you make a mistake in one commit it shouldn't be fixed in another (unless the mistake is already merged).
The trick to a cleanup rebase is to do it in interactive mode. The process is similar to above and it's usually easier to do the above first and THEN the interactive rebase to make sure you have a nice clean start before starting your interactive rebase.
Assuming the upstream repo is called 'upstream' the command is
```
git rebase -i upstream/master
```
You then get to squash or remove commits are fix up the history. Do a force push (per above) when you have finished
# Development tools
## Tools included with buildkit {:#with-buildkit}
When you install [buildkit](buildkit.md) you'll get all these tools.
*This list of tools is also maintained [in the buildkit readme file](https://github.com/civicrm/civicrm-buildkit/blob/master/README.md).*
### CiviCRM-specific tools {:#civicrm-specific}
* `civibuild` - Build a complete source tree (with CMS+Civi+addons), provision httpd/sql, etc.
* *[documentation](civibuild.md)*
* *[repository](https://github.com/civicrm/civicrm-buildkit)*
* `cv` - command is a utility for interacting with a CiviCRM installation
* *documentation: run `cv list`*
* *[repository](https://github.com/civicrm/cv)*
* `civix` - CiviCRM extension code generator
* *[documentation](../extensions/civix.md)*
* *[repository](https://github.com/totten/civix)*
* `civistrings` - Scan code for translatable strings (*.pot)
* *documentation: run `civistrings --help`*
* *[repository](https://github.com/civicrm/civistrings)*
* `cividist` - Generate tarballs from a series of git branches/tags
* *[documentation](cividist.md)*
* *repository: [within civicrm-buildkit](https://github.com/civicrm/civicrm-buildkit/blob/master/bin/cividist)*
* `gitify` - Convert a CiviCRM installation to a git repo
* *documentation: run `gitify` with no arguments*
* *repository: [within civicrm-buildkit](https://github.com/civicrm/civicrm-buildkit/blob/master/bin/gitify)*
* `civilint` - Check the syntax of uncommitted files using `phpcs`, `jshint`, etc.
* *documentation: run `civilint` with no arguments*
* *repository: [within civicrm-buildkit](https://github.com/civicrm/civicrm-buildkit/blob/master/bin/civilint)*
* `civihydra` - Create a series test sites for several CMSs (extends `civibuild`)
* *documentation: run `civihydra` with no arguments*
* *repository: [within civicrm-buildkit](https://github.com/civicrm/civicrm-buildkit/blob/master/bin/civihydra)*
* `civicrm-upgrade-test` - Scripts and data files for testing upgrades
* *[documentation& repository](https://github.com/civicrm/civicrm-upgrade-test)*
* `civi-test-run` - Run one or more test suites
* *[documentation](civi-test-run.md)*
* *repository: [within civicrm-buildkit](https://github.com/civicrm/civicrm-buildkit/blob/master/bin/civi-test-run)*
* Coder - Configure phpcs for CiviCRM's [coding standards](../standards/php.md)
* *[documentation & repository](https://github.com/civicrm/coder)*
* *(Derived from [Drupal's coder project](https://www.drupal.org/project/coder))*
### External tools installed with buildkit {:#external}
These tools are not specific to CiviCRM, so you may already have some of them installed on your system. If you install [buildkit](buildkit.md) you'll get all these tools at once, in addition to the CiviCRM-specific tools listed above.
* Dependency management
* [composer](http://getcomposer.org/) - Manage dependencies for PHP code.
* [bower](http://bower.io/) - Manage dependencies for Javascript code.
* Source code management
* [git-scan](https://github.com/totten/git-scan/) - Manage a large number of git repositories.
* [hub](http://hub.github.com/) - Send commands to github.com.
* Source code quality
* [jshint](http://jshint.com/) - Check the syntax of Javascript files.
* [phpcs](https://github.com/squizlabs/PHP_CodeSniffer) - Check the syntax of PHP files.
* Site management
* [amp](https://github.com/totten/amp) - Abstracted interface for local httpd/sql service (Apache/nginx/MySQL).
* [drush](http://drush.ws/) - Administer a Drupal site.
* [joomla](https://github.com/joomlatools/joomla-console) (joomla-console) - Administer a Joomla site.
* [wp](http://wp-cli.org/) (wp-cli) - Administer a WordPress site.
* Testing
* [karma](http://karma-runner.github.io) (w/[jasmine](http://jasmine.github.io/)) - Unit testing for Javascript.
* [paratest](https://github.com/brianium/paratest) - Parallelized version of PHPUnit.
* [phpunit](http://phpunit.de/) - Unit testing for PHP (with Selenium and DB add-ons).
## Other useful tools {:#other}
### Miscellaneous {:#misc}
* [git](https://git-scm.com/) - version control system
* [psysh](http://psysh.org/) - a reply-echo-print-loop for PHP (like `php -a`, but better)
* [MySQL Workbench](https://www.mysql.com/products/workbench/) - A graphical interface to your local (or remote) MySQL server
* [MkDocs](http://www.mkdocs.org) - for [editing documentation](../documentation/index.md)
### Text editors
If you already have a text editor you love, then stick to that. If you're new and need some recommendations, here are some of the most popular text editors among CiviCRM developers:
* [PhpStorm](https://www.jetbrains.com/phpstorm/) *(See [CiviCRM-specific notes on PhpStorm](phpstorm.md))*
* [NetBeans](https://netbeans.org/)
* [Sublime](https://www.sublimetext.com/)
* [Atom](https://atom.io/)
* [vim](http://www.vim.org/)
# Issue-tracking systems
As of 2019, CiviCRM uses two different systems for tracking and managing issues (aka tickets) - GitLab and GitHub. Until early 2018, Jira was also used. This page offers a brief summary of the systems and helps developers understand when and how to use them.
## Systems
### GitLab {:#gitlab}
**[lab.civicrm.org](http://lab.civicrm.org)**
Used as an issue-tracking system for:
* **[CiviCRM](https://lab.civicrm.org/groups/dev/-/issues)** (including `civicrm-core`, `civicrm-packages`, `civicrm-drupal`, `civicrm-joomla`, and `civicrm-wordpress`)
* [civicrm.org website issues](https://lab.civicrm.org/marketing-team/civicrm-website)
* [infrastructure issues](https://lab.civicrm.org/infrastructure/ops/issues)
* *...and many [other projects](https://lab.civicrm.org/explore/projects)*
#### How GitLab organizes things {:#gitlab-organizing}
* At the top level, GitLab is divided into [_groups_](https://lab.civicrm.org/dashboard/groups) (which are mostly analogous to _GitHub's_ concept of "organizations").
* Groups own *projects* (and individual users can own projects, too).
* Projects often contain *issues*.
Issues about CiviCRM itself are opened within the [Development Team's projects](https://lab.civicrm.org/dev/).
#### Referencing GitLab issues {:#gitlab-reference}
Use text like `dev/core#1` to reference specific issues in your [commit messages](git.md#commit-messages), [pull request subjects](git.md#pr-subject), and other communication.
In the above example:
* `dev` is the *group*
* `core` is the *project*
* `1` is the *issue number*
!!! tip
GitLab displays the issue reference at the bottom of the right-hand column along with a link that copies the reference to your clipboard:
![Screenshot of GitLab issue reference](../img/gitlab-reference.png)
### GitHub {:#github}
**[github.com/civicrm](https://github.com/civicrm)**
Besides being a code repository for most CiviCRM projects, GitHub is used as an issue-tracking system for:
* [buildkit](https://github.com/civicrm/civicrm-buildkit/issues)
* [cv](https://github.com/civicrm/cv/issues)
* [civix](https://github.com/totten/civix)
* *...and many [other projects](https://github.com/civicrm)*
!!! note
Some projects (e.g. CiviCRM core) have their repository hosted on GitHub but do *not* use the GitHub issue-tracking functionality. For these projects you will notice there is no "Issues" tab.
### Jira (deprecated) {:#jira}
**[issues.civicrm.org](https://issues.civicrm.org/jira)**
Used as an issue-tracking system until early 2018 for:
* **[CiviCRM (`CRM`)](https://issues.civicrm.org/jira/browse/CRM)** (including `civicrm-core`, `civicrm-packages`, `civicrm-drupal`, `civicrm-joomla`, and `civicrm-wordpress`)
* [CiviVolunteer (`VOL`)](https://issues.civicrm.org/jira/browse/VOL)
* [Extension Review Queue (`EXT`)](https://issues.civicrm.org/jira/browse/EXT)
## Guidelines for creating issues {:#guidelines}
### When to create an issue {:#when-to-create}
If you are ready to make a change to CiviCRM, you can [submit a pull request](git.md#pr) *without* creating an issue first.
Otherwise, you'll want to create an issue in order to track work that might need to be done at some point in the future.
### Check the latest version {:#check-version}
There's no sense in planning any changes to CiviCRM's core code without looking at the most recent release. Any changes you make will be based upon it, and it may include a fix or attempted resolution that may change your thinking about the issue.
It's best to start with upgrading your own site rather than just trying to use one with demo data. That way, you can be sure to know how the system behaves with your real-life data.
If upgrading your site doesn't resolve it, try a plain installation of CiviCRM, such as one generated with Buildkit. This will ensure that your site-specific data isn't the problem, and having a plain vanilla site will be important for trying out your changes later.
### Talk over the issue {:#talk}
To get your ideas together for later steps, it's best to start with a conversation. This doesn't need to be technical, but it should be with someone familiar with using CiviCRM. A coworker or consultant might be a place to start, or you could talk it over on [Mattermost](https://chat.civicrm.org/) or [Stack Exchange](http://civicrm.stackexchange.com/).
In your conversation, think about some of the following questions:
- How severe is the impact on organizations using CiviCRM?
- Has this feature's behavior changed recently? Is a bug a regression, or has it always been this way? Is this a new feature that doesn't handle all situations properly?
- What skills, time and/or money are you able to contribute to this issue? Will you need the skills and/or money of others as well?
- Who might like things the way they are? Are there ways to resolve the issue that meet their needs as well as yours?
- Will your change be self-explanatory, or will other users need an explanation?
If you are able to coherently explain the problem and resolution&mdash;and reasonably confident that fix will be good for everyone&mdash;it's time to register the issue with CiviCRM.
### Research existing issues {:#research}
Search for existing issues that may be the same as or related to yours. Because CiviCRM transitioned from [Jira](#jira) to [GitLab](#gitlab) in early 2018, you'll need to search in both systems for existing issues. Jira's search will order by relevance, but you are searching over a decade of issues, so you may get overwhelmed with old items. Consider filtering Created Date to two years ago or newer.
If an issue directly describes your situation, your job will be different: read it over, and edit or comment as necessary. If the issue is marked as closed and completed, you should create a new issue indicating a regression, and you should link to the original issue you found.
If issues you find are related but not quite the same, you should still record them so that you can mention them in the issue you create.
### Open a blank issue {:#new}
Begin creating your issue as follows:
1. Sign in to [GitLab](https://lab.civicrm.org/)
1. Navigate to the appropriate GitLab project. For CiviCRM core, look in the [Development Team's projects](https://lab.civicrm.org/dev/).
1. Click the `+` button at the top of the screen and choose **New Issue**.
### Describe the issue {:#describe}
Give it a title that describes your issue concisely, and explain the issue in the details. In writing your issue, remember that your audience includes a variety of people:
- Other users encountering the same problem now
- Maintainers deciding whether to include your code
- Developers considering future changes
- The release notes editor compiling the notes
- Users browsing what's new in an upcoming version
Readers will come from different perspectives and contexts, so thorough explanations and coherent summaries are valuable. A well-written issue will be taken more seriously, increasing the likelihood that your changes are accepted and that others engage in your issue.
#### Naming your issue {:#naming}
*Vague issue titles are boring and unhelpful.* They don't inspire people to use or upgrade CiviCRM, and they make it difficult for implementors and developers to know what's different. Don't say "improve" unless the improvement is so scattered and subtle that you can't say anything else. Instead, make the specific improvements explicit.
Bug titles are slightly different, but they still should never be vague. *A good bug title simply says the bad thing that's happening.* Great examples include the following:
- "Batch merge redirects users to snippet URL"
- "Contribution page: missing translation"
- "Cannot create smart group from 'Find participants'"
The best leave no question as to what was going wrong or what has changed: something undesirable was happening, and once this issue is resolved, it won't happen anymore.
#### Issue scope {:#scope}
*It's important to keep your issue snappy and closeable.* A issue that stays open long after commits have been merged into core is confusing to users and demoralizing for contributors. The way to prevent this is to make issues distinct and coherent so they're clearly done or not done.
Better yet, describe the issue distinctly and coherently yourself. If you find an existing issue that was reported vaguely, there's no reason not to revise the description. If the original issue involves several things, don't be shy about closing it and opening new ones--just document what you've done.
A rule of thumb is that if an issue has more than 2 or 3 pull requests in GitHub (described below), something is wrong. It may be a series of false starts, and that's okay, but if it's a bunch of pull requests against the same repository, you probably should have opened new issues to describe the separate features or bugs&mdash;or to document a regression or feature gap.
See also: [pull request scope](git.md#pr-scope)
#### Categorization {:#categorization}
Categorization is useful for finding issues, and it also determines how issues appear in the release notes.
Use the Labels field to apply any relevant labels to your issue. You need to join the Development Group on Gitlab in order to be able to apply labels.
#### Confidentiality {:#confidentiality}
Issues can be marked Confidential, this is a useful "middle ground" status for issues which perhaps shouldn't be public but which are **not** security issues. If you have a security issue please report it as described at [Reporting a Security Vulnerability](../security/reporting/).
In GitLab a user can be either anonymous (no account), have a GitLab account but not be a project member, or be a project member. The confidential checkbox on issues will hide it from anonymous users and non-project members.
Anyone with an account can create confidential issues, but non-project members will only see their own. Please use confidential issues only where appropriate - transparency is important in our development processes and most development/code-related issues should be public.
## Guidelines for triaging issues {:#triage}
*This is the outcome of a meeting on 'how we do triage now we are in gitlab'*
### Identifying bugs - aka triage
Triage is how we deal with incoming bug reports &
* Categorise them
* Escalate any new critical bugs or regressions
* Provide first level support and / or ask additional questions / add additional information
Triage needs to be a fairly quick task in most instances & then depending on the extent to which the original submitter engages some tasks might not get much more attention.
Triage is done from this screen https://lab.civicrm.org/groups/dev/-/boards and in general the goal of 'product-maintenance' is to keep the first three columns clear - ie. triage, regressions & critical bugs.
### Categorisation
In Gitlab, issues are categorized by "Label", and multiple labels may be applied. A few of the most important labels are standalone terms:
* __`regression`__ - A problem which was demonstrably introduced by a recent change (*last few months*).
* __`triaged`__ - The issue has received an initial evaluation/categorization.
* __`prioritised`__ - The issue was designated by the product maintenance team as a priority.
Additionally, there are [a number of specific labels](https://lab.civicrm.org/dev/core/-/labels) organized with prefixes. This list is easier to navigate if you know the prefixes:
* __`comp:{$X}`__ - The *component* or *subsystem* or [functional area](https://stackoverflow.com/questions/16475979/what-is-the-difference-between-functional-and-non-functional-requirement).
* __Example__: The CiviMail component addresses the functional requirements to compose, send, and track email-blasts. Any bug, feature, or improvement relating to email-blasts would be `comp:CiviMail`.
* __`sig:{$X}`__: The *signficance* or *quality* or [non-functional requirement](https://stackoverflow.com/questions/16475979/what-is-the-difference-between-functional-and-non-functional-requirement).
* __Example__: If a screen unexpectedly terminates after pressing the letter "p", then it is not functioning correctly. That screen has a bug (`sig:bug`).
* __Example__: If a screen runs too slowly or consumes too many resources (CPU/RAM/disk), then the functionality is correct, but the screen has a `sig:performance` issue.
* __`needs:{$X}`__ - The next step that needs work/action.
* __Example__: Suppose an issue has been investigated and a patch was approved for the next release. The patch adds a new field, and this field needs to be explained in the "CiviCRM User Guide". The issue `needs:documentation`.
* __`type:{$X}`__ - The *type* indicates how this issue is being shepherded.
* __Example__: Suppose someone filed an issue because they believed it was important - but they did not have any specific capacity or resources allocated to fixing it. They're looking for other people to help with understanding/resolving it. This is a `type:request`.
For the most complete, current list of labels, see [Gitlab: Development > Core > Labels](https://lab.civicrm.org/dev/core/-/labels).
### Escalate any new critical bugs or regressions
Part of the triage process is figuring out if a bug is critical or a regression. Where they are they will be tagged and relevant people will be pinged on chat and from the issue.
### Provide first level support and / or ask additional questions / add additional information
The triager should ask questions if the issue is unclear or it is not clear how to replicate. Optionally the triager can try to replicate the bug (which has the benefit of testing the rc). The triager does not need to wait for responses before triaging the issue but if there is any possibility the bug is critical or a regression then they should add those tags so the issue does not lose visibility once triaged (they can be removed later after analysis)
# Jenkins continuous integration
Pull-requests are tested automatically with build-bot software called [Jenkins](https://jenkins.io/) which runs on [test.civicrm.org](http://test.civicrm.org/). Key things to know:
* If you are a new contributor, the tests may be placed on hold pending a cursory review. One of the administrators will post a comment like `jenkins, ok to test` or `jenkins, add to whitelist`.
* The pull-request will have a colored dot indicating its status:
* **Yellow**: The automated tests are running.
* **Red**: The automated tests have failed.
* **Green**: The automated tests have passed.
* If the automated test fails, click on the red dot to investigate details. Check for information in:
* The initial summary. Ordinarily, this will list test failures and error messages.
* The console output. If the test-suite encountered a significant error (such as a PHP crash), the key details will only appear in the console.
* __Tip__: Sometimes, the console output is pretty long (several hundred KB). This usually means that a majority of tests ran, but there's a failure mixed in somewhere. View the full log and search for the word `EXITCODE`; this should normally appear as blank or 0. The first non-empty `EXITCODE` should be close to the problem.
* __Tip__: Sometimes, the console output is relatively short (a page or two). You might look for evidence of one of these typical problems:
* A network service (such as `github.com` or `packagist.org`) was unavailable. These are usually corrected quickly without any action. Try running the test again.
* The pull-request is based on an old version of the codebase, and it cannot be applied cleanly with `git apply` or `git scan am`. Rebasing the PR branch should resolve this.
* On the test node, a local resource (such as disk-space, RAM, or inode count) was exhausted. If the failure was recent (past few hours), seek help on [the infrastructure channel](https://chat.civicrm.org/civicrm/channels/infrastructure). If the failure occurred a few hours or days ago, try running the test again.
* Some part of the build/test toolchain needs attention. For example, a test script may have been changed without supporting an edge-case; or a tool like `bower` or `npm` may need to be upgraded. Seek help on `infrastructure`.
* If the test appears to have failed randomly and you have been added to the whilelist by an admin, you can comment `test this please` to restart the test.
* Code-style tests are executed first. If the code-style in this patch is inconsistent, the remaining tests will be skipped.
* The primary tests may take 20-120 min to execute. This includes the following suites: `api_v3_AllTests`, `CRM_AllTests`, `Civi\AllTests`, `civicrm-upgrade-test`, and `karma`
* There are a handful of unit tests which are time-sensitive and which fail sporadically. See: https://forum.civicrm.org/index.php?topic=36964.0
* If needed, you can also manually [generate a test site](https://test.civicrm.org/job/CiviCRM-Manual/) with the PHP and
MYSQL versions, CMS and proposed patch you need or you can [manually run the test suites](https://test.civicrm.org/job/CiviCRM-Manual-Test/) with the same options.
* The web test suite (`WebTest_AllTests`) takes several hours to execute. [It runs separately -- after the PR has been merged.](https://test.civicrm.org/job/CiviCRM-WebTest-Matrix/)
For detailed discussion about automated tests, see [Testing](../testing/index.md)
# Using PhpStorm for CiviCRM Development
[PHPStorm](https://www.jetbrains.com/phpstorm) is a commercial IDE which is popular among CiviCRM developers.
## General project setup
* Use the root directory of your CMS as your project root (otherwise in-app debugging won't work)
* You can speed up PhpStorm's indexing process by taking the following steps to ignore most files:
1. **Settings > Directories**
1. Mark all directories as **Excluded**
1. Drill down to find the **civicrm** folder and mark it as **Sources**
## Code style setup
Create the CiviCRM code styling preference:
1. Open **Settings > Editor > Code Style**
1. Select **Scheme > Default** or **Project** if you want these settings to apply only to CiviCRM
1. In the **Code style** sub-menu, select PHP, then **Set from ...** at the far right, **Drupal** (this sets options across all tabs of the dialog), then click **Apply**
1. In the **Code style** sub-menu, select Javascript, then **Set from ...** at the far right, PHP (this replicates all PHP settings to the Javascript section), then click **Apply**
That's it. You can now use this code style on all future CiviCRM-related projects.
## XDebug integration
You need to configure XDebug on the webserver, phpstorm on the development machine and a debugger helper in the browser.
To configure XDebug and PHPStorm see: https://www.jetbrains.com/help/phpstorm/configuring-xdebug.html
For browser helpers see: https://confluence.jetbrains.com/display/PhpStorm/Browser+Debugging+Extensions
## Running automated tests from within PHPStorm {:#testing}
*PHPStorm provides convenient tools for running and debugging unit tests in-app.*
!!! note
These instructions assume you already have a working instance of CiviCRM running locally with [buildkit](buildkit).
1. On the CLI from a directory inside your build, run the command `civibuild phpunit-info`. This outputs configuration settings you will need to paste into PHPStorm.
2. From the `Run > Edit Configurations` menu edit the default PHPUnit configuration for your project.
3. Check "Use alternative configuration file" and choose the one output by the `civibuild` command.
4. Set the custom working directory as specified by the `civibuild` output.
5. Expand "Environment variables" and add the variables shown in the `civibuild` output.
For more detailed instructions (with screenshots!) see this [StackExchange answer](https://civicrm.stackexchange.com/questions/16489/how-do-i-run-php-unit-tests-w-xdebug-from-within-phpstorm-on-mac/16497#16497).
### Adding external libraries
It can be frustrating when writing tests the PHPStorm complains about missing classes or undefined methods. This happens because PHPUnit is not included in the CiviCRM codebase.
To remedy this you can add an external content root. You'll need to clone the [PHPUnit](https://phpunit.de/) library locally. Then from that directory check out the latest supported version of PHPUnit (4.x right now).
After that you just add the directory to your project include paths by [following the instructions on the Jetbrains site](https://www.jetbrains.com/help/phpstorm/configuring-include-paths.html).
Alternatively: always use buildkit to generate you CiviCRM development environment; it ships with many tools - including PHPUnit 4
The `universe` is the list of knowable codes, tools, add-ons, integrations, etc for CiviCRM. The `universe` includes:
* The standard CiviCRM git repositories (`civicrm-core.git`, `civicrm-packages.git`, etc).
* Any extensions registered on `civicrm.org` that have a Git URL.
* Most infrastructure and supporting components behind `civicrm.org`.
The `universe` can help you analyze the technical state of the CiviCRM community's code. For example, suppose you want to change the
signature of a function in `civicrm-core.git` named `getContactDetails(...)`. You can get a copy of the universe and search the entire
source tree for `getContactDetails` to see how it's being used.
!!! tip "Use a fast network and fast storage device (SSD)"
The `universe` is fairly big. (At time of writing, ~2 GB.) A fast network will help with downloading, and a fast storage will help
with searching.
## Create the universe
If your system is configured to support [civibuild](civibuild.md), then simply run:
```bash
$ civibuild create universe
```
Alternatively, if you have a copy of `buildkit` but don't use `civibuild`, then run:
```bash
$ mkdir ~/src/universe
$ fetch-universe ~/src/universe
```
## Search the universe
Note the path to your copy (eg `~/buildkit/build/universe` or `~/src/universe`) and `cd` to it.
```bash
$ cd ~/buildkit/build/universe
```
You can get a lot of information with standard Unix tools like `grep`, eg
```bash
$ grep -r getContactDetails .
```
There's a lot you can do with `grep`, such as:
```bash
# Case insensitive search
$ grep -ri getContactDetails .
# Ignore folders like `.git` or `.svn`
$ grep -r --exclude-dir=.git --exclude-dir=.svn getContactDetails .
# Edit all matching files
$ vi $(grep -ril getContactDetails .)
```
Of course, there's nothing special about `grep` here. Lots of other powerful tools will do the job, such as
[`ack`](https://beyondgrep.com/) or [the Silver Searcher](https://github.com/ggreer/the_silver_searcher). The author of `ack` has
published a longer [list of relevant tools](https://beyondgrep.com/more-tools/).
!!! tip "Why would you search `universe`?"
Continuing the example, you might argue, "`getContactDetails` isn't officially an API, so it's fair-game to change whenever we want.
Searching the universe doesn't add anything."
In *policy* terms, that might be right... but is it really a safe change in *practical* terms? Most of the time... probably! But
some of the time, Murphy's Law kicks in -- changing `getContactDetails(...)` might break 10 extensions. Arguably, the fault lies with
the extension author who called a non-API -- but that will bring little comfort to the 20 users who show up on StackExchange asking for
help, and it will still reflect badly on all of us.
Searching `universe` is a simple way to get ahead of that risk -- and to make decisions based on *empirical data* rather than
proscriptive notions.
!!! tip "What to do if searching `universe` reveals a technical conflict?"
The `universe` is just a tool -- it's a way to get ahead of problems (by making them easier to discover). It's not an over-arching policy on
what to do if you find a conflict. Returning to our `getContactDetails` example:
* Maybe you should change the approach -- keep the signature of `getContactDetails` as-is, but change something else.
* Or maybe the extensions should be updated to match the new signature.
* Or maybe you should give a heads-up to the other affected developers.
We're not trying to pre-judge the solution here. Main advice: start from the assumption that this is a shared problem. Finding a
solution is good for you, for the other developers, and for the users. Encourage others to view it the same way.
## Update the universe
The `universe` is ever-expanding -- eg projects are updated, and new projects are added. Generally, it's not important to be accurate
"up-to-the-minute". But you may want to update if your copy of the universe is more than a week or two old.
Simply note the path to your copy (eg `~/buildkit/build/universe` or `~/src/universe`) and run `fetch-universe`:
```bash
$ fetch-universe ~/buildkit/build/universe
```
# Database localized fields and upgrades
## PHP code related to database upgrades
We try to reduce the number of strings that will be practically never seen by administrators. Very unlikely error messages should be left untranslated.
For example, in `CRM_Upgrade_Incremental_php_FourSeven`, `addTask()` task names such as "Upgrade DB to ..." should be translated:
```php
$this->addTask(
ts('Upgrade DB to %1: SQL', array(1 => '4.3.5')),
'task_4_3_x_runSql',
$rev
);
```
Very specific one-time tasks should not be translated (wrapped in `ts`). Administrators are very unlikely to see such strings. If they do, they will probably need the original English string in order to get support on the forums. They are also strings that are very hard to translate because of lack of context.
For example, do not translate:
```php
$this->addTask(
'Update financial_account_id in financial_trxn table',
'updateFinancialTrxnData',
$rev
);
```
## Localized fields
Any value stored in the database that may depend on the language must be localizable. For example:
* A contribution page title or description,
* A group title or description,
* A configurable string to display on forms (ex: a custom "submit" button label).
However, since localizable fields add a certain technical complexity, the following type of fields are not localized:
* Contact information, such as the first name, nickname, etc.
* Address fields.
While there are many cities where street names can officially be in multiple languages (or have official transliterations), users usually enter their address only in one language. It is rarely required to store the address translation (one exception: event locations, which is currently a known limitation).
Similarly, the first and last name of an individual may be written in different alphabets (ex: Latin and Cyrillic), but this is not a frequent use-case worth the complexity. Administrators can workaround this by creating custom fields.
In order to define a field as localizable, the [schema definition](../framework/entities/index.md) for that field must have the following tag:
```
<localizable>true</localizable>
```
If a new field was not initially tagged as localizable, the upgrade must explicitly convert the field. See the section below on localised fields schema changes.
## SQL upgrades
SQL upgrades must account for two use-cases:
* localized CiviCRM: the values in the database are in one language only, so no new database fields are created, however
* multi-lingual CiviCRM: a typical `value` field will be removed, and replaced with `value_en_US`, `value_fr_FR`, and so on.
There are two variables exposed to the sql templates when upgrading: `$multilingual` makes it possible to test if the database is multi-lingual, while `$locales` lists the enabled languages. For example:
```smarty
{if $multilingual}
{foreach from=$locales item=locale}
UPDATE civicrm_option_group
SET label_{$locale} = description_{$locale}
WHERE label_{$locale} IS NULL;
{/foreach}
{else}
UPDATE civicrm_option_group
SET `label` = `description`
WHERE `label` IS NULL;
{/if}
```
However the `{localize}` helper for SQL upgrades (e.g. statements in `CRM/Upgrade/Incremental/sql/*.mysql.tpl` files) allows you do the same thing without explicitly looping on locales. This `UPDATE` statement handles both multi-lingual and non-multi-lingual cases.
```smarty
UPDATE `civicrm_premiums`
SET
{localize field="premiums_nothankyou_label"}
premiums_nothankyou_label = '{ts escape="sql"}No thank-you{/ts}'
{/localize};
```
On a multi-lingual site with English and French enabled, this would evaluate to:
```sql
UPDATE `civicrm_premiums`
SET
premiums_nothankyou_label_en_US = 'No thank-you',
premiums_nothankyou_label_fr_FR = 'Non merci';
```
The `{ts}` tag translates the string based on the default language that is set _when the upgrade is being run_. In the above example if the upgrade was run while the default language was French, that column would be set to "Merci non". It would be good to fix this so that the values for each enabled language are translated when a translated string is available.
For an `INSERT` example, the following query:
```smarty
INSERT INTO civicrm_option_value (
option_group_id,
{localize field='label'}label{/localize},
value,
name,
filter,
weight,
is_active )
VALUES (
@option_group_id_ere,
{localize}'{ts escape="sql"}Participant Role{/ts}'{/localize},
1,
'participant_role',
0,
1,
1 );
```
On a multi-lingual site with English and French enabled, the above would evaluate to:
```sql
INSERT INTO civicrm_option_value (
option_group_id,
label_en_US,
label_fr_FR,
value,
name,
filter,
weight,
is_active )
VALUES (
@option_group_id_ere,
'Participant Role',
'Rôle du participant',
1,
'participant_role',
0,
1,
1 );
```
## Localised fields schema changes
Two use-cases:
1. An existing field in CiviCRM was not tagged in the [schema](../framework/entities/index.md) as `'localizable' => TRUE` (ex: the `title` in `civicrm_survey`, before CiviCRM 4.5). After adding the `<localize>` tag in the XML file, you must also add an upgrade snippet for existing databases. Example, from `sql/4.1.0.mysql.tpl`:
```smarty
{if $multilingual}
{foreach from=$locales item=locale}
ALTER TABLE civicrm_pcp_block ADD link_text_{$locale} varchar(255);
UPDATE civicrm_pcp_block SET link_text_{$locale} = link_text;
{/foreach}
ALTER TABLE civicrm_pcp_block DROP link_text;
{/if}
```
2. If a localized field was removed or added, the schema does odd things during the upgrade to figure out which fields are mutli-lingual. Rebuilding the multi-lingual schema will check in `CRM/Core/I18n/SchemaStructure.php` for the fields used by the database views. If the schema is changed, copy the `SchemaStructure.php` from the master branch to, for example, `SchemaStructure_4_5_alpha1.php` and rename the class as appropriate. The 4.5 alpha1 will then read this file when rebuilding the schema, see `CRM/Core/I18n/Schema.php` for more information (`getLatestSchema`). i.e. during an upgrade, we may be upgrading from 4.0 to 4.5, and when rebuilding the views at each stage, we need to load the correct schema version. Since we do not have a schema file for each minor version, CiviCRM will attempt to load the most relevant schema version to the version of the upgrade step being run.
# Translation for Developers
Developers should write their code so that it may be localized to various languages and regions of the world.
If you are an extension developer, there is additional documentation in the [Extension translation](../extensions/translation.md) page.
## PHP
* The strings hard-coded into PHP should be wrapped in `ts()` function calls. For example:
```php
$string = ts('Hello, World!');
$options = [
1 => ts('One'),
2 => ts('Two'),
3 => ts('Three'),
];
```
* You can also use placeholders for variables:
```php
$string = ts("A new '%1' has been created.", [1 => $contactType]);
```
Note that variables should themselves be translated by your code before passing in, if appropriate.
* If the string needs to be pluralized, use the singular form as the main string, and provide the count (integer) and plural (string) in the 2nd argument along with any placeholder values:
```php
$string = ts('%count item was created by %1', [
'count' => $total,
'plural' => '%count items were created by %1',
1 => $userName,
]);
```
## Javascript
When translating strings in an extension, ts scope needs to be declared. The `CRM.ts` function takes scope as an argument and returns a function that always applies that scope to ts calls:
```js
// This closure gets a local copy of jQuery, Lo-dash, and ts
(function($, _, ts) {
CRM.alert(ts('Your foo has been barred.'));
})(CRM.$, CRM._, CRM.ts('foo.bar.myextension'));
```
!!! note
`CRM.ts` is not the same as the global `ts` function. `CRM.ts` is a function that returns a function (javascript is wacky like that). Since your closure gives the local `ts` the same name as the global `ts`, it will be used instead.
!!! important
Your local version of `ts` could be named anything, but strings in your javascript file cannot be accurately parsed unless you name it `ts`.
## Smarty templates
* The strings hard-coded into templates should be wrapped in `{ts}...{/ts}` tags. For example:
```smarty
{ts}Full or partial name (last name, or first name, or organization name).{/ts}
```
* If you need to pass a variable to the localizable string, you should use the following pattern:
```smarty
<div class="status">
{ts 1=$delName}Are you sure you want to delete <b>%1</b> Tag?{/ts}
</div>
```
## Best practices
The general rules for avoiding errors may be summed up as:
* The first argument to `ts()` must be a single, literal string.
* The string must not contain variables, concatenation, line-breaks, or leading/trailing spaces.
* The second parameter of the `ts()` call is an array of variables to swap for placeholders in the string.
### Use placeholders instead of variables inside strings
!!! failure "Bad"
```php
$string = ts("The date type '$name' has been saved.");
```
!!! success "Good"
```php
$string = ts("The date type '%1' has been saved.", [1 => $name]);
```
### Avoid tags inside strings
!!! failure "Bad"
```smarty
{ts}<p>Hello, world!</p>{/ts}
```
!!! success "Good"
```smarty
<p>{ts}Hello, world!{/ts}</p>
```
Hyperlinks within larger blocks of text are an exception to this rule, where you should place the `<a>` tags within the `ts`. Any link parameters should be provided as arguments to the ts. For example:
!!! failure "Bad"
```smarty
{ts}Here is a block of text with a link to the <a href="https://www.civicrm.org" target="_blank">CiviCRM Web Site</a>.{/ts}
```
!!! success "OK"
```smarty
{ts 1='href="https://www.civicrm.org" target="_blank"'}Here is a block of text with a link to the <a %1>CiviCRM Web Site</a>.{/ts}
```
Smarty doesn't evaluate within single quotes, so if you are capturing an URL for a link, capture it with the `href="` and optionally `target="_blank"`.
!!! success "OK"
```smarty
{capture assign=something}href="{crmURL p='civicrm/admin/something' q='reset=1'}" target="_blank"{/capture}
{ts 1=$something}Here is a block of text with a link to a <a %1>specific URL in CiviCRM</a>.{/ts}
```
For `title` attributes in `<a>` links, within CiviCRM these usually only appear in links that aren't within a larger block of text or where there is no clickable text, such as a datepicker icon. In this situation, the title text needs to be translated:
!!! failure "Bad"
```smarty
{ts}<a href="https://www.example.org/civicrm/something?reset=1" title="List participants for this event (all statuses)">Participants</a>{/ts}
```
!!! success "Good"
```smarty
<a href="https://www.example.org/civicrm/something?reset=1" title="{ts}List participants for this event (all statuses){/ts}">{ts}Participants{/ts}</a>
```
If there is no clickable text, just translate the title attribute:
!!! success "Good"
```smarty
<a title="{ts}Select Date{/ts}"><i class="crm-i fa-calendar"></i></a>
```
### Avoid multi-line strings
Even if your code editor may not like it, long strings should be on a single line since a change in indentation might change where the line breaks are, which would then require re-translating the string.
!!! failure "Bad"
```php
$string = ts("Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Proin elementum, ex in pretium tincidunt, felis lorem facilisis
lacus, vel iaculis ex orci vitae risus. Maecenas in sapien ut velit
scelerisque interdum.");
```
!!! success "Good"
```php
$string = ts("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin elementum, ex in pretium tincidunt, felis lorem facilisis lacus, vel iaculis ex orci vitae risus. Maecenas in sapien ut velit scelerisque interdum.");
```
### Avoid strings which begin or end with spaces
!!! failure "Bad"
```php
$string = $labelFormat['label'] . ts(' has been created.'),
```
!!! success "Good"
```php
$string = ts('%1 has been created.', [1 => $labelFormat['label']]),
```
### Avoid escaped quotes whenever possible
!!! failure "Bad"
```php
$string = ts('A new \'%1\' has been created.', [1 => $contactType]);
```
!!! success "Good"
```php
$string = ts("A new '%1' has been created.", [1 => $contactType]);
```
### Use separate strings for plural items
!!! failure "Bad"
```php
$string = ts('%1 item(s) were created by %2', [1 => $count, 2 => $userName]);
```
!!! success "Good"
```php
$string = ts('%count item was created by %1', [
'count' => $total,
'plural' => '%count items were created by %1',
1 => $userName,
]);
```
### Ensure that strings have *some* words in them
Another common error is to use `ts()` to aggregate strings or as a "clever" way of writing shorter code:
!!! failure "Bad"
Incorrect aggregation. This will be extremely confusing to translators and might give some really bad results in some languages.
```php
$operation = empty($params['id']) ? ts('New') : ts('Edit'));
$string = ts("%1 %2", [1 => $operation, 2 => $contactType]);
```
!!! success "OK"
```php
if (empty($params['id'])) {
$string = ts("New %1", [1 => $contactType]);
}
else {
$string = ts("Edit %1", [1 => $contactType]);
}
```
Note that this still makes it difficult to use the correct gender.
### Include typography in strings
Typography is different in different languages and thus must be translated along with the string. For example, in French, there must be a space before a colon.
!!! failure "Bad"
```smarty
{ts}Event Total{/ts}:
```
!!! success "Good"
```smarty
{ts}Event Total:{/ts}
```
## Rationale for using Gettext
In most projects, strings are typically translated by either:
* using Gettext (which is what CiviCRM does),
* using arrays of key/string dictionaries,
* using database lookups of strings (which is what Drupal does).
In order to be support Joomla!, WordPress, Backdrop and eventually other content management systems. Gettext is the standard way to translate strings in PHP, used by most projects.
## Other guides/references
Here are the guides to other popular projects:
* Drupal: <https://www.drupal.org/node/322729>
* Joomla!: <https://docs.joomla.org/Specification_of_language_files>
* WordPress: <https://codex.wordpress.org/I18n_for_WordPress_Developers>
site_name: CiviCRM Developer Guide
repo_url: https://github.com/civicrm/civicrm-dev-docs
site_name: Developer Guide
site_url: https://docs.civicrm.org/dev/en/latest/
repo_url: https://lab.civicrm.org/documentation/docs/dev
edit_uri: https://lab.civicrm.org/documentation/docs/dev/-/edit/master/docs/
site_description: A guide for CiviCRM developers.
site_author: The CiviCRM community
theme: readthedocs
extra_javascript:
- js/custom.js
theme:
name: material
icon:
repo: fontawesome/brands/gitlab
markdown_extensions:
- markdown.extensions.admonition
- markdown.extensions.attr_list
pages:
- attr_list
- admonition
- def_list
- toc:
permalink: true
- pymdownx.details
- pymdownx.highlight:
guess_lang: true
extend_pygments_lang:
- name: php
lang: php
options:
startinline: true
- pymdownx.superfences:
css_class: codehilite
- pymdownx.inlinehilite:
css_class: codehilite
- pymdownx.tilde
- pymdownx.betterem
- pymdownx.mark
plugins:
- search:
lang: en
nav:
- Home: index.md
- Basics:
- Developer Community: basics/community.md
- Prerequisite skills: basics/skills.md
- Requirements: requirements.md
- Planning your project: basics/planning.md
- Build: build.md
- Customize: customize.md
- Extend: extend.md
- Develop: develop.md
- Testing: testing.md
- Writing Documentation: documentation.md
- Development Environment:
- Debugging: dev-tools/debugging.md
- APIv3:
- API Intro: api/general.md
- API Usage: api/usage.md
- API Actions: api/actions.md
- API Parameters: api/params.md
- API Chaining: api/chaining.md
- Hooks:
- How to Use Hooks: hook.md
- All Available Hooks: hooks-db.md
- Writing Extensions:
- Basics: extensions/basics.md
- Using civix: extensions/civix.md
- Anatomy of Files: extensions/files.md
- Advanced Patterns: extensions/advanced.md
- Requirements: basics/requirements.md
- Useful Skills: basics/skills.md
- Planning Your Project: basics/planning.md
- Buildkit:
- Overview: tools/buildkit.md
- Apt-Get: tools/buildkit/apt-get.md
- Docker: tools/buildkit/docker.md
- Generic: tools/buildkit/generic.md
- Nix: tools/buildkit/nix.md
- Vagrant: tools/buildkit/vagrant.md
- Virtual Desktop: tools/buildkit/virtual.md
- Tools:
- Development Tools: tools/index.md
- civibuild: tools/civibuild.md
- cividist: tools/cividist.md
- civilint: tools/civilint.md
- civi-test-run: tools/civi-test-run.md
- Issue Tracking: tools/issue-tracking.md
- Git, GitHub, &amp; GitLab: tools/git.md
- Jenkins: tools/jenkins.md
- PhpStorm: tools/phpstorm.md
- Debugging: tools/debugging.md
- Universe: tools/universe.md
- Core:
- When to Edit Core: core/hacking.md
- How to Contribute: core/contributing.md
- Reviewing a PR: core/pr-review.md
- Verifying a Bug Fix: core/verify-fix.md
- Release Process: core/release-process.md
- Dependencies: core/dependencies.md
- Form Builder (Afform):
- Overview: afform/overview.md
- Afform Core: afform/afform-core.md
- Form Builder: afform/form-builder.md
- Search Forms: afform/search-forms.md
- Events: afform/afform-events.md
- Behaviors: afform/afform-behaviors.md
- Search Kit:
- Overview: searchkit/overview.md
- Query Building with APIv4: searchkit/queries.md
- Links and Tasks: searchkit/tasks.md
- Displays and the AngularJS UI: searchkit/displays.md
- Add Saved Search to Your Own Extension: searchkit/extension.md
- Financial:
- Overview: financial/overview.md
- Order API: financial/orderAPI.md
- Payment API: financial/paymentAPI.md
- Entities: financial/financialentities.md
- Recurring Contributions: financial/recurring-contributions.md
- Extensions:
- Basics: extensions/index.md
- Packaging Options: extensions/packaging.md
- civix: extensions/civix.md
- civix (legacy): extensions/civix-legacy.md
- Extension Structure: extensions/structure.md
- info.xml File: extensions/info-xml.md
- Managed Entities: extensions/managed.md
- Documentation: extensions/documentation.md
- Pop-up Help: extensions/helptext.md
- Translation: extensions/translation.md
- Publishing Extensions: extensions/publish.md
- Extension Lifecycle: extensions/lifecycle.md
- Troubleshooting: extensions/troubleshooting.md
# - Using hooks: extensions/using-hooks.md
# - Customizing Screens: extensions/customize-screens.md
# - Creating Pages: Forms/extensions/create-page.md
# - Storing Configuration: extensions/config.md
# - Storing Data: extensions/storing-data.md
# - Setting Permissions: extensions/permissions.md
# - Custom API Functions: extensions/custom-api.md
# - Custom Reports: extensions/custom-reports.md
# - Custom Searches: extensions/custom-searches.md
# - Payment Processors: extensions/payment-processor.md
- Publish: extensions/publish.md
- Best Practices:
- Documentation Style Guide: best-practices/documentation-style-guide.md
- Core code:
- Hacking the core: core/hacking.md
- Architecture: core/architecture.md
- Miscellaneous:
- Extension Lifecycle: extend-stages.md
- Markdown: markdownrules.md
# - hookref-old: hookref-old.md
- Deprecated:
- Building CiviCRM from source: develop-deprecated.md
- Advanced Patterns: extensions/advanced.md
- Payment Processors:
- Overview: extensions/payment-processors/overview.md
- The Payment Class: extensions/payment-processors/paymentclass.md
- Testing: extensions/payment-processors/testing.md
- CMS-specific development: extensions/cms-specific.md
- API:
- API Intro: api/index.md
- APIv4:
- APIv4 Usage: api/v4/usage.md
- APIv4 Actions: api/v4/actions.md
- APIv4 Fields: api/v4/fields.md
- Relational Data:
- Implicit Joins: api/v4/implicit-joins.md
- Explicit Joins: api/v4/explicit-joins.md
- Set Operations: api/v4/set-ops.md
- Option Lists: api/v4/pseudoconstants.md
- Chaining: api/v4/chaining.md
- Custom Data: api/v4/custom-data.md
- Managed APIv4 Entities: api/v4/managed.md
- Differences Between Api v3 and v4: api/v4/differences-with-v3.md
- APIv4 Architecture: api/v4/architecture.md
- APIv4 Changelog: api/v4/changes.md
- APIv4 REST: api/v4/rest.md
- APIv3:
- APIv3 Usage: api/v3/usage.md
- APIv3 Interfaces: api/v3/interfaces.md
- APIv3 Actions: api/v3/actions.md
- APIv3 Options: api/v3/options.md
- APIv3 Joins: api/v3/joins.md
- APIv3 Chaining: api/v3/chaining.md
- APIv3 Custom Data: api/v3/custom-data.md
- APIv3 Examples: api/v3/examples.md
- APIv3 Changelog: api/v3/changes.md
- APIv3 REST: api/v3/rest.md
- WordPress REST Interface: api/v3/wp-rest.md
- API ERDs: api/ERDs/index.md
- Hooks:
- Hooks Introduction: hooks/index.md
- Hooks Changelog: hooks/changes.md
- Usage:
- Hooks in Extensions: hooks/usage/extension.md
- Hooks in Symfony: hooks/usage/symfony.md
- Hooks in Drupal: hooks/usage/drupal.md
- Hooks in Joomla: hooks/usage/joomla.md
- Hooks in WordPress: hooks/usage/wordpress.md
- All Hooks: hooks/list.md
- Batch Hooks:
- hook_civicrm_batchItems: hooks/hook_civicrm_batchItems.md
- hook_civicrm_batchQuery: hooks/hook_civicrm_batchQuery.md
- Case Hooks:
- hook_civicrm_caseChange: hooks/hook_civicrm_caseChange.md
- hook_civicrm_caseEmailSubjectPatterns: hooks/hook_civicrm_caseEmailSubjectPatterns.md
- hook_civicrm_caseTypes: hooks/hook_civicrm_caseTypes.md
- hook_civicrm_post_case_merge: hooks/hook_civicrm_post_case_merge.md
- hook_civicrm_pre_case_merge: hooks/hook_civicrm_pre_case_merge.md
- Database Hooks:
- hook_civicrm_alterLocationMergeData: hooks/hook_civicrm_alterLocationMergeData.md
- hook_civicrm_copy: hooks/hook_civicrm_copy.md
- hook_civicrm_custom: hooks/hook_civicrm_custom.md
- hook_civicrm_customPre: hooks/hook_civicrm_customPre.md
- hook_civicrm_managed: hooks/hook_civicrm_managed.md
- hook_civicrm_merge: hooks/hook_civicrm_merge.md
- hook_civicrm_post: hooks/hook_civicrm_post.md
- hook_civicrm_postCommit: hooks/hook_civicrm_postCommit.md
- hook_civicrm_postSave_table_name: hooks/hook_civicrm_postSave_table_name.md
- hook_civicrm_pre: hooks/hook_civicrm_pre.md
- hook_civicrm_referenceCounts: hooks/hook_civicrm_referenceCounts.md
- hook_civicrm_triggerInfo: hooks/hook_civicrm_triggerInfo.md
- Dedupe Hooks:
- hook_civicrm_dupeQuery: hooks/hook_civicrm_dupeQuery.md
- hook_civicrm_findDuplicates: hooks/hook_civicrm_findDuplicates.md
- Entity Hooks:
- hook_civicrm_entityTypes: hooks/hook_civicrm_entityTypes.md
- Extension Lifecycle Hooks:
- hook_civicrm_disable: hooks/hook_civicrm_disable.md
- hook_civicrm_enable: hooks/hook_civicrm_enable.md
- hook_civicrm_install: hooks/hook_civicrm_install.md
- hook_civicrm_postInstall: hooks/hook_civicrm_postInstall.md
- hook_civicrm_uninstall: hooks/hook_civicrm_uninstall.md
- hook_civicrm_upgrade: hooks/hook_civicrm_upgrade.md
- Form Hooks:
- hook_civicrm_alterAngular: hooks/hook_civicrm_alterAngular.md
- hook_civicrm_alterContent: hooks/hook_civicrm_alterContent.md
- hook_civicrm_alterTemplateFile: hooks/hook_civicrm_alterTemplateFile.md
- hook_civicrm_buildForm: hooks/hook_civicrm_buildForm.md
- hook_civicrm_idsException: hooks/hook_civicrm_idsException.md
- hook_civicrm_postProcess: hooks/hook_civicrm_postProcess.md
- hook_civicrm_preProcess: hooks/hook_civicrm_preProcess.md
- <del>hook_civicrm_validate</del>: hooks/hook_civicrm_validate.md
- hook_civicrm_validateForm: hooks/hook_civicrm_validateForm.md
- GUI Hooks:
- hook_civicrm_activeTheme: hooks/hook_civicrm_activeTheme.md
- hook_civicrm_alterBundle: hooks/hook_civicrm_alterBundle.md
- hook_civicrm_alterCustomFieldDisplayValue: hooks/hook_civicrm_alterCustomFieldDisplayValue.md
- hook_civicrm_alterEntityRefParams: hooks/hook_civicrm_alterEntityRefParams.md
- hook_civicrm_alterMenu: hooks/hook_civicrm_alterMenu.md
- hook_civicrm_alterAdminPanel: hooks/hook_civicrm_alterAdminPanel.md
- hook_civicrm_buildAmount: hooks/hook_civicrm_buildAmount.md
- hook_civicrm_caseSummary: hooks/hook_civicrm_caseSummary.md
- hook_civicrm_contact_get_displayname: hooks/hook_civicrm_contact_get_displayname.md
- <del>hook_civicrm_customFieldOptions</del>: hooks/hook_civicrm_customFieldOptions.md
- hook_civicrm_dashboard: hooks/hook_civicrm_dashboard.md
- hook_civicrm_dashboard_defaults: hooks/hook_civicrm_dashboard_defaults.md
- hook_civicrm_entityRefFilters: hooks/hook_civicrm_entityRefFilters.md
- hook_civicrm_fieldOptions: hooks/hook_civicrm_fieldOptions.md
- hook_civicrm_links: hooks/hook_civicrm_links.md
- hook_civicrm_navigationMenu: hooks/hook_civicrm_navigationMenu.md
- hook_civicrm_pageRun: hooks/hook_civicrm_pageRun.md
- hook_civicrm_searchColumns: hooks/hook_civicrm_searchColumns.md
- hook_civicrm_searchTasks: hooks/hook_civicrm_searchTasks.md
- hook_civicrm_searchKitTasks: hooks/hook_civicrm_searchKitTasks.md
- hook_civicrm_summary: hooks/hook_civicrm_summary.md
- hook_civicrm_summaryActions: hooks/hook_civicrm_summaryActions.md
- hook_civicrm_themes: hooks/hook_civicrm_themes.md
- <del>hook_civicrm_tabs</del>: hooks/hook_civicrm_tabs.md
- hook_civicrm_tabset: hooks/hook_civicrm_tabset.md
- hook_civicrm_xmlMenu: hooks/hook_civicrm_xmlMenu.md
- Import Hooks:
- hook_civicrm_importAlterMappedRow: hooks/hook_civicrm_importAlterMappedRow.md
- <del>hook_civicrm_import</del>: hooks/hook_civicrm_import.md
- Mail Hooks:
- hook_civicrm_alterMailContent: hooks/hook_civicrm_alterMailContent.md
- hook_civicrm_alterMailer: hooks/hook_civicrm_alterMailer.md
- hook_civicrm_alterMailParams: hooks/hook_civicrm_alterMailParams.md
- hook_civicrm_alterMailStore: hooks/hook_civicrm_alterMailStore.md
- hook_civicrm_alterMailingRecipients: hooks/hook_civicrm_alterMailingRecipients.md
- hook_civicrm_emailProcessor: hooks/hook_civicrm_emailProcessor.md
- hook_civicrm_emailProcessorContact: hooks/hook_civicrm_emailProcessorContact.md
- hook_civicrm_mailingGroups: hooks/hook_civicrm_mailingGroups.md
- hook_civicrm_mailSetupActions: hooks/hook_civicrm_mailSetupActions.md
- hook_civicrm_postEmailSend: hooks/hook_civicrm_postEmailSend.md
- hook_civicrm_postMailing: hooks/hook_civicrm_postMailing.md
- hook_civicrm_unsubscribeGroups: hooks/hook_civicrm_unsubscribeGroups.md
- Membership Hooks:
- hook_civicrm_alterCalculatedMembershipStatus: hooks/hook_civicrm_alterCalculatedMembershipStatus.md
- hook_civicrm_membershipTypeValues: hooks/hook_civicrm_membershipTypeValues.md
- Permission Hooks:
- hook_civicrm_aclGroup: hooks/hook_civicrm_aclGroup.md
- hook_civicrm_aclWhereClause: hooks/hook_civicrm_aclWhereClause.md
- hook_civicrm_alterApiRoutePermissions: hooks/hook_civicrm_alterApiRoutePermissions.md
- hook_civicrm_alterAPIPermissions: hooks/hook_civicrm_alterAPIPermissions.md
- hook_civicrm_invalidateChecksum: hooks/hook_civicrm_invalidateChecksum.md
- <del>hook_civicrm_notePrivacy</del>: hooks/hook_civicrm_notePrivacy.md
- hook_civicrm_permission: hooks/hook_civicrm_permission.md
- hook_civicrm_permission_check: hooks/hook_civicrm_permission_check.md
- hook_civicrm_permissionList: hooks/hook_civicrm_permissionList.md
- hook_civicrm_selectWhereClause: hooks/hook_civicrm_selectWhereClause.md
- Profile Hooks:
- hook_civicrm_buildProfile: hooks/hook_civicrm_buildProfile.md
- hook_civicrm_buildUFGroupsForModule: hooks/hook_civicrm_buildUFGroupsForModule.md
- hook_civicrm_processProfile: hooks/hook_civicrm_processProfile.md
- hook_civicrm_searchProfile: hooks/hook_civicrm_searchProfile.md
- hook_civicrm_validateProfile: hooks/hook_civicrm_validateProfile.md
- hook_civicrm_viewProfile: hooks/hook_civicrm_viewProfile.md
- Queue Hooks:
- hook_civicrm_queueActive: hooks/hook_civicrm_queueActive.md
- hook_civicrm_queueRun: hooks/hook_civicrm_queueRun.md
- hook_civicrm_queueStatus: hooks/hook_civicrm_queueStatus.md
- hook_civicrm_queueTaskError: hooks/hook_civicrm_queueTaskError.md
- Report Hooks:
- hook_civicrm_alterReportVar: hooks/hook_civicrm_alterReportVar.md
- SMS Hooks:
- hook_civicrm_inboundSMS: hooks/hook_civicrm_inboundSMS.md
- Scheduled Job / cron Hooks:
- hook_civicrm_cron: hooks/hook_civicrm_cron.md
- hook_civicrm_preJob: hooks/hook_civicrm_preJob.md
- hook_civicrm_postJob: hooks/hook_civicrm_postJob.md
- Token Hooks/listeners:
- civi.token.eval: hooks/civi.token.eval.md
- civi.token.list: hooks/civi.token.list.md
- <del>hook_civicrm_tokens</del>: hooks/hook_civicrm_tokens.md
- <del>hook_civicrm_tokenValues</del>: hooks/hook_civicrm_tokenValues.md
- Uncategorized Hooks:
- hook_civicrm_alterBadge: hooks/hook_civicrm_alterBadge.md
- hook_civicrm_alterBarcode: hooks/hook_civicrm_alterBarcode.md
- hook_civicrm_alterExternUrl: hooks/hook_civicrm_alterExternUrl.md
- hook_civicrm_alterLogTables: hooks/hook_civicrm_alterLogTables.md
- hook_civicrm_alterMailingLabelParams: hooks/hook_civicrm_alterMailingLabelParams.md
- hook_civicrm_alterPaymentProcessorParams: hooks/hook_civicrm_alterPaymentProcessorParams.md
- hook_civicrm_alterRedirect: hooks/hook_civicrm_alterRedirect.md
- hook_civicrm_alterSettingsFolders: hooks/hook_civicrm_alterSettingsFolders.md
- hook_civicrm_alterSettingsMetaData: hooks/hook_civicrm_alterSettingsMetaData.md
- hook_civicrm_alterUFFIelds: hooks/hook_civicrm_alterUFFields.md
- hook_civicrm_angularModules: hooks/hook_civicrm_angularModules.md
- hook_civicrm_apiWrappers: hooks/hook_civicrm_apiWrappers.md
- hook_civicrm_buildAsset: hooks/hook_civicrm_buildAsset.md
- hook_civicrm_buildStateProvinceForCountry: hooks/hook_civicrm_buildStateProvinceForCountry.md
- hook_civicrm_check: hooks/hook_civicrm_check.md
- hook_civicrm_config: hooks/hook_civicrm_config.md
- <del>hook_civicrm_contactListQuery</del>: hooks/hook_civicrm_contactListQuery.md
- hook_civicrm_container: hooks/hook_civicrm_container.md
- hook_civicrm_coreResourceList: hooks/hook_civicrm_coreResourceList.md
- <del>hook_civicrm_crudLink></del>: hooks/hook_civicrm_crudLink.md
- hook_civicrm_crypto: hooks/hook_civicrm_crypto.md
- hook_civicrm_cryptoRotateKey: hooks/hook_civicrm_cryptoRotateKey.md
- hook_civicrm_eventDiscount: hooks/hook_civicrm_eventDiscount.md
- hook_civicrm_export: hooks/hook_civicrm_export.md
- hook_civicrm_fileSearches: hooks/hook_civicrm_fileSearches.md
- hook_civicrm_geocoderFormat: hooks/hook_civicrm_geocoderFormat.md
- hook_civicrm_getAssetUrl: hooks/hook_civicrm_getAssetUrl.md
- hook_civicrm_oauthProviders: hooks/hook_civicrm_oauthProviders.md
- hook_civicrm_oauthReturn: hooks/hook_civicrm_oauthReturn.md
- hook_civicrm_oauthReturnError: hooks/hook_civicrm_oauthReturnError.md
- <del>hook_civicrm_optionValues</del>: hooks/hook_civicrm_optionValues.md
- hook_civicrm_postIPNProcess: hooks/hook_civicrm_postIPNProcess.md
- hook_civicrm_queryObjects: hooks/hook_civicrm_queryObjects.md
- hook_civicrm_recent: hooks/hook_civicrm_recent.md
- hook_civicrm_scanClasses: hooks/hook_civicrm_scanClasses.md
- hook_civicrm_unhandledException: hooks/hook_civicrm_unhandledException.md
- hook_civicrm_userContentPolicy: hooks/hook_civicrm_userContentPolicy.md
- Testing:
- Testing: testing/index.md
- Continuous Integration: testing/continuous-integration.md
- PHP:
- PHPUnit Tests: testing/phpunit.md
# - Codeception Tests: testing/codeception.md
- Selenium Tests: testing/selenium.md
- Mink Tests: testing/mink.md
- Javascript:
- Karma Tests: testing/karma.md
# - Protractor Tests: testing/protractor.md
- QUnit Tests: testing/qunit.md
- Codeception: testing/codeception.md
- Protractor: testing/protractor.md
- Other:
- Upgrade Tests: testing/upgrades.md
- Manual Tests: testing/manual.md
- Security:
- Secure Coding: security/index.md
- Securing Inputs: security/inputs.md
- Securing Outputs: security/outputs.md
- Permissions: security/permissions.md
- Access Control: security/access.md
- Reporting Vulnerabilities: security/reporting.md
- Request Forgery: security/csrf.md
- Framework:
- AJAX Pages and Forms Reference: framework/ajax.md
- AngularJS:
- AngularJS Intro: framework/angular/index.md
- AngularJS Quick Start: framework/angular/quickstart.md
- AngularJS File Names: framework/angular/files.md
- AngularJS Loader: framework/angular/loader.md
- AngularJS Changesets: framework/angular/changeset.md
- Asset Builder: framework/asset-builder.md
- Authentication: framework/authx.md
- Autocompletes: framework/autocomplete.md
- Bootstrap Process: framework/bootstrap.md
- Backbone Reference: framework/backbone.md
- Bundle Reference: framework/bundle.md
- Cache Reference: framework/cache.md
- CiviMail: framework/civimail.md
- CiviReport: framework/civireport.md
- Codebase: framework/codebase.md
- Cryptography Reference: framework/crypto.md
- Entities:
- CiviCRM Entities: framework/entities/index.md
- Schema Design: framework/entities/schema-design.md
- Migrating from Legacy XML: framework/entities/schema-definition.md
- Database Transaction Reference: framework/transactions.md
- Formatting: framework/formatting.md
- File System: framework/filesystem.md
- Import: framework/import.md
- Logging Reference: framework/logging.md
- Mixins:
- Introduction: framework/mixin/index.md
- New Mixin: framework/mixin/create.md
- Standard Mixins: framework/mixin/standard.md
- OAuth Reference: framework/oauth.md
- Pipe Reference: framework/pipe.md
- Pseudoconstant (Option List) Reference: framework/pseudoconstant.md
- QuickForm Reference:
- QuickForm: framework/quickform/index.md
- Entity Reference Field: framework/quickform/entityref.md
- Queue Reference: framework/queues/index.md
- Region Reference: framework/region.md
- Routing: framework/routing.md
- Resources Reference: framework/resources.md
- Service Container: framework/services.md
- Setting:
- Introduction: framework/setting/index.md
- Usage: framework/setting/usage.md
- Settings Properties: framework/setting/properties.md
- Extension Settings: framework/setting/extension.md
- Core Settings: framework/setting/core.md
- Setup Reference:
- Overview: framework/setup/index.md
- Getting Started: framework/setup/getting-started.md
- New Installer: framework/setup/new-installer.md
- New Plugin: framework/setup/new-plugin.md
- Manage Plugins: framework/setup/plugins.md
- Template Reference:
- Templates: framework/templates/index.md
- Customizing Templates: framework/templates/customizing.md
- Extending Smarty: framework/templates/extending-smarty.md
- Theme Reference: framework/theme.md
- Token Reference: framework/token.md
- UI Reference: framework/ui.md
- Upgrade Reference: framework/upgrade.md
- Workflow Message Reference: framework/message.md
- Translation:
- Translation: translation/index.md
- Extensions Translation: extensions/translation.md
- Database localized fields and upgrades: translation/database.md
- Standards:
- Coding Standards: standards/index.md
- PHP Standards: standards/php.md
- Javascript Standards: standards/javascript.md
- Entity Standards: standards/entity.md
- Review Standards: standards/review.md
- Review Template (DEL): standards/review/template-del-1.0.md
- Review Template (MC): standards/review/template-mc-1.0.md
- Review Template (WORD): standards/review/template-word-1.0.md
- Documentation:
- Writing Documentation: documentation/index.md
- Documenting Extensions: extensions/documentation.md
- Markdown: documentation/markdown.md
- Style Guide: documentation/style-guide.md
- Step by Step Guides:
- Create entity: step-by-step/create-entity.md
- Create a custom Case token: step-by-step/create-custom-case-token.md
- Create Cached Configuration Container: step-by-step/create-cached-config-container.md
dev-tools/debugging tools/debugging
extend-stages extensions/lifecycle
markdownrules documentation/markdown
best-practices/documentation-style-guide documentation/style-guide
extensions/basics extensions
api/general api
hooks/hook_civicrm_trigger_info hooks/hook_civicrm_triggerInfo
testing/setup testing
testing/javascript testing/karma
framework/schema-definition framework/entities/schema-definition
api/params api/v3/options
api/usage api/v3/usage
api/actions api/v3/actions
api/options api/v3/options
api/joins api/v3/joins
api/chaining api/v3/chaining
api/custom-data api/v3/custom-data
api/examples api/v3/examples
api/changes api/v3/changes
testing/selinium testing/selenium
core/develop tools/git
basics/filesystem framework/filesystem
core/architecture framework/codebase
framework/civimail/tokens https://docs.civicrm.org/user/en/latest/common-workflows/tokens-and-mail-merge/
framework/api-architecture api/v4/architecture
documentation/extensions extensions/documentation
translation/extensions extensions/translation
\ No newline at end of file
Documentation+Infrastructure+Canary develop
Book+style+guide best-practices/documentation-style-guide
CiviCRM+Unit+Testing+basic+information testing
Setting+up+your+personal+testing+sandbox+HOWTO testing
Writing+a+PHPUnit+testcase+HOWTO testing
Pull-Request+Process tools/git/#pr
Documentation+Infrastructure+Canary develop
Documentation+Infrastructure+Canary basics/community
The+developer+community basics/community
Create+an+Extension extensions/basics
Create+an+Extension extensions
Publish+an+Extension extensions/publish
Before+you+start basics/planning
Recommendations basics/planning
The+codebase core/architecture
Debugging+for+developers dev-tools/debugging
The+developer+community extensions/civix
The+codebase framework/filesystem
Debugging+for+developers tools/debugging
Create+a+Module+Extension extensions/civix
hook_civicrm_copy hooks/hook_civicrm_copy
hook_civicrm_custom hooks/hook_civicrm_custom
hook_civicrm_managed hooks/hook_civicrm_managed
hook_civicrm_merge hooks/hook_civicrm_merge
hook_civicrm_alterLocationMergeData hooks/hook_civicrm_alterLocationMergeData
hook_civicrm_post hooks/hook_civicrm_post
hook_civicrm_pre hooks/hook_civicrm_pre
hook_civicrm_trigger_info hooks/hook_civicrm_triggerInfo
hook_civicrm_referenceCounts hooks/hook_civicrm_referenceCounts
hook_civicrm_postSave_table_name hooks/hook_civicrm_postSave_table_name
hook_civicrm_disable hooks/hook_civicrm_disable
hook_civicrm_enable hooks/hook_civicrm_enable
hook_civicrm_install hooks/hook_civicrm_install
hook_civicrm_uninstall hooks/hook_civicrm_uninstall
hook_civicrm_upgrade hooks/hook_civicrm_upgrade
hook_civicrm_postInstall hooks/hook_civicrm_postInstall
hook_civicrm_alterContent hooks/hook_civicrm_alterContent
hook_civicrm_buildForm hooks/hook_civicrm_buildForm
hook_civicrm_postProcess hooks/hook_civicrm_postProcess
hook_civicrm_validateForm hooks/hook_civicrm_validateForm
hook_civicrm_alterTemplateFile hooks/hook_civicrm_alterTemplateFile
hook_civicrm_preProcess hooks/hook_civicrm_preProcess
hook_civicrm_idsException hooks/hook_civicrm_idsException
hook_civicrm_buildAmount hooks/hook_civicrm_buildAmount
hook_civicrm_caseSummary hooks/hook_civicrm_caseSummary
hook_civicrm_customFieldOptions hooks/hook_civicrm_customFieldOptions
hook_civicrm_dashboard hooks/hook_civicrm_dashboard
hook_civicrm_links hooks/hook_civicrm_links
hook_civicrm_navigationMenu hooks/hook_civicrm_navigationMenu
hook_civicrm_pageRun hooks/hook_civicrm_pageRun
hook_civicrm_searchColumns hooks/hook_civicrm_searchColumns
hook_civicrm_searchTasks hooks/hook_civicrm_searchTasks
hook_civicrm_summary hooks/hook_civicrm_summary
hook_civicrm_summaryActions hooks/hook_civicrm_summaryActions
hook_civicrm_tabs hooks/hook_civicrm_tabs
hook_civicrm_xmlMenu hooks/hook_civicrm_xmlMenu
hook_civicrm_tabset hooks/hook_civicrm_tabset
hook_civicrm_dashboard_defaults hooks/hook_civicrm_dashboard_defaults
hook_civicrm_contact_get_displayname hooks/hook_civicrm_contact_get_displayname
hook_civicrm_fieldOptions hooks/hook_civicrm_fieldOptions
hook_civicrm_alterMenu hooks/hook_civicrm_alterMenu
hook_civicrm_alterMailParams hooks/hook_civicrm_alterMailParams
hook_civicrm_emailProcessor hooks/hook_civicrm_emailProcessor
hook_civicrm_emailProcessorContact hooks/hook_civicrm_emailProcessorContact
hook_civicrm_mailingGroups hooks/hook_civicrm_mailingGroups
hook_civicrm_postEmailSend hooks/hook_civicrm_postEmailSend
hook_civicrm_alterMailer hooks/hook_civicrm_alterMailer
hook_civicrm_unsubscribeGroups hooks/hook_civicrm_unsubscribeGroups
hook_civicrm_alterMailContent hooks/hook_civicrm_alterMailContent
hook_civicrm_postMailing hooks/hook_civicrm_postMailing
hook_civicrm_aclGroup hooks/hook_civicrm_aclGroup
hook_civicrm_aclWhereClause hooks/hook_civicrm_aclWhereClause
hook_civicrm_alterAPIPermissions hooks/hook_civicrm_alterAPIPermissions
hook_civicrm_permission_check hooks/hook_civicrm_permission_check
hook_civicrm_permission hooks/hook_civicrm_permission
hook_civicrm_selectWhereClause hooks/hook_civicrm_selectWhereClause
hook_civicrm_alterCalculatedMembershipStatus hooks/hook_civicrm_alterCalculatedMembershipStatus
hook_civicrm_alterBarcode hooks/hook_civicrm_alterBarcode
hook_civicrm_alterBadge hooks/hook_civicrm_alterBadge
hook_civicrm_alterPaymentProcessorParams hooks/hook_civicrm_alterPaymentProcessorParams
hook_civicrm_alterSettingsFolders hooks/hook_civicrm_alterSettingsFolders
hook_civicrm_alterSettingsMetaData hooks/hook_civicrm_alterSettingsMetaData
hook_civicrm_apiWrappers hooks/hook_civicrm_apiWrappers
hook_civicrm_buildStateProvinceForCountry hooks/hook_civicrm_buildStateProvinceForCountry
hook_civicrm_config hooks/hook_civicrm_config
hook_civicrm_contactListQuery hooks/hook_civicrm_contactListQuery
hook_civicrm_cron hooks/hook_civicrm_cron
hook_civicrm_dupeQuery hooks/hook_civicrm_dupeQuery
hook_civicrm_export hooks/hook_civicrm_export
hook_civicrm_import hooks/hook_civicrm_import
hook_civicrm_membershipTypeValues hooks/hook_civicrm_membershipTypeValues
hook_civicrm_tokens hooks/hook_civicrm_tokens
hook_civicrm_tokenValues hooks/hook_civicrm_tokenValues
hook_civicrm_queryObjects hooks/hook_civicrm_queryObjects
hook_civicrm_check hooks/hook_civicrm_check
hook_civicrm_optionValues hooks/hook_civicrm_optionValues
hook_civicrm_coreResourceList hooks/hook_civicrm_coreResourceList
hook_civicrm_angularModules hooks/hook_civicrm_angularModules
hook_civicrm_container hooks/hook_civicrm_container
hook_civicrm_crudLink hooks/hook_civicrm_crudLink
hook_civicrm_fileSearches hooks/hook_civicrm_fileSearches
hook_civicrm_notePrivacy hooks/hook_civicrm_notePrivacy
hook_civicrm_eventDiscount hooks/hook_civicrm_eventDiscount
hook_civicrm_recent hooks/hook_civicrm_recent
hook_civicrm_unhandledException hooks/hook_civicrm_unhandledException
hook_civicrm_alterMailingLabelParams hooks/hook_civicrm_alterMailingLabelParams
hook_civicrm_geocoderFormat hooks/hook_civicrm_geocoderFormat
hook_civicrm_alterLogTables hooks/hook_civicrm_alterLogTables
hook_civicrm_caseChange hooks/hook_civicrm_caseChange
hook_civicrm_caseTypes hooks/hook_civicrm_caseTypes
hook_civicrm_post_case_merge hooks/hook_civicrm_post_case_merge
hook_civicrm_pre_case_merge hooks/hook_civicrm_pre_case_merge
hook_civicrm_batchItems hooks/hook_civicrm_batchItems
hook_civicrm_batchQuery hooks/hook_civicrm_batchQuery
hook_civicrm_entityTypes hooks/hook_civicrm_entityTypes
hook_civicrm_buildProfile hooks/hook_civicrm_buildProfile
hook_civicrm_buildUFGroupsForModule hooks/hook_civicrm_buildUFGroupsForModule
hook_civicrm_processProfile hooks/hook_civicrm_processProfile
hook_civicrm_searchProfile hooks/hook_civicrm_searchProfile
hook_civicrm_validateProfile hooks/hook_civicrm_validateProfile
hook_civicrm_viewProfile hooks/hook_civicrm_viewProfile
hook_civicrm_alterReportVar hooks/hook_civicrm_alterReportVar
Hook+Reference hooks
Hooks hooks
Extension+Review extensions/lifecycle/#formal-review
Call+the+CiviCRM+API+from+a+custom+template api/v3/usage/#smarty
Using+the+API api
Hook+examples hooks
Database+hooks hooks
Extension+lifecycle+hooks hooks
Form+hooks hooks
GUI+hooks hooks
Mail+hooks hooks
Permission+hooks hooks
Uncategorized+hooks hooks
Case+hooks hooks
Batch+hooks hooks
Entity+Hooks hooks
CiviRules+hooks hooks
Profile+Hooks hooks
Report+Hooks hooks
Tests+in+phpstorm tools/phpstorm/#testing
Testing testing
PHP+Code+and+Inline+Documentation standards/php
Upgrade+Reference framework/upgrade
Bootstrap+Reference framework/bootstrap
API+Architecture+Standards framework/api-architecture
How+to+migrate+or+write+an+api framework/api-architecture
Javascript+Reference standards/javascript
Resource+Reference framework/resources
API+Examples api/v3/examples
REST+interface api/interfaces#rest-interface
AJAX+Interface api/interfaces#ajax-interface
Smarty+API+interface api/interfaces#smarty-api-interface
Cache+Reference framework/cache
Extension+Reference extensions/info-xml
Settings+Reference framework/setting
Region+Reference framework/region
HTML+Header+Region framework/region#header
Chaining api/v3/chaining
Add-on+Formats extensions/packaging
IDE+Settings+to+Meet+Coding+Standards tools/phpstorm
API+changes api/v3/changes
Ajax+Pages+and+Forms framework/ajax
Coding+Standards standards
QuickForm+Reference framework/quickform
EntityRef+Fields framework/quickform/entityref
Pseudoconstant+option+list+Reference framework/pseudoconstant
API+Security api/v3/usage/#api-security
UI+Elements+Reference framework/ui
Accordions framework/ui
Buttons framework/ui
crmDatepicker framework/ui
Icons framework/ui
In-Place+Field+Editing framework/ui
Notifications+and+Confirmations framework/ui
Section+elements framework/ui
Database+layer standards/database
Using+Custom+Data+with+the+API api/v3/custom-data
CiviReport+Reference framework/civireport
Manual+testing testing/manual
Dedupe+and+merge+testing testing/manual/#dedupe
Smart+group+testing testing/manual/#smart-group
Tarball+installation+testing testing/manual/#tarball
Contributing+to+CiviCRM+using+GitHub tools/git/#github
Git+Commit+Messages+for+CiviCRM tools/git/#committing
Transaction+Reference framework/entities/transactions
Backbone+Reference framework/backbone
Extensions+and+Permissions security/permissions#extensions
Customize+Built-in+Profile+Contribution+and+Event+Registration+Screens framework/templates/customizing
Page+Templates framework/templates
Extending+Smarty framework/templates/extending-smarty
What+is+a+Payment+Processor extensions/payment-processors
Create+a+Payment-Processor+Extension extensions/payment-processors/create
Testing+Processor+Plugins extensions/payment-processors/create/#testing
Example+of+creating+a+payment+processor+extension extensions/payment-processors/create
CiviMail+Reference framework/civimail
Token+Reference framework/civimail#tokens
Verify+a+bug+fix core/verify-fix
Overview index.html
Developer+Setup index.html
Techniques index.html
Customize+Built-in+Screens index.html
Custom+Error+Screens+and+Error+Handlers index.html
Reference+Sheets index.html
API+Reference api
Database+Reference framework/database
Permission+Reference security/permissions
Develop index.html
Customized+and+Custom+Tokens framework/civimail#extending-the-token-system
Tokens framework/civimail/tokens
Internationalisation+for+Developers translation