Skip to content
Snippets Groups Projects
Commit fc9eb598 authored by vangelis's avatar vangelis
Browse files

Initial Release

parents
No related branches found
No related tags found
No related merge requests found
APIv3
=====
CiviCRM has a stable comprehensive **API** (Application Programming
Interface) that can be used to access and manage data in CiviCRM. The
API is the recommended way for any CiviCRM extension, CMS module, or
external program to interact with CiviCRM. This section of the wiki
gives you an introduction to the basics of the API. This page's children
dive into the depths of the API.
Why use the API?
----------------
If you're not familiar with APIs, you might ask why you would use the
API when you could access the core functions (e.g. the BAO files) or the
data in the MySQL database directly?
The answer is that the community will ensure that the API will function
as expected with every new release. Great effort is made to preserve
backwards compatibility of the API for several versions of CiviCRM. If
you decide to use other ways to collect data (like your own MySQL
statements), you are left to your own devices. Changes in the schema and
BAO arguments, etc. will cause you grief.
A few comments before we start
------------------------------
The API is something that we as a community develop and maintain
together. A pretty awesome achievement so a big round of applause for
everyone who contributes! It also means that:
- the API is continuously developed and improved. Once you have
mastered the basics from this introduction it is a good idea to
delve deeper into the wiki and the forums for the latest and
greatest
- there is always a chance you run into a bug, if you do please report
it on the forum or go to the CiviCRM IRC channel if it is a real
urgency. Obviously it will be greatly appreciated if you fix it,
send it as a patch with a unit test
- This introduction is updated by the community too. If you do happen
to find some mistake, please log in and change
Exploring the API and documentation
-----------------------------------
The best place to learn about the API is your own ***test*** install of
CiviCRM, using the API explorer and the API parameter list.
Each install comes with two tools that will help you to explore the
wonders of the API and learn a little more about each one:
1. The**API parameter list**, which shows all available entities which
can be manipulated by the API and is available
at http://[CIVICRM\_URL]/civicrm/api/doc (or
http://[CIVICRM\_URL]/?q=civicrm/api/doc if you do not use clean
URLs in Drupal). You will first get a list of all the API entities.
If you click on an entity you will get a list of parameters that are
available for that specific entity, with the type of the parameter.
This can be very useful if you want to check what you can retrieve
with the API and what parameters you can use to refine your get
action or complete your create or update action.
2. The **API explorer**, which is available
at http://[CIVICRM\_URL]/civicrm/api/explorer (or
http://[CIVICRM\_URL]/?q=civicrm/api/explorer if you do not use
clean URLs in Drupal). This gives you the possibility to actually
try out the API in action. You can select the entity you want to
use, for example ' Contact' and the action you want to perform, for
example ' Get' . Again, be careful as the API explorer will actually
perform your actions! So if you delete a contact to check what API
call to use, it will really delete the contact. The API explorer
will show you the code you need to have to execute the API call you
have been testing. To see an example of the API explorer in action
check
[http://civicrm.org/API\_version\_3](http://civicrm.org/API_version_3).
It may be that it uses an older version of the API explorer, but you
will get the idea!
Public API
Explorer: [http://drupal.sandbox.civicrm.org/civicrm/api/explorer](http://drupal.sandbox.civicrm.org/civicrm/api/explorer) (login
as demo/demo)
On top of these tools, your CiviCRM installation will also contain a
directory full of examples on how the API can be used. These examples
will be inside the api/v3 directory and is called 'examples'. You can
also find the examples on GitHub:
[https://github.com/civicrm/civicrm-core/tree/master/api/v3/examples](https://github.com/civicrm/civicrm-core/tree/master/api/v3/examples)
There is also the code-level documentation which can be found at
[http://api.civicrm.org/v3/](http://api.civicrm.org/v3/)
Also, the [API Reference](/confluence/display/CRMDOC/API+Reference) page
on this wiki.
Changelog
---------
Any API change you should be aware of will be recorded on this wiki
documentation at [API changes](/confluence/display/CRMDOC/API+changes)
Examples
========
Online Examples
---------------
All the API examples included with CiviCRM core are auto-generated so
the validity of the code is certain.
|Version|URL|
|:-----------|-------------|
|Upcoming Version|[https://github.com/civicrm/civicrm-core/tree/master/api/v3/examples](https://github.com/civicrm/civicrm-core/tree/master/api/v3/examples)|
|CiviCRM 4.5|[https://github.com/civicrm/civicrm-core/tree/4.5/api/v3/examples](https://github.com/civicrm/civicrm-core/tree/4.5/api/v3/examples)|
|CiviCRM 4.2 LTS|[https://github.com/CiviCRM42/civicrm42-core/tree/4.2/api/v3/examples](https://github.com/CiviCRM42/civicrm42-core/tree/4.2/api/v3/examples)|
Local Examples
--------------
CiviCRM ships with API examples included in the distribution. You can
find the examples specific to your installed version at:
<civicrm\_root\>/api/v3/examples
For example, if you have CiviCRM installed with Drupal the location to
the examples would be:
[/path/to/your/drupalroot/sites/all/modules/civicrm/api/v3/examples](http://path/to/your/drupalroot/sites/all/modules/civicrm/api/v3/examples)
Bindings
========
There are at least 5 different ways of using an API function. In each
environment, the API uses the same names for entities, actions, and
parameters, but the syntax is slightly different. Entities are the data
collections you want to operate on, for example Contact, Event or Group.
The actions are the thing you want to do to the entity, for example get,
create, delete or update.
You can use the API:
1. as a PHP function, to run your own code on the same server as
CiviCRM
2. via the AJAX interface, to be called from JavaScript code
3. via the REST\* interface, can be called from another server via
http/https calls
4. as a Smarty function to add data to templates
5. from drush on the command line for Drupal installations.
. The following examples show how to search for contacts named "Alice
Roberts".
PHP (procedural) from CiviCRM 4.2 onwards
-----------------------------------------
The PHP procedural API is the canonical API – every other API builds on
top of it. It can be used when writing core code, native extensions
(modules), or CMS extensions (modules). The first example is the
recommended way of calling the API in PHP, which has been backported
into CiviCRM version 4.2 (LTS).
If you forget to include the API call in a try/catch block, an error in the API call will result in a fatal CiviCRM error
```
try{
$contacts = civicrm_api3('contact', 'get', array(
'first_name' => 'Alice',
'last_name' => 'Roberts'
));
}
catch (CiviCRM_API3_Exception $e) {
$error = $e->getMessage();
}
printf("Found %d item(s)\n", $contacts['count']);
```
Further examples are in the api/v3/examples folder in your install or on
[GitHub](https://github.com/civicrm/civicrm-core/tree/master/api/v3/examples).
Note that the examples are all generated by the test suite. If there is
something missing from the examples post on the API forum board and help
us add it to the test suite. This may be a function or a field within
that function.
Before calling the PHP procedural API, one must ***bootstrap*** CiviCRM. If you're writing code for CiviCRM Core or for a native CiviCRM extension, then the bootstrap is handled automatically. If you're writing code for a Drupal module, a Joomla extension, or a standalone script, then see the examples in [Bootstrap Reference](/confluence/display/CRMDOC/Bootstrap+Reference).
PHP (procedural) up to CiviCRM 4.2
----------------------------------
In the CiviCRM versions before 4.2, you have to include the version
parameter in the parameter array of your API call. In your code you need
to check if the call has been succesfull by testing the 'is\_error'
result element:
````
$apiParams = array(
'version' => 3,
'first_name' => 'Alice',
'last_name' => 'Roberts'
);
$apiResult = civicrm_api('Contact', 'Get', $apiParams);
if (!civicrm_error($apiResult)) {
//rest of your code
}
/*
* or alternatively
*/
if (!isset($apiResult['is_error']) || $apiResult['is_error'] == 0) {
// rest of your code
}
````
PHP (object oriented) since CiviCRM 3.4
---------------------------------------
In CiviCRM version 3.4 an API class was introduced, allowing you to call
the CiviCRM API in an Object Oriented way. The class is called
*class.api.php* and can be found in the api directory. It allows you to
call the API like this:
````
require_once 'your/civicrm/folder/api/class.api.php';
$api = new civicrm_api3();
$apiParams = array(
'first_name' => 'Alice',
'last_name' => 'Roberts'
);
if ($api->Contact->Get($apiParams)) {
//each key of the result array is an attribute of the api
echo "\n contacts found ".$api->count;
'contact_type'=>'Individual','return'=>'sort_name,current_employer')) {
} else {
echo $api->errorMsg();
}
````
If you call the API in the object oriented fashion, you do not have to
specify 'version' as a parameter
REST
----
````javascript
// For external services
http://www.example.com/sites/all/modules/civicrm/extern/rest.php
?api_key=t0ps3cr3t
&key=an07h3rs3cr3t
&json=1
&debug=1
&version=3
&entity=Contact
&action=get
&first_name=Alice
&last_name=Roberts
// For sessions already authenticated by the CMS (e.g. AJAX)
http://www.example.com/civicrm/ajax/rest
?json=1
&debug=1
&version=3
&entity=Contact
&action=get
&first_name=Alice
&last_name=Roberts
````
Obviously you should substitute your site in! You can explore the syntax
and options available using the [api
explorer](http://sandbox.civicrm.org/civicrm/ajax/doc#explorer) (also on
your site!)
Please note that the REST interface is subject to [API Security](/confluence/display/CRMDOC/API+Security).
For more details, see [REST
interface](http://wiki.civicrm.org/confluence/display/CRMDOC/REST+interface).
AJAX
----
````
CRM.api3('entity', 'action', [params], [statusMessage]);
````
For more details, see [AJAX
Interface](/confluence/display/CRMDOC/AJAX+Interface).
The AJAX interface is automatically available for web-pages generated through CiviCRM (such as ***standard CiviCRM web-page****s***, CiviCRM ***extensions***, and custom CiviCRM ***templates***).
The AJAX interface could be made available to other parts of the same website (e.g. a drupal module or wordpress widget) by calling CRM\_Core\_Resources::singleton()-\>addCoreResources() from php. Please note that the AJAX interface is subject to [API Security](/confluence/display/CRMDOC/API+Security) and [Same Origin Policy](http://en.wikipedia.org/wiki/Same_origin_policy). To use it from an external site or application, see REST interface documentation.
Smarty
------
````
{crmAPI var="myContactList" entity="Contact" action="get" version="3" first_name="Alice" last_name="Roberts" }
Found {$myContactList.count} item(s).
````
The smarty call is to add extra information, therefore *create* or
*delete* actions don't make sense in this case.
For more details, see [Smarty API
interface](/confluence/display/CRMDOC/Smarty+API+interface).
Drush
-----
````
## To run on the default Drupal site
drush civicrm-api contact.get first_name=Alice last_name=Roberts
## To run on Drupal multisite, specify the site name
drush -l www.example.com civicrm-api contact.get first_name=Alice last_name=Roberts
````
Request Format
==============
Every API call consists of three elements:
- **Entity name**: a string such as "Contact" or "Activity"
- **Action name**: a string such as "create" or "delete"
- **Parameters**: an associative-array (such as the first-name and
last-name of a new contact record); this varies depending on the
entity name
Entities
========
There are many entities supported by the CiviCRM API, and the list
expands in every release. For current details in your version, see the
"Documentation" section; in particular, see the "API Explorer" and the
API examples.
For demonstration, consider a few commonly-used entities:
| Entity | Description | Example Parameters |
|--------------------------|--------------------------|--------------------------|
| Contact | An individual, <br /> organization, or <br />house-hold. | “contact\_type”,<br /> “first\_name”, <br />“last\_name”, <br />“preferred\_language” |
| Activity | An phone call, meeting,<br /> or email message. that <br /> has occurred (or will <br /> occur) at a specific <br /> date and time| “activity\_type\_id”, <br /> “source\_contact\_id”, <br /> “assignee\_contact\_id” |
| Address | A street-address related <br /> to a contact. | “contact\_id”, <br /> “street\_address”, <br /> “city”, <br /> “state\_province\_id”, <br /> "country\_id’ |
Actions
=======
Most entities support the following actions:
create
------
Insert or update one record. (Note: If an *"id*" is specified, then an
existing record will be modified.)
delete
------
Delete one record. (Note: Requires an explicit "*id*". Note: if you
want to skip the 'recycle bin' for entities that support undelete (e.g.
contacts) you should set \$param['skip\_undelete'] =\> 1);
get
---
Search for records
getsingle
---------
Search for records and return the first or only match. (Note: This
returns the record in a simplified format which is easy to use)
getvalue
--------
Does a **getsingle** & returns a single value - you need to also set
````
$param['return'] => 'fieldname'
````
getcount
--------
Search for records and return the quantity. (Note: In many cases in
early versions queries are limited to 25 so this may not always be
accurate)
getrefcount
-----------
Counts the number of references to a record
getfields
---------
Fetch entity metadata, i.e. the list of fields supported by the entity
getlist
-------
Used for autocomplete lookups by the
[entityRef](/confluence/display/CRMDOC/EntityRef+Fields) widget
getoptions
----------
Returns the options for a specified field e.g.
````
civicrm_api3(
'contact',
'getoptions',
array('field' => 'gender_id')
);
````
returns
````
array(
1 => 'Female',
2 => 'Male',
3 => 'Transgender'
)
````
replace
-------
Replace an old set of records with a new or modified set of records.
(For example, replace the set of "Phone" numbers with a different set of
"Phone" numbers.).
Warning - REPLACE includes an implicit delete - use with care & test well before using in productions
<del>setvalue</del>
-------------------
**Deprecated.** Use the create action with the param 'id' instead.
<del>update</del>
-----------------
**Deprecated.** Use the create action with the param 'id' instead.
Parameters
==========
There are many parameters accepted by the CiviCRM API. Most parameters
depend on the entity – for current details in your version, see the
"Documentation" section; in particular, see the "API Explorer" and the
API examples. However, some parameters are particularly dynamic or
generic; these may not be explained well by the auto-generated
documentation. The format for passing options as parameters using the
REST interface is explained at [REST
interface\#optionsparameters](/confluence/display/CRMDOC/REST+interface#RESTinterface-optionsparameters).
**sequential**
--------------
* **Action**: get
* **Type**: bool
* **Default**: FALSE
* **Compatibility**: ??
* **Description**:
Determine whether the returned records are indexed sequentially (0, 1, 2, ...) or by ID.
Without sequential
````
$result= civicrm_api('UFMatch','Get', array('version' =>3, 'uf_id' => $user->uid);
$contactid=$contact['values'][$result['id']]['contact_id'] );
````
With sequential
````
$result= civicrm_api('UFMatch','Get', array('version' =>3, 'uf_id' => $user->uid, 'sequential' => 1);
$contactid=$result['values'][0]['contact_id'] );
````
Note that a single record is returned in this example - whenever a single record is returned the entity_id of that record should be in $result['id']
### Example: sequential
````
civicrm_api('UFMatch','Get', array(
'version' => 3,
'uf_id' => $user->uid,
'sequential' => 1,
));
````
**options.limit**
-----------------
* **Action**: get
* **Type**: int
* **Default**: 25
* **Compatibility**: ??
* **Description**:
The maximum number of records to return
### Example: options.limit
````
civicrm_api('UFMatch','Get', array(
'version' => 3,
'uf_id' => $user->uid,
'options' => array(
'limit' => 25,
),
));
````
**options.offset**
------------------
* **Action**: get
* **Type**: int
* **Default**: 0
* **Description**:
The numerical offset of the first result record
### Example: options.offset
````
civicrm_api('UFMatch','Get', array(
'version' => 3,
'uf_id' => $user->uid,
'options' => array(
'limit' => 25,
'offset' => 50,
),
));
````
**options.sort**
----------------
* **Action**: get
* **Type**: ??
* **Default**: ??
* **Parameters**: field name, order (ASC / DESC)
* **Description**:
The criterion to sort on
### Example: options.sort
````
civicrm_api3('Contact', 'get', array(
'sequential' => 1,
'return' => "contact_type",
'options' => array('sort' => "contact_type ASC"),
));
````
**options.reload**
------------------
* **Action**: create
* **Type**: bool
* **Default**: FALSE
* **Compatibility**: v4.4+
* **Description**:
Whether to reload and return the final record after the saving process
completes.
### Example: options.reload
```
civicrm_api('Contact', 'create', array(
'version' => 3,
'contact_type' => 'Individual',
'first_name' => 'First',
'last_name' => 'Last',
'nick_name' => 'Firstie',
'options' => array(
'reload' => 1,
),
));
```
**options.match**
-----------------
* **Action**: create | replace
* **Type**: string | array
* **Default**: NULL
* **Compatibility**: v4.4+
* **Description**:
Attempt to update an existing record by matching against the specified
field.
<br />
If **one** matching record already exists, then the record will be
**updated**.
<br />
If **no** matching record exists, then a new one will be **inserted**.
<br />
If **multiple** matching records exist, then return an **error**.
### Example: options.match
```
civicrm_api('contact', 'create', array(
'version' => 3,
'contact_type' => 'Individual',
'first_name' => 'Jeffrey',
'last_name' => 'Lebowski',
'nick_name' => 'The Dude',
'external_identifier' => '1234',
'options' => array(
'match' => 'external_identifier',
),
));
```
**options.match-mandatory**
---------------------------
* **Action**: create | replace
* **Type**: string | array
* **Default**: NULL
* **Compatibility**: v4.4+
* **Description**:
Attempt to update an existing record by matching against the specified
field.
<br />
If **one** matching record already exists, then the record will be
updated.
<br />
If **no** matching record exists, then return an **error**.
<br />
If **multiple** matching records exist, then return an **error**.
### Example: options.match-mandatory
```
civicrm_api('contact', 'create', array(
'version' => 3,
'contact_type' => 'Individual',
'first_name' => 'Jeffrey',
'last_name' => 'Lebowski',
'nick_name' => 'The Dude',
'external_identifier' => '1234',
'options' => array(
'match-mandatory' => 'external_identifier',
),
));
```
**Custom Data**
---------------
Custom data attached to entities is referenced by custom\_N where N is
the unique numerical ID for the custom data field.
To set a custom field, or find entities with custom fields of a
particular value, you typically use a parameter like this:
```
$param['custom_N'] => 'value';
```
To return custom data for an entity, you typically pass a param like the
following:
```
$param['return.custom_N'] => 1;
```
*or (depending on which API entity you are querying)*
```
$param['return'] => 'custom_N';
```
*or*
```
$param['return'] => 'custom_N,custom_O,custom_P';
```
For setting custom date fields, (ie CustomValue create), date format is YmdHis, for example: 20050425000000.
This is just a brief introduction; each API may have different requirements and allow different formats for accessing the custom data. See the [API function documentation](/confluence/display/CRMDOC/Using+the+API) and also read the comments and documentation in each API php file (under civicrm/CRM/api/v3 in your CiviCRM installation) for exact details, which vary for each API entity and function.
For more details and examples, [see the tutorial on using custom data with the API here](/confluence/display/CRMDOC/Using+Custom+Data+with+the+API).
Response Format
===============
The response from an API call is always an associative-array. The
response format can vary depending on the action, but generally
responses meet one of these two structures:
Success
-------
````
$result['is_error'] = 0
$result['version'] = 2 or 3 as appropriate
$result['count'] = number of records in the 'values' element of the $result array
$result['values'] = an array of records
````
Please note that the **getsingle** response will not have a $result['values'] holding the records, but a $result array with the fields from the selected record. The response $result will only have an 'is\_error' attribute if there actually is an error.
Error
-----
````
$result['is_error'] = 1
$result['error_message'] = An error message as a string.
````
Chaining
========
It is now possible to do two api calls at once with the first call feeding into the second. E.g. to create a contact with a contribution you can nest the contribution create into the contact create. Once the contact has been created it will action the contribution create using the id from the contact create as 'contact\_id'. Likewise you can ask for all activities or all contributions to be returned when you do a get. Some examples will explain
* [https://github.com/civicrm/civicrm-core/blob/master/api/v3/examples/ContactCreate.php](https://github.com/civicrm/civicrm-core/blob/master/api/v3/examples/ContactCreate.php)
* [https://github.com/civicrm/civicrm-core/blob/master/api/v3/examples/ContactGet.php](https://github.com/civicrm/civicrm-core/blob/master/api/v3/examples/ContactGet.php)
* [https://github.com/civicrm/civicrm-core/blob/master/api/v3/examples/Contact/APIChainedArray.php](https://github.com/civicrm/civicrm-core/blob/master/api/v3/examples/Contact/APIChainedArray.php)
* [https://github.com/civicrm/civicrm-core/blob/master/api/v3/examples/Contact/APIChainedArrayFormats.php](https://github.com/civicrm/civicrm-core/blob/master/api/v3/examples/Contact/APIChainedArrayFormats.php)
* [https://github.com/civicrm/civicrm-core/blob/master/api/v3/examples/Contact/APIChainedArrayValuesFromSiblingFunction.php](https://github.com/civicrm/civicrm-core/blob/master/api/v3/examples/Contact/APIChainedArrayValuesFromSiblingFunction.php)
Note that there are a few supported syntaxes
```
civicrm('Contact', 'Create',
array(
'version' => 3,
'contact_type' => 'Individual',
'display_name' => 'BA Baracus',
'api.website.create' => array('url' => 'Ateam.com'));
```
is the same as
````
civicrm('Contact', 'Create', array(
'version' => 3,
'contact_type' => 'Individual',
'display_name' => 'BA Baracus',
'api.website' => array('url' => 'Ateam.com'));
````
If you have 2 websites to create you can pass them as ids after the '.'
or an array
````
civicrm('Contact', 'Create', array(
'version' => 3,
'contact_type' => 'Individual',
'display_name' => 'BA Baracus',
'api.website.create' => array('url' => 'Ateam.com',),
'api.website.create.2' => array('url' => 'warmbeer.com', ));
````
OR
````
civicrm('Contact', 'Create', array(
'version' => 3,
'contact_type' => 'Individual',
'display_name' => 'BA Baracus',
'api.website.create' => array(
array('url' => 'Ateam.com', ),
array('url' => 'warmbeer.com', )));
````
the format you use on the way in will dictate the format on the way out.
Currently this supports any entity & it will convert to 'entity\_id' - ie. a PledgePayment inside a contribution will receive the contribution\_id from the outer call
*Build.md*
TODO:
* Nightlies vs gitify vs civibuild
* gitify
* civibuild (https://github.com/civicrm/civicrm-buildkit/blob/master/doc/civibuild.md)
chapter
\ No newline at end of file
*Customize*
TODO:
* *(Requirements: Don't need full git install)*
* *(When possible, link to User/Admin Guide or other existing docs instead of giving details.)*
* Custom fields, profiles, option groups, etc
* webform_civicrm
* Extensions (download+install; web and CLI).
* (Maybe) CiviRules
* (Maybe) CSS override
* (Maybe) *.extra.tpl
*Develop*
TODO: Assimilate http://wiki.civicrm.org/confluence/display/CRMDOC/GitHub+for+CiviCRM
*Extend*
TODO:
* General overview: Use APIv3 and hooks. Package code in Civi extensions or CMS extensions (w/trade-offs).
* Assimilate: http://wiki.civicrm.org/confluence/display/CRMDOC/Create+an+Extension
* Assimilate: http://wiki.civicrm.org/confluence/display/CRMDOC/Publish+an+Extension
*The hooks*
TODO:
* http://wiki.civicrm.org/confluence/display/CRMDOC/Hooks
* http://wiki.civicrm.org/confluence/display/CRMDOC/Hook+Reference
Hooks are a common way to extend systems. The way they work in CiviCRM is that, at key points in processing - such as saving a change or displaying a page - CiviCRM checks to see whether you've "hooked in" some custom code, and runs any valid code it finds.
For example, let's say you want to send an email message to someone in your organization every time a contact in a particular group is edited. Hooks allow you to do this by defining a function with a specific name and adding it to your organisation's CiviCRM installation. The name of the function indicates the point at which CiviCRM should call it. CiviCRM looks for appropriate function names and calls the functions whenever it performs the indicated operations.
Hooks are a powerful way to extend CiviCRM's functionality, incorporate additional business logic, and even integrate CiviCRM with external systems. Many CiviCRM developers find themselves using them in nearly every customization project.
A good test for whether or not to use a hook is to ask yourself whether what you're trying to do can be expressed with a sentence like this: "I want X to happen every time someone does Y."
How to use hooks
================
How you use hooks depends on whether you're using CiviCRM with Drupal or Joomla!.
Using hooks with Drupal
-----------------------
Check the CiviCRM wiki page for the most up-to-date information on setting up hooks with Drupal:
* [http://tiny.booki.cc/?hooks-in-drupal](http://tiny.booki.cc/?hooks-in-drupal)
* [http://wiki.civicrm.org/confluence/display/CRMDOC/CiviCRM+hook+specification\#CiviCRMhookspecification-Proceduresforimplementinghooks%28forDrupal%29](http://wiki.civicrm.org/confluence/display/CRMDOC/CiviCRM+hook+specification#CiviCRMhookspecification-Proceduresforimplementinghooks%28forDrupal%29)
In order to start using hooks with a Drupal-based CiviCRM installation, you or your administrator needs to do the following:
1. Create a file with the extension .info (for instance, myhooks.info) containing the following lines. Replace the example text in the first 2 lines with something appropriate for your organization, and assign 7.x to core if you use Drupal 7.
```
name = My Organization's Hooks
description = Module containing the CiviCRM hooks for my organization
dependencies[] = civicrm
package = CiviCRM
core = 7.x
version = 7.x-1.0
```
2. Create a new file with the extension *.module* (for instance, *myhooks.module*) to hold your PHP functions.
3. Upload both the *.info* and *.module* files to the server running CiviCRM, creating a new directory for them under
*/sites/all/modules* (for instance, */sites/all/modules/myhooks/*) inside your Drupal installation. The directory name you create should be short and contain only lowercase letters, digits, and underlines without spaces.
4. Enable your new hooks module through the Drupal administration page.
NOTE that if you use certain Drupal functions from within CiviCRM, you could break whatever form you're working with! To prevent very hard-to-troubleshoot errors, do the following (at least for user\_save() with Drupal 6, possibly others):
````
$config = CRM_Core_Config::singleton();
````
````
$config->inCiviCRM = TRUE;
````
````
$user = user_save('',array(..));
````
````
$config->inCiviCRM = FALSE;
````
Using hooks with Joomla!
------------------------
Hooks may be implemented in Joomla in two ways, depending on the version of CiviCRM and Joomla you are using. For sites running Joomla 1.5 with CiviCRM up to and including version 3.4, you implement hooks with a single civicrmHooks.php in your php override directory. Sites running Joomla 1.6+ and CiviCRM 4+ may implement with either that single hooks
file, or by creating a Joomla plugin. In general, implementing through a plugin is preferred as you can benefit from the native access control within the plugin structure, include code that responds to other Joomla events, organize your hook implementations into multiple plugins which may be enabled/disabled as desired, and roughly follow the event-observer pattern intended by Joomla plugins.
As you implement hooks in Joomla, be sure to check the CiviCRM wiki for the most up-to-date information:
* [http://tiny.booki.cc/?hooks-in-joomla](http://tiny.booki.cc/?hooks-in-joomla)
* [http://wiki.civicrm.org/confluence/display/CRMDOC/CiviCRM+hook+specification\#CiviCRMhookspecification-Proceduresforimplementinghooks%28forJoomla%29](http://wiki.civicrm.org/confluence/display/CRMDOC/CiviCRM+hook+specification#CiviCRMhookspecification-Proceduresforimplementinghooks%28forJoomla%29)
To implement hooks with a single file, you will do the following:
1. If you have not done so already, create a new directory on your server to store your PHP override files. In Joomla, that is commonly placed in the media folder, as it will not be impacted by Joomla and CiviCRM upgrades. For example, you might create the following folder: */var/www/media/civicrm/customphp*.
2. If you have not done so already, configure your system to reference the folder you've created as your override directory. Go to: CiviCRM Administer \> Global Settings \> Directories. Change the value of Custom PHP Path Directory to the absolute path for the new directory (e.g., "/var/www/media/civicrm/customphp" if you used that suggestion in the earlier step). The custom override directory may also be used to store modified copies of core files -- thus overriding them. You may want to familiarize yourself with its purpose if you are not yet.
3. Create a file named *civicrmHooks.php* to contain your hook implementations, and upload the file to the directory you just
created.
4. Within that file, your hooks will be implemented by calling the hook function prefaced by "joomla\_". For example, you would call the buildForm hook (used to modify form rendering and functionality) by adding the following function to your hook file:
```
function joomla_civicrm_buildForm( $formName, &$form ) {
//your custom code
}
```
If you are implementing hooks with a Joomla plugin, you will create a standard, installable plugin package. At a minimum, a plugin extension will consist of an xml file (defining the plugin and its parameters), and a php file. Within the php file, define a class that extends the Joomla JPlugin class, and call your hooks but adding the appropriate functions. For example, your plugin file may look like the following:
```
defined('_JEXEC') or die;
jimport('joomla.plugin.plugin');
class plgCiviCRMMyPlugin extends JPlugin {
public function civicrm_tabs(&$tabs, $contactID) {
//your code to alter the contact summary tabs
}
}
```
The first two lines are required -- the first is for security purposes, and ensures the code will exit if it has not been called from within Joomla. The second includes the necessary parent plugin class.
Joomla plugin classes follow standard naming conventions which you should follow. By naming this plugin class "plgCiviCRMMyPlugin," I am stating that the plugin resides in the plugin/civicrm/ folder, and the plugin file is named "myplugin.php."
For more information about implementing hooks through plugins, visit this blog article:
* [http://civicrm.org/blogs/mcsmom/hooks-and-joomla](http://civicrm.org/blogs/mcsmom/hooks-and-joomla).
Note the reference in the comments to a sample plugin which you can download and modify.
Refine what you want to act upon
--------------------------------
When you create a hook, it will be called for all the types of entities. For instance, a civicrm\_post is called after the creation or modification of any object of any type (contact, tag, group, activity, etc.). But usually, you want to launch an action only for a specific type of entity.
So a hook generally starts with a test on the type of entity or type of action. For instance, if you want to act only when a new individual contact is created or modified(does this match the code?), start your civicrm\_post hook with:
```
if ($objectName != "Individual" || $op != "edit") { return; }
```
On the other hand, if you want to run multiple hooks within the same function, you don't want to return from any single hook. Instead, you can nest the entire code for each hook within your test:
```
if ($objectName == "Individual" && $op == "edit") { // Your hook }
```
Pitfalls of hooks
-----------------
Because you have little control over what CiviCRM passes to your hook function, it is very helpful to look inside those objects (especially **\$objectRef**) to make sure you're getting what you expect. A good debugger is indispensable here. See the Developer Tips & Tricks chapter at the end of this section for more information on setting up a debugger for your development environment.
Examples of using hooks
-----------------------
Some example hooks follow. Consult the hooks reference documentation on the CiviCRM wiki to see the full extent of what you can do:
* [http://wiki.civicrm.org/confluence/display/CRMDOC/CiviCRM+hook+specification](http://wiki.civicrm.org/confluence/display/CRMDOC/CiviCRM+hook+specification)
In all of these examples, you'll put the code we provide into your *myhooks.module* file if using Drupal, or the *civicrmHooks.php* file if using Joomla!. Be sure to upload the file after each change to the appropriate location on your server to see the new code take effect.
Additionally, if you are using Drupal and add a new hook to an existing module, you will need to clear the cache for the hook to start operating. One way of doing this is by visiting the page Admin \> Build \> Modules.
Sending an email message when a contact in a particular group is edited
------
In order to have CiviCRM tell you when a contact is edited, define the civicrm\_pre hook. This lets you see the incoming edits as well as the values of the existing record, because you may want to include that information in the email.
If you are using Drupal, create a function named *myhooks***\_civicrm\_pre**. If using Joomla!, create a function named
**joomla\_civicrm\_pre**. We'll assume you're using Drupal for the rest of the example, so please adjust the code accordingly if you're using Joomla! instead.
````
<?php function myhooks_civicrm_pre( $op, $objectName, $objectId, &$objectRef ) {
# configuration stuff
$theGroupId = 1;
# group id we want the contacts to be in
$emailRecipient = 'johndoe@example.org';
# person to e-mail
# Make sure we just saved an Individual contact and that it was edited
if ($objectName == "Individual" && $op == "edit") {
# Now see if it's in the particular group we're interested in
require_once 'api/v2/GroupContact.php';
$params = array('contact_id' => $objectId);
$groups = civicrm_group_contact_get( $params );
$found = false;
foreach ($groups as $group) {
if ($group['group_id'] == $theGroupId) {
$found = true;
}
}
# Exit now if contact wasn't in the group we wanted
if (! $found) {
return;
}
# We found the contact in the group we wanted, send the e-mail
$emailSubject = "Contact was edited";
$emailBody = "Someone edited contactId $objectId\n";
# Here's where you may want to iterate over the fields
# and compare them so you can report on what has changed.
mail( $emailRecipient, $emailSubject, $emailBody );
}
}
````
Validating a new contribution against custom business rules
------
If you have experience with other hook-based systems, you might think that the civicrm\_pre hook is the one to use for validations. But this is not the case in CiviCRM because, even though the civicrm\_pre hook is called before the record is saved to the database, you cannot abort the action from this hook.
This is where validation hooks come in. When you return true from a validation hook, CiviCRM saves the new or updated record. When you return an error object instead, CiviCRM aborts the operation and reports your error to the user.
An example follows of using a validation hook to validate new contributions against a business rule that says campaign contributions must have a source associated with them. In this example, we'll assume you are using Joomla!, so if you are using Drupal instead, be sure to change the function name accordingly.
````
<?php function joomla_civicrm_validate( $formName, &$fields, &$files, &$form ) {
# configuration stuff
$campaignContributionTypeId = 3;
# adjust for your site if different
$errors = array();
# $formName will be set to the class name of the form that was posted
if ($formName == 'CRM_Contribute_Form_Contribution') {
require_once 'CRM/Utils/Array.php';
$contributionTypeId = CRM_Utils_Array::value( 'contribution_type_id', $fields );
if ($contributionTypeId == $campaignContributionTypeId) {
# see if the source field is blank or not
$source = CRM_Utils_Array::value( 'source', $fields );
if (strlen( $source ) > 0) {
# tell CiviCRM to proceed with saving the contribution
return true;
} else {
# source is blank, bzzzzzzzzzzzt!
# assign the error to a key corresponding to the field name
$errors['source'] = "Source must contain the campaign identifier for campaign contributions";
return $errors;
}
} else {
# not a campaign contribution, let it through
return true;
}
}
}
````
Automatically filling custom field values based on custom business logic
--------
This example uses a hook to write some data back to CiviCRM. You can make a custom field read-only and then set its value from a hook. This is very handy for storing and displaying data that are derived from other attributes of a record based on custom business logic.
For example, let's say you are storing employee records and you want to auto-generate their network login account when new employees are added. By doing it in your code, you can enforce a policy for login account names. For this example, let's say the policy is first initial + last name. So if your name is Jack Frost, your network login name would be jfrost.
Add a new read-only custom field to CiviCRM called "Network Login" and then find its ID. You can find it either by:
- Checking the civicrm\_custom\_field table in your CiviCRM database.
- Editing a contact and check the name of the Network Login field.
The code must refer to the ID as **custom**\_*id*. So if you find that
the id of the new field is 74, refer to is as **custom\_74** in your
code.
Now that we have our Network Login field, let's see how to populate it automatically with a hook. We'll switch back to the Drupal naming convention for this example.
Note that we use the civicrm\_post hook here because we need the new contact record's ID in order to save a value to one of its custom fields. New records don't have an ID until they have been saved in the database, so if we ran this code in the civicrm\_pre hook, it would fail.
```
<?php function myhooks_civicrm_post( $op, $objectName, $objectId, &$objectRef ) {
# configuration stuff
$customId = 74;
if ($objectName == 'Individual' && $op == 'create') {
# generate the login
$firstName = $objectRef->first_name;
$lastName = $objectRef->last_name;
$firstInitial = substr( $firstName, 0, 1 );
$networkLogin = strtolower( $firstInitial . $lastName );
# assign to the custom field
$customParams = array("entityID" => $objectId,
"custom_$customId" => $networkLogin);
require_once 'CRM/Core/BAO/CustomValueTable.php';
CRM_Core_BAO_CustomValueTable::setValues( $customParams );
}
}
```
Custom mail merge token
-----------
The CiviMail component lets you customise a bulk email message using mail merge tokens. For instance, you can begin your message with, "Hi, {recipient.first\_name}!" and when John Doe receives it, he'll see, "Hi, John!" whereas when Suzy Queue receives it, she'll see, "Hi, Suzy!" You can find out more details about working with custom tokens on the CiviCRM wiki:
* [http://wiki.civicrm.org/confluence/display/CRMDOC/Mail-merge+Tokens+for+Contact+Data](http://wiki.civicrm.org/confluence/display/CRMDOC/Mail-merge+Tokens+for+Contact+Data).
Besides the built-in tokens, you can use a hook to create new custom tokens. Let's make a new one that will show the largest contribution each recipient has given in the past. We'll use Drupal syntax again for this one.
```
# implement the tokens hook so we can add our new token to the list of tokens
# displayed to CiviMail users
function myhooks_civicrm_tokens( &$tokens ) {
$tokens['contribution'] =
array('contribution.largest' => 'Largest Contribution');
/* just array('contribution.largest'); in 3.1 or earlier */
}
# now we'll set the value of our custom token;
# it's better in general to use the API rather than SQL queries to retrieve data,
# but in this case the MAX() function makes it very efficient to get the largest
# contribution, so let's make an exception
function myhooks_civicrm_tokenValues( &$details, &$contactIDs ) {
# prepare the contact ID(s) for use in a database query
if ( is_array( $contactIDs ) ) {
$contactIDString = implode( ',', array_values( $contactIDs ) );
$single = false;
} else {
$contactIDString = "( $contactIDs )";
$single = true;
}
# build the database query
$query = "SELECT contact_id,
max( total_amount ) as total_amount
FROM civicrm_contribution
WHERE contact_id IN ( $contactIDString )
AND is_test = 0
GROUP BY contact_id";
# run the query
$dao = CRM_Core_DAO::executeQuery( $query );
while ( $dao->fetch( ) ) {
if ( $single ) {
$value =& $details;
} else {
if ( ! array_key_exists( $dao->contact_id, $details ) ) {
$details[$dao->contact_id] = array( );
}
$value =& $details[$dao->contact_id];
}
# set the token's value
$value['contribution.largest'] = $dao->total_amount;
}
}
```
Goals and background
--------------------
- This documents how to extend CiviCRM to meet your needs. CiviCRM
uses hooks in a very similar manner to Drupal, primarily because
(based on our experience with Drupal's extension architecture) we
think it is clean and non-intrusive, yet incredibly powerful. For a
simple example module check [civitest
module](http://svn.civicrm.org/trunk/drupal/civitest.module.sample)
- See Drupal [hook documentation](http://drupal.org/node/292) for a
description of how hooks are implemented.
- See [CRM/Utils/Hook.php](http://svn.civicrm.org/civicrm/trunk/CRM/Utils/Hook.php)
in CiviCRM for the source code that invokes these hooks.
Implementing hooks
------------------
- In Drupal or CiviCRM, hooks can be implemented within a module or
extension. In general, implement a hook by declaring a global
function that starts with the name of your module and ends with the
name of the hook.
In Drupal module or a CiviCRM extension for example: to implement hook\_civicrm\_buildForm from within the "my\_custom" module/extension you would add the following function to your main .php or .module file (or a file always included by that script):
````
function my_custom_civicrm_buildForm($formName, &$form) {
// since the $form object was passed by reference, modifying it here will change it permanently
$form->assign('intro_text', ts('hello world'));
}
````
As long as the module/extension is enabled, this function will be called every time CiviCRM builds a form.
In WordPress, hooks can be implemented in a variety of ways. You can write a plugin or include them in your theme's 'functions.php' file - where you place them depends largely on whether they are theme-dependent or theme-independent. The general rule for targeting the hook is to remove the 'hook\_' prefix when you create the filter or action, but see the "For a WordPress Plugin" section below for more details.
The following code block shows the simplest form of a hook implementation in WordPress. In this case, the code receives callbacks from 'hook\_civicrm\_pre':
```
// hook into civicrm_pre
add_filter( 'civicrm_pre', 'my_plugin_pre_callback', 10, 4 );
function my_plugin_pre_callback( $op, $objectName, $objectId, &$objectRef ) {
// your code here
}
```
As long as the plugin is active (or - if the code is in 'functions.php' - as long as your theme is active), this function will be called every time CiviCRM is about to save data to the database.
For A CiviCRM (native) Extension
--------------------------------
- See this page for [creating an extension and implementing hooks
within it](/confluence/display/CRMDOC/Create+a+Module+Extension).
For A Drupal Module
-------------------
- See this page for [creating a module in Drupal](http://drupal.org/node/1074360) esp. the section on implementing hooks.
- For a working example, see the hook\_civicrm\_postProcess documentation below.
- You can also find examples in your CiviCRM install in [drupal/civitest.module.sample](http://svn.civicrm.org/civicrm/trunk/drupal/civitest.module.sample)
For a Joomla Plugin
-------------------
- See this page for [creating a Joomla plugin](http://docs.joomla.org/Plugin). Joomla plugins implement the
observer design pattern.
- Hook plugins should be placed in the civicrm plugin group in a subfolder with the same name as the plugin.
- Once created plugins may be packaged and installed with the Joomla installer or the files can be placed in the appropriate folder and installed with the discover method.
- See this [sample Joomla plugin for CiviCRM hooks](/confluence/display/CRMDOC/Example+Joomla+Plugin+for+implementing+hooks)
For a WordPress Plugin
----------------------
- For a detailed overview of the updated relationship between WordPress and CiviCRM, see the blog post [Working with CiviCRM 4.6 in WordPress](https://civicrm.org/blogs/haystack/working-civicrm-46-wordpress) on the CiviCRM website.
- In summary, as of CiviCRM 4.6 there is (almost) full compatibility with the WordPress actions and filters system.
- Any PHP file that will be included by WordPress can be used to contain your hook implementations. Use an in-house plugin, your site's 'functions.php' file, or place a file named 'civicrmHooks.php' in your CiviCRM custom php path (as specified in
Administer -\> System Settings -\> Directories -\> Custom PHP Path Directory).
- Prior to CiviCRM 4.6, hooks had to use the prefix "wordpress\_" as
the replacement for the "hook\_" part of the hook name. So to implement 'hook\_civicrm\_pre' you had to write:
```
function wordpress_civicrm_pre($op, objectName, $objectId, &$objectRef)
```
This method still works, so if you have legacy modifications, they will not break.
- As of CiviCRM 4.6, the general rule for targeting the hook is to remove the 'hook\_' prefix when you create the filter or action. So, if your plugin or theme wants to receive callbacks from 'hook\_civicrm\_pre', the filter should be written as
```
add_filter('civicrm_pre', 'my_callback_function', 10, 4 )
```
or if your callback method is declared in a class, the filter should be written as
```
add_filter( 'civicrm_pre', array( $this, 'my_callback_method', 10, 4 )
```
For more details (as well as the exceptions to this rule) see the [blog post](https://civicrm.org/blogs/haystack/working-civicrm-46-wordpress) mentioned above.
Inspecting hooks
----------------
The documentation about hooks can be somewhat abstract, and it sometimes
helps to see interactively how the hooks run.
- If you use Drupal, then you can inspect some hooks by installing
these two Drupal modules:
- [devel](http://drupal.org/project/devel)
- [civicrm\_developer](https://github.com/eileenmcnaughton/civicrm_developer)
- If you use WordPress, you can inspect hooks by installing the following plugin:
- [Query Monitor](https://wordpress.org/plugins/query-monitor/)
Example Drupal module for implementing hooks
---
I found it useful, when implementing hooks, to write wrapper code for most of them. The [attached zip](http://wiki.civicrm.org/confluence/download/attachments/86213379/callhooks.zip?version=1&modificationDate=1372586243000&api=v2) file is an example Drupal module that illustrates this technique. From the README file:
This is just example code to implement custom hooks for CiviCRM.
Each custom hook defined by CiviCRM is implemented here.
To use:
1. Install this module or incorporate its code into your own custom module.
2. Uncomment some/all the watchdog lines.
3. Visit the page you need to modify via a CiviCRM custom hook.
4. Re-comment the watchdog lines.
5. Visit admin/reports/dblog and look at the comments there.
6. Write a function as described by one of the comments.
Example Joomla Plugin for implementing hooks
---
This is a simple example of a plugin for Joomla that implements CiviCRM hooks. It consists of two file tabs.php and tabs.xml along with the blank index.html file which is considered good Joomla coding practice.
Note: Somewhere around Joomla 2.5.20 the JPlugin class was moved to cms.plugin.plugin from joomla.plugin.plugin (see the jimport call in Tab.php below). If you have not remained current with the latest Joomla revision, you may need to reference the correct location. If you find your plugins fail after updating to the latest release, be sure to check and fix that reference (it will often fail silently).
Tabs.php
```
<?php
/**
* @version
* @package Civicrm
* @subpackage Joomla Plugin
* @copyright Copyright (C) 2005 - 2011 Open Source Matters, Inc. All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
// No direct access
defined('_JEXEC') or die;
jimport('cms.plugin.plugin');
class plgCivicrmTabs extends JPlugin
{
/**
* Example Civicrm Plugin
*
* @package Civicrm
* @subpackage Joomla plugins
* @since 1.5
*/
public function civicrm_tabs(&$tabs, $contactID)
{
// unset the contribition tab, i.e. remove it from the page
unset( $tabs[1] );
// let's add a new "contribution" tab with a different name and put it last
// this is just a demo, in the real world, you would create a url which would
// return an html snippet etc.
$url = CRM_Utils_System::url( 'civicrm/contact/view/contribution',
"reset=1&snippet=1&force=1&cid=$contactID" );
$tabs[] = array( 'id' => 'mySupercoolTab',
'url' => $url,
'title' => 'Contribution Tab Renamed',
'weight' => 300 );
}
}
```
Tabs.xml
```
<?xml version="1.0" encoding="UTF-8"?>
<extension version="1.6" type="plugin" group="civicrm">
<name>plg_civcrm_tabs</name>
<author>Joomla! Project</author>
<creationDate>November 2005</creationDate>
<copyright>Copyright (C) 2005 - 2011 Open Source Matters. All rights reserved.</copyright>
<license>GNU General Public License version 2 or later; see LICENSE.txt</license>
<authorEmail>admin@joomla.org</authorEmail>
<authorUrl>www.joomla.org</authorUrl>
<version>1.6.0</version>
<description>PLG_CIVICRM_TABS_XML_DESCRIPTION</description>
<files>
<filename plugin="tabs">tabs.php</filename>
<filename>index.html</filename>
</files>
<config>
</config>
</extension>
```
You can make plugins that include multiple hooks or you can make separate plugins. What is appropriate will depend on the application.
Setting and getting custom field values from within hooks
---
To get a custom field ID given the custom field name and custom group name, you can use the following code:
```
require_once 'CRM/Core/BAO/CustomField.php';
$customFieldID = CRM_Core_BAO_CustomField::getCustomFieldID( $fieldLabel, $groupTitle );
```
For setting and getting custom field values in hooks, you need to know the field ID of the custom field(s) you want to work with. The easiest place to find these IDs is in the civicrm_custom_field table in the database. You'll then access these fields as "custom_ID". So if you have a field holding a custom value whose ID in the civicrm_custom_field table is 34, you'll use "custom_34" to access it.
Once you have the ID(s), you'll want to use the setValues and getValues functions in the CRM/Core/BAO/CustomValueTable.php file. Here are a couple of examples of their use:
Setting values (on a Contribution object's custom fields):
```
$custom_fields = array('foo' => 'custom_1', 'bar' => 'custom_2');
function modulename_civicrm_pre ($op, objectName, $objectId, &$objectRef) {
if ($objectName != 'Contribution' || ($op != 'edit' && $op != 'create')) {
return;
}
$contribution_id = $objectId;
require_once 'CRM/Core/BAO/CustomValueTable.php';
$my_foo = 'blah';
$my_bar = 'baz';
$set_params = array('entityID' => $contribution_id,
$custom_fields['foo'] => $my_foo, $custom_fields['bar'] => $my_bar);
CRM_Core_BAO_CustomValueTable::setValues($set_params);
}
```
Getting values (from a Contribution's associated Contact object):
```
$custom_fields = array('contact_foo' => 'custom_3', 'contact_bar' => 'custom_4');
function modulename_civicrm_pre ($op, objectName, $objectId, &$objectRef) {
if ($objectName != 'Contribution' || ($op != 'edit' && $op != 'create')) {
return;
}
// set the field names to 1 that we want to get back
$get_params = array('entityID' => $objectRef['contact_id'],
$custom_fields['contact_foo'] => 1, $custom_fields['contact_bar'] => 1);
require_once 'CRM/Core/BAO/CustomValueTable.php';
$values = CRM_Core_BAO_CustomValueTable::getValues($get_params);
$my_cfoo = $values[$custom_fields['contact_foo']];
$my_cbar = $values[$custom_fields['contact_bar']];
}
```
Note that custom field values may not always be available when you might expect. For instance, you can't retrieve custom field values in the 'create' operation in the _pre and _post hooks, because the custom field values haven't been stored yet. However, you can retrieve values in the 'edit' operation.
\ No newline at end of file
This diff is collapsed.
# Build
CiviCRM is an open-source application which can be poked, prodded, twisted,
and hacked. It can be customized (with minimal code skills), extended (for
add-ons and integrations), and collaboratively developed.
<table>
<tbody>
<tr>
<td><a href="requirements">Requirements</a></td>
<td>Get the tools you need</td>
</tr>
<tr>
<td><a href="build">Git Install</a></td>
<td>Install the latest code from git</td>
</tr>
<tr>
<td><a href="customize">Customize</a></td>
<td>Change your site without coding</td>
</tr>
<tr>
<td><a href="extend">Extend</a></td>
<td>Create an add-on or integration</td>
</tr>
<tr>
<td><a href="develop">Develop</a></td>
<td>Create a feature or fix for CiviCRM</td>
</tr>
<tr>
<td><a href="test">Test</a></td>
<td>Make it good</td>
</tr>
<tr>
<td><a href="reference">Reference</a></td>
<td>Dig into the nitty-gritty</td>
</tr>
</tbody>
</table>
# Collaborate
As an open-source project, CiviCRM is managed by an international community
of developers and activists. If you have questions, issues, or want to make
plans for new development, reach out online.
<table>
<tbody>
<tr>
<td><a href="https://civicrm.org/blog">Blog</a></td>
<td>Read about the big developments</td>
</tr>
<tr>
<td><a href="http://forum.civicrm.org/">Forum</a></td>
<td>Converse in the public square</td>
</tr>
<tr>
<td><a href="https://github.com/civicrm/civicrm-core/">Github</a></td>
<td>Tap the firehose of core development</td>
</tr>
<tr>
<td><a href="FIXME">Guidelines</a></td>
<td>Check the rules of the road</td>
</tr>
<tr>
<td><a href="https://irc.civicrm.org/">IRC</a></td>
<td>Chat with other developers in real-time</td>
</tr>
<tr>
<td><a href="http://issues.civicrm.org/">Issues</a></td>
<td>Discover on-going and resolved issues</td>
</tr>
<tr>
<td><a href="FIXME">Publish</a></td>
<td>Share your extensions</td>
</tr>
<tr>
<td><a href="FIXME">Sprints</a></td>
<td>Get together IRL</td>
</tr>
<tr>
<td><a href="http://civicrm.stackexchange.com/">StackExchange</a></td>
<td>Ask questions. Find answers.</td>
</tr>
<tr>
<td><a href="http://wiki.civicrm.org/confluence/display/CRM/CiviCRM+Wiki">Wiki</a></td>
<td>Share drafts, notes, and specs</td>
</tr>
</tbody>
</table>
Overview
========
In order for your CiviCRM extension to be compliant, you must provide a minimal extension documentation, written in [Markdown](https://guides.github.com/features/mastering-markdown/) language.
The allowed structure is the following:
* Headings (eg. [Heading 1](#heading-1), [Heading 2](#heading-2), [Heading 3](#heading-3))
* [Styling Texts](#styling-text)
* [Blockquotes](#blockquotes)
* [Unordered Lists](#unordered-lists)
* [Ordered Lists](#ordered lists)
* [Nested Lists](#nested-lists)
* Inline code block (see [example](#code-inline))
* [Links](#links)
* Table creation - Avoid creating tables! If you still want to use them, avoid complex columns/rows
Examples
========
Heading 1
---------
````javascript
This is a heading 1
===================
````
Heading 2
---------
````javascript
This is a heading 2
-------------------
````
Heading 3
---------
````javascript
### This is a heading 3
````
Styling Text
------------
Both bold and italic can use either a * or an _ around the text for styling. This allows you to combine both bold and italic if needed.
````
*This text will be italic*
**This text will be bold**
````
Blockquotes
-----------
You can indicate blockquotes with a >.
````
In the words of Abraham Lincoln:
> Pardon my french
````
Lists
-----
Unordered lists
---------------
You can make an unordered list by preceding list items with either a * or a -.
````
* Item
* Item
* Item
- Item
- Item
- Item
````
Ordered lists
-------------
You can make an ordered list by preceding list items with a number.
````
1. Item 1
2. Item 2
3. Item 3
````
Nested lists
------------
You can create nested lists by indenting list items by two spaces.
````
1. Item 1
1. A corollary to the above item.
2. Yet another point to consider.
2. Item 2
* A corollary that does not need to be ordered.
* This is indented four spaces, because it's two spaces further than the item above.
* You might want to consider making a new list.
3. Item 3
````
Inline code block
-----------------
### Inline formats
Use single backticks (`) to format text in a special monospace format. Everything within the backticks appear as-is, with no other special formatting.
Here's an idea: why don't we take `SuperiorProject` and turn it into `**Reasonable**Project`.
### Multiple lines
You can use prepend and append triple backticks (```) to format text as its own distinct block.
Check out this neat program I wrote:
```
x = 0
x = 2 + 2
what is x
```
Links
-----
You can create an inline link by wrapping link text in brackets ( [ ] ), and then wrapping the link in parentheses ( ( ) ).
````
This is a [demo link](https://www.google.com)
````
\ No newline at end of file
# Languages and Services
* Unix-like environment (Linux, OS X, or a virtual machine)
* [PHP v5.3+](http://php.net/)
* [MySQL v5.1+](http://mysql.com/)
* [NodeJS](https://nodejs.org/)
* [Git](https://git-scm.com/)
* Recommended: Apache HTTPD v2.2+
* Recommended: Ruby/Rake
# Command Line
There are many ways to install MySQL, PHP, and other dependencies -- for
example, `apt-get` and `yum` can download packages automatically; `php.net`
and `mysql.com` provide standalone installers; and MAMP/XAMPP provide
bundled installers.
Civi development should work with most packages -- but there's one proviso:
***the command-line must support standard commands*** (`php`, `mysql`,
`node`, `git`, `bash`, etc).
Some packages are configured properly out-of-the-box. (Linux distributions
do a pretty good job of this.) Other packages require extra configuration
steps (e.g. [Setup Command Line
PHP](http://wiki.civicrm.org/confluence/display/CRMDOC/Setup+Command-Line+PHP)
for MAMP).
In subsequent steps, the download script will attempt to identify
misconfigurations and display an appropriate message.
# Buildkit
The developer docs reference a large number of developer tools, such as
`drush` (the Drupal command line), `civix` (the CiviCRM code-generator), and
`karma` (the Javascript tester).
Many of these tools are commonly used by web developers, so you may have
already installed a few. You could install all the tools individually --
but that takes a lot of work.
[civicrm-buildkit](https://github.com/civicrm/civicrm-buildkit) provides
a script which downloads the full collection.
### - Option #1: Full Stack Ubuntu (Opinionated)
If you have a new installation of Ubuntu 12.04 or 14.04, then you can download everything -- buildkit and the system
requirements (`git`, `php`, `apache`, `mysql`, etc) -- with one command. This command will install buildkit to `~/buildkit`:
```bash
curl -Ls https://civicrm.org/get-buildkit.sh | bash -s -- --full --dir ~/buildkit
```
Note:
* When executing the above command, you must ***NOT*** run as `root`. (Doing so will produce incorrect permissions.)
Instead, you must have `sudo` permissions.
* The `--full` option is opinionated; it specifically installs `php`, `apache`, and `mysql` (rather than `hvm`, `nginx`, `lighttpd`, or `percona`).
If you try to mix `--full` with alternative systems, then expect conflicts.
### - Option #2: Other Systems
If you already installed the requirements (`git`, `php`, etc), then you can download buildkit to `~/buildkit` with these commands:
```bash
git clone https://github.com/civicrm/civicrm-buildkit.git buildkit
cd buildkit/bin
./civi-download-tools
export PATH="$PWD:$PATH"
```
### - Option #3: Upgrade
If you have previously downloaded buildkit and want to update it, run:
```bash
cd buildkit
git pull
./bin/civi-download-tools
```
*Test*
TODO:
* http://wiki.civicrm.org/confluence/display/CRMDOC/Testing
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment