diff --git a/docs/api/chaining.md b/docs/api/chaining.md deleted file mode 100644 index 2b725d448a29d4074de26b836fbea112cce31f75..0000000000000000000000000000000000000000 --- a/docs/api/chaining.md +++ /dev/null @@ -1,76 +0,0 @@ -# APIv3 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. - -See [api/v3/examples] within the core source code for a plethora of examples -(from unit tests) that use chaining. To start, look at these examples: - -- [APIChainedArray.php] -- [APIChainedArrayFormats.php] -- [APIChainedArrayValuesFromSiblingFunction.php] - -[api/v3/examples]: https://github.com/civicrm/civicrm-core/tree/master/api/v3/examples -[APIChainedArray.php]: https://github.com/civicrm/civicrm-core/blob/master/api/v3/examples/Contact/APIChainedArray.php -[APIChainedArrayFormats.php]: https://github.com/civicrm/civicrm-core/blob/master/api/v3/examples/Contact/APIChainedArrayFormats.php -[APIChainedArrayValuesFromSiblingFunction.php]: https://github.com/civicrm/civicrm-core/blob/master/api/v3/examples/Contact/APIChainedArrayValuesFromSiblingFunction.php - - -Note that there are a few supported syntaxes: - -```php -civicrm_api('Contact', 'create', array( - 'version' => 3, - 'contact_type' => 'Individual', - 'display_name' => 'BA Baracus', - 'api.website.create' => array('url' => 'example.com'), -)); -``` - -is the same as - -```php -civicrm_api('Contact', 'create', array( - 'version' => 3, - 'contact_type' => 'Individual', - 'display_name' => 'BA Baracus', - 'api.website' => array('url' => 'example.com'), -)); -``` - -If you have 2 websites to create you can pass them as ids after the `.` -or an array - -```php -civicrm_api('Contact', 'create', array( - 'version' => 3, - 'contact_type' => 'Individual', - 'display_name' => 'BA Baracus', - 'api.website.create' => array('url' => 'example.com'), - 'api.website.create.2' => array('url' => 'example.org'), -)); -``` - -or - -```php -civicrm_api('Contact', 'create', array( - 'version' => 3, - 'contact_type' => 'Individual', - 'display_name' => 'BA Baracus', - 'api.website.create' => array( - array('url' => 'example.com'), - array('url' => 'example.org'), - ), -)); -``` - -The format you use on the way in will dictate the format on the way out. - -Currently this supports any entity and it will convert to `entity_id` - -i.e. a PledgePayment inside a contribution will receive the `contribution_id` -from the outer call. diff --git a/docs/api/index.md b/docs/api/index.md index f2e13f1436503a3dc0cef4d428569a5104392623..76c86aa9232040db524a9b2ef3139d1ffcb9adad 100644 --- a/docs/api/index.md +++ b/docs/api/index.md @@ -1,56 +1,42 @@ # The CiviCRM API -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. +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. -Utilizing the API is superior to accessing core functions directly (e.g. -calling raw SQL, or calling functions within the BAO files) -because the API offers a consistent interface to CiviCRM's features. It is -designed to function predictably with every new release so as 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 SQL statements), -you risk running into future problems when changes to the schema and -BAO arguments inevitably occur. +Utilizing the API is superior to accessing core functions directly (e.g.calling raw SQL, or calling functions within the BAO files) because the API offers a consistent interface to CiviCRM's features. It is designed to function predictably with every new release so as 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 SQL statements), you risk running into future problems when changes to the schema and BAO arguments inevitably occur. -The best place to begin working with the API is your own ***test*** install of -CiviCRM, using the API explorer and the API parameter list. +The best place to begin working with the API is your own *test* install of CiviCRM, using the API explorer and the API parameter list. -For help creating your own API custom calls, see [civix generate:api](/extensions/civix.md#generate-api) +Extensions can provide additional API functionality. For help creating your own additions to the API, see [civix generate:api](/extensions/civix.md#generate-api). -## API explorer +## API Versions -The API explorer is a powerful GUI tool for building and executing API calls. +CiviCRM's API has major versions (APIv2, APIv3, APIv4) which are independent of the CiviCRM version. The API version is incremented more slowly in order to maintain stability within the extension ecosystem. Typically, two versions of the API are maintained concurrently (currently v3 and v4) to allow gradual transitions. New releases of CiviCRM may add features to the API but will not break backward-compatibility within an API version. -To access the API explorer: +## API Explorer -1. Go to any CiviCRM site +The API explorer is a powerful GUI tool for building and executing API calls. To access it: + +1. Log in to a CiviCRM site as an administrator. * This can even be the [demo site](http://dmaster.demo.civicrm.org/). -1. Within the CivCRM menu, go to **Support > Developer > API Explorer** or go to the URL `/civicrm/api`. +2. Within the CivCRM menu, go to **Support > Developer** and either **API Explorer v3** or **API Explorer v4** (URL `/civicrm/api` or `/civicrm/api4`). !!! warning The API explorer actually executes real API calls. It can modify data! So if you execute a `Contact` `delete` call, it will really delete the contact. As such, any experimenting is best done within a test site. -You can select the entity you want to -use, for example `Contact` and the action you want to perform, for -example `Get`. The API explorer -will show you the specific code necessary to execute the API call you -have been testing. +You can select the entity you want to use, for example `Contact` and the action you want to perform, for example `Get`. The API explorer will show you the specific code necessary to execute the API call you have been testing using the various API interfaces available. ## API parameter documentation -From the API explorer, you can click on the **Code Docs** tab to find documentation for each API entity/action. 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. +From the API explorer, you can get documentation on how to construct your API query. This is done either in the screen as you fill out the GUI to create your API call or in the v3 Explorer there are docs under the Code Docs tab which will point at the relevant aspects of the v3 code base that run the API calls. -## API examples +## API Examples (APIv3 Only) -From the API explorer, you can click on the **Examples** tab to find examples of API calls which are based on automated tests within the source code. You can also [explore these examples on GitHub](https://github.com/civicrm/civicrm-core/tree/master/api/v3/examples). +Within the API Explorer you will be able to attain an example of the code that you should write to call the API. In APIv3, you can also access specific examples of some API calls from the Examples tab within the explorer. You can also [explore these examples on GitHub](https://github.com/civicrm/civicrm-core/tree/master/api/v3/examples). -### API Examples in your extensions +### API examples in your extensions -From CiviCRM v5.8 the APIv3 explorer will now be able to show examples that are stored in your extension. The only requirement is that they are found in the same sort of directory structure as core e.g. in `<yourextension>/api/v3/examples/<entity>/<file>` +Beginning in CiviCRM v5.8, the APIv3 explorer will now be able to show examples that are stored in your extension. The only requirement is that they are found in the same sort of directory structure as core e.g. in `<yourextension>/api/v3/examples/<entity>/<file>` ## Changelog -All important changes made to the API are recorded in [API changes](/api/changes.md). +All important changes made to the API are recorded in [APIv3 changes](/api/v3/changes.md) and [APIv4 changes](/api/v4/changes.md). diff --git a/docs/api/interfaces.md b/docs/api/interfaces.md index 094881b50f1e8fea75e15c4aa7f209671be751e2..0af7467d602db1ca30f823215692d2f027a7406b 100644 --- a/docs/api/interfaces.md +++ b/docs/api/interfaces.md @@ -1,6 +1,6 @@ -# APIv3 Interfaces +# API Interfaces -The APIv3 has three main interfaces along with the PHP Code that can be used to access the API. +The API has three main interfaces along with the PHP Code that can be used to access the API. ## Javascript {#javascript} @@ -10,56 +10,9 @@ CiviCRM provides a number of different methods to interact with the API when in The AJAX interface is one of the more common interfaces used within CiviCRM code. The AJAX interface is most commonly seen when used in javascript code. You can get example AJAX interface code out of the [API Explorer](/api/index.md#api-explorer) as needed. -#### CRM.api3 - -`CRM.api3` is a javascript method produced by CiviCRM as a thin wrapper around a call to `http://example.org/civicrm/ajax/rest`. The standard format of a `CRM.api3` call would be - -```javascript -CRM.api3('entity', 'action', [params], [statusMessage]); -``` - -If you pass `true` in as the `StatusMessage` param, it will display the default status Message. This is useful when doing things such as adding tags to contacts or similar. If you wish to do further work based on the result of the API call (e.g use the results from a GET call) you will need to use the [done method](http://api.jquery.com/deferred.done/) to listen for the event. For example: - -```javascript -CRM.api3('entity_tag', 'create', {contact_id:123, tag_id:42}) - .done(function(result) { - console.log(result); - }); -``` - -Using the CRM.api3 method you can pass multiple requests through at once e.g. - -```javascript -var params = [ - ['email', 'get', {contact_id: 123}], - ['phone', 'get', {phone: '555-5555'}] -]; -CRM.api3(params).done(function(result) { - console.log('email result is:', result[0]); - console.log('phone result is:', result[1]); -}); -``` - -You can also use associative objects in your API call as follows: - -``` -var params = { - one: ['email', 'getoptions', {field: 'location_type_id'}], - two: ['phone', 'getoptions', {field: 'phone_type_id', sequential: 1}], - three: ['phone', 'get'] -}; -CRM.api3(params).done(function(result) { - console.log('email result is:', result.one); - console.log('phone options are:', result.two); - console.log('phone get result is:', result.three); -}); -``` - -These requests are different to doing a Chained API call as they are making simultaneous API requests and they are not related or dependent on each other. - -!!! note - Javascript does not guarantee the *ordering* of associative objects. To ensure the API calls execute in a specific order, use the array syntax instead. +#### CRM.api3 / CRM.api4 +`CRM.api3` and `CRM.api4` is a javascript method produced by CiviCRM as a thin wrapper around a call to `http://example.org/civicrm/ajax/rest`. The standard format of such an API call can be found under the relevant usage sub-chapter of this documentation #### Tests @@ -75,7 +28,7 @@ The recommended AJAX interface has changed between CiviCRM versions as follows: * version 4.3.x - `CRM.api(...)` * version 4.4.x onwards - `CRM.api3()` -For details see [API changes](/api/changes.md). +For details see [APIv3 changes](/api/v3/changes.md). ### Javascript AngularJS crmAPI {:#angularjs} diff --git a/docs/api/actions.md b/docs/api/v3/actions.md similarity index 99% rename from docs/api/actions.md rename to docs/api/v3/actions.md index b2cc49d32f067551db8cb0e77f20c065960a419e..f2e16ff5d0ae6ba11336eaa1e7af03ff24ed91fb 100644 --- a/docs/api/actions.md +++ b/docs/api/v3/actions.md @@ -1,4 +1,4 @@ -# API Actions +# APIv3 Actions Most entities support the following actions: diff --git a/docs/api/v3/chaining.md b/docs/api/v3/chaining.md new file mode 100644 index 0000000000000000000000000000000000000000..7719233eb9ed65c98bcefc23aa479879cf76ad45 --- /dev/null +++ b/docs/api/v3/chaining.md @@ -0,0 +1,62 @@ +# APIv3 Chaining + +It is 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`. + +See [api/v3/examples](https://github.com/civicrm/civicrm-core/tree/master/api/v3/examples) within the core source code for a plethora of examples (from unit tests) that use chaining. To start, look at these examples: + +- [APIChainedArray.php](https://github.com/civicrm/civicrm-core/blob/master/api/v3/examples/Contact/APIChainedArray.ex.php) +- [APIChainedArrayFormats.php](https://github.com/civicrm/civicrm-core/blob/master/api/v3/examples/Contact/APIChainedArrayFormats.ex.php) +- [APIChainedArrayValuesFromSiblingFunction.php](https://github.com/civicrm/civicrm-core/blob/master/api/v3/examples/Contact/APIChainedArrayValuesFromSiblingFunction.ex.php) + +Note that there are a few supported syntaxes: + +```php +civicrm_api('Contact', 'create', array( + 'version' => 3, + 'contact_type' => 'Individual', + 'display_name' => 'BA Baracus', + 'api.website.create' => array('url' => 'example.com'), +)); +``` + +is the same as + +```php +civicrm_api('Contact', 'create', array( + 'version' => 3, + 'contact_type' => 'Individual', + 'display_name' => 'BA Baracus', + 'api.website' => array('url' => 'example.com'), +)); +``` + +If you have 2 websites to create you can pass them as ids after the `.` +or an array + +```php +civicrm_api('Contact', 'create', array( + 'version' => 3, + 'contact_type' => 'Individual', + 'display_name' => 'BA Baracus', + 'api.website.create' => array('url' => 'example.com'), + 'api.website.create.2' => array('url' => 'example.org'), +)); +``` + +or + +```php +civicrm_api('Contact', 'create', array( + 'version' => 3, + 'contact_type' => 'Individual', + 'display_name' => 'BA Baracus', + 'api.website.create' => array( + array('url' => 'example.com'), + array('url' => 'example.org'), + ), +)); +``` + +The format you use on the way in will dictate the format on the way out. + +Currently this supports any entity and it will convert to `entity_id` - i.e. a PledgePayment inside a contribution will receive the `contribution_id` from the outer call. diff --git a/docs/api/changes.md b/docs/api/v3/changes.md similarity index 99% rename from docs/api/changes.md rename to docs/api/v3/changes.md index 3b0e4600d19945a937aea728132681c561dc721c..df26cecef82df754c3cc7874706c978f6b5f59dd 100644 --- a/docs/api/changes.md +++ b/docs/api/v3/changes.md @@ -338,7 +338,7 @@ When creating a new Case record, the "create" API previously accepted `case_type ### 4.3.0: Deprecate Constant API -Most `CRM_*_Pseudoconstant methods` (which the 'constant' api is a wrapper for) are deprecated in 4.3 and many are removed in 4.4. To future-proof your code, use the [api.getoptions](/api/actions.md#getoptions) method instead of the constant api. See [Pseudoconstant (option list) Reference](/framework/pseudoconstant.md) +Most `CRM_*_Pseudoconstant methods` (which the 'constant' api is a wrapper for) are deprecated in 4.3 and many are removed in 4.4. To future-proof your code, use the [api.getoptions](/api/v3/actions.md#getoptions) method instead of the constant api. See [Pseudoconstant (option list) Reference](/framework/pseudoconstant.md) ### 4.3.0: Contact get API now respects ACLS diff --git a/docs/api/custom-data.md b/docs/api/v3/custom-data.md similarity index 100% rename from docs/api/custom-data.md rename to docs/api/v3/custom-data.md diff --git a/docs/api/examples.md b/docs/api/v3/examples.md similarity index 74% rename from docs/api/examples.md rename to docs/api/v3/examples.md index 098ee517cb97c75998608c10dbfed50a969f4f2c..d41ddcff9699cd64b5c5464a58b896d4146c2fd3 100644 --- a/docs/api/examples.md +++ b/docs/api/v3/examples.md @@ -4,7 +4,7 @@ All the APIv3 Examples are generated through Tests in the CodeBase and are auto- ## Location of Examples -The most current examples can be found in CiviCRM's GitHub Repo on the [Master Branch](https://github.com/civicrm/civicrm-core/tree/master/api/v3/examples). In the GitHub Repo can you also find examples that relate to the LTS version as well in the [4.6 Branch](https://github.com/civicrm/civicrm-core/tree/4.6/api/v3/examples). When you install CiviCRM the Examples that come with the particular version of CiviCRM you have installed can be found in `<civicrm_root>/api/v3/examples`. You will also be able to view them through the [API Explorer](/api/index.md#api-explorer) by clicking on the **Examples** tab in the Explorer. +The most current examples can be found in CiviCRM's GitHub Repo on the [Master Branch](https://github.com/civicrm/civicrm-core/tree/master/api/v3/examples). When you install CiviCRM the Examples that come with the particular version of CiviCRM you have installed can be found in `<civicrm_root>/api/v3/examples`. You will also be able to view them through the [API Explorer](/api/index.md#api-explorer) by clicking on the **Examples** tab in the Explorer. ## Creating a New Example diff --git a/docs/api/joins.md b/docs/api/v3/joins.md similarity index 87% rename from docs/api/joins.md rename to docs/api/v3/joins.md index 62f70b1b43b14a2d8f628c01c31b3f55fb44b97d..f8e675e427362e75906727ee8d5a2ba522f3a961 100644 --- a/docs/api/joins.md +++ b/docs/api/v3/joins.md @@ -7,7 +7,7 @@ addresses, you may want to return the name of the associated contact from the Contact entity. The CiviCRM API supports two methods of returning data from associated entities; -API Joins and [API Chaining](/api/chaining.md). API joins provide higher +API Joins and [APIv3 Chaining](/api/v3/chaining.md). API joins provide higher performance by making a single SQL query with a [SQL join](https://dev.mysql.com/doc/refman/5.7/en/join.html), and are generally preferable to API chaining where available. @@ -43,8 +43,8 @@ $result = civicrm_api3('Event', 'get', array( )); ``` !!! tip - Joins are available only with the [get](/api/actions.md#getfields), - [getsingle](/api/actions.md#getsingle), and [getcount](/api/actions.md#getcount) + Joins are available only with the [get](/api/v3/actions.md#get), + [getsingle](/api/v3/actions.md#getsingle), and [getcount](/api/v3/actions.md#getcount) actions. ## Identifying fields eligible for a join @@ -52,7 +52,7 @@ $result = civicrm_api3('Event', 'get', array( It is possible to join an entity to any other entity if the [xml schema](/framework/database/schema-definition.md) identifies a [foreign key](/framework/database/schema-definition.md#table-foreignKey) or -a [pseudoconstant](/framework/database/schema-definition.md#table-field-pseudoconstant). The [getfields](/api/actions.md#getfields) action identifies +a [pseudoconstant](/framework/database/schema-definition.md#table-field-pseudoconstant). The [getfields](/api/v3/actions.md#getfields) action identifies fields that are eligible for an API join. !!! warning diff --git a/docs/api/options.md b/docs/api/v3/options.md similarity index 92% rename from docs/api/options.md rename to docs/api/v3/options.md index 9a51087087c858e8726665958be89f11d2a0f4d0..b31b34cc53ec9cb647e739f1ddff422a9f9dab1d 100644 --- a/docs/api/options.md +++ b/docs/api/v3/options.md @@ -1,6 +1,6 @@ # API Options -There are many API Options accepted by the CiviCRM API. These options allow the developer to add in more parameters to the resulting Query that is run against the database. E.g. Limit, Sort. You can explore these options using the the [API Explorer](/api/index.md#api-explorer) and the [API Examples](/api/examples.md) 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](/api/interfaces.md#rest). +There are many API Options accepted by the CiviCRM API. These options allow the developer to add in more parameters to the resulting Query that is run against the database. E.g. Limit, Sort. You can explore these options using the the [API Explorer](/api/index.md#api-explorer) and the [APIv3 Examples](/api/v3/examples.md) 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](/api/interfaces.md#rest). ## sequential diff --git a/docs/api/usage.md b/docs/api/v3/usage.md similarity index 79% rename from docs/api/usage.md rename to docs/api/v3/usage.md index 92a798733762a24ae73affc01c877c9ff617215a..d58967bf53d6f48a36140c6ce2bac875a75d58fc 100644 --- a/docs/api/usage.md +++ b/docs/api/v3/usage.md @@ -161,20 +161,48 @@ For more details, see [REST interface](/api/interfaces.md#rest). CRM.api3('entity', 'action', [params], [statusMessage]); ``` -For more details, see [AJAX Interface](/api/interfaces.md#ajax). - -The AJAX interface is automatically available for web-pages generated through -CiviCRM (such as standard CiviCRM web-pages, 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](/security/permissions.md#api-permissions) -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. +If you pass `true` in as the `StatusMessage` param, it will display the default status message. This is useful when doing things such as adding tags to contacts or similar. If you wish to do further work based on the result of the API call (e.g use the results from a GET call) you will need to use the [done method](http://api.jquery.com/deferred.done/) to listen for the event. For example: + +```javascript +CRM.api3('entity_tag', 'create', {contact_id:123, tag_id:42}) + .done(function(result) { + console.log(result); + }); +``` + +Using the CRM.api3 method you can pass multiple requests through at once e.g. + +```javascript +var params = [ + ['email', 'get', {contact_id: 123}], + ['phone', 'get', {phone: '555-5555'}] +]; +CRM.api3(params).done(function(result) { + console.log('email result is:', result[0]); + console.log('phone result is:', result[1]); +}); +``` + +You can also use associative objects in your API call as follows: + +``` javascript +var params = { + one: ['email', 'getoptions', {field: 'location_type_id'}], + two: ['phone', 'getoptions', {field: 'phone_type_id', sequential: 1}], + three: ['phone', 'get'] +}; +CRM.api3(params).done(function(result) { + console.log('email result is:', result.one); + console.log('phone options are:', result.two); + console.log('phone get result is:', result.three); +}); +``` + +The AJAX interface is automatically available for web-pages generated through CiviCRM (such as standard CiviCRM web-pages, 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](/security/permissions.md#api-permissions) +and [Same Origin Policy](http://en.wikipedia.org/wiki/Same_origin_policy). To use it from an external site or application, see the REST interface documentation. ## Smarty diff --git a/docs/api/v4/actions.md b/docs/api/v4/actions.md new file mode 100644 index 0000000000000000000000000000000000000000..da0ed3992b9662c4bac19a4f7e29444c365d2bcf --- /dev/null +++ b/docs/api/v4/actions.md @@ -0,0 +1,34 @@ +# APIv4 Actions + +Most entities support the following actions: + +## Create + +Insert new records into the database. + +## Update + +Update records in the database. + +## Delete + +Delete one or more records. Requires an explicit `id`. 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 + +## GetFields + +Fetch entity metadata, i.e. the list of fields supported by the entity. There is now an option that you can pass in for get fields which is `loadOptions`. This is the equivilant of the apiv3 getoptions API call. When used for any field that specifies a pseudoconstant it will return the relevant options in an options key. You can also pass in an option `IncludeCustom` which will specifiy whether to include the relevant custom fields for that entity or not. + +## 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 action - use with care & test well before using in production. + +## Save + +Create or update one or more records diff --git a/docs/api/v4/chaining.md b/docs/api/v4/chaining.md new file mode 100644 index 0000000000000000000000000000000000000000..cc57142943aa848ef7a8dcb1648f15d85f257fce --- /dev/null +++ b/docs/api/v4/chaining.md @@ -0,0 +1,61 @@ +# APIv4 Chaining + +It is 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`. + +Note that there are a few supported syntaxes: + +Object Oriented way + +```php +$results = \Civi\Api4\Contact::create() + ->addValue('contact_id', 'Individual') + ->addValue('display_name', 'BA Baracus') + ->addChain('create_website', \Civi\Api4\Website::create()->setValues(['contact_id' => '$id', 'url' => 'example.com'])) + ->execute(); +``` + +Traditional: + +```php +civicrm_api('Contact', 'create', [ + 'version' => 4, + 'values' => [ + 'contact_type' => 'Individual', + 'display_name' => 'BA Baracus', + ], + 'chain' => [ + 'create_website', ['Website', 'create', ['values' => ['url' => 'example.com', 'contact_id' => '$id']]], + ], +]); +``` + +If you have 2 websites to create you can pass them as separate key => array pairs just specify a unique array key in the chain array + +Object Oriented way + +```php +$results = \Civi\Api4\Contact::create() + ->addValue('contact_id', 'Individual') + ->addValue('display_name', 'BA Baracus') + ->addChain('first_website', \Civi\Api4\Website::create()->setValues(['contact_id' => '$id', 'url' => 'example1.com'])) + ->addChain('second_website', \Civi\Api4\Website::create()->setValues(['contact_id' => '$id', 'url' => 'example2.com'])) + ->execute(); +``` + +Traditional: + +```php +civicrm_api('Contact', 'create', [ + 'version' => 4, + 'values' => [ + 'contact_type' => 'Individual', + 'display_name' => 'BA Baracus', + ], + 'chain' => [ + 'create_first website', ['Website', 'create', ['values' => ['url' => 'example1.com', 'contact_id' => '$id']]], + 'create_second_website', ['Website', 'create', ['values' => ['url' => 'example2.com', 'contact_id' => '$id']]], + ], +]); +``` + +Note the use of "$id" in the examples above - any field returned by the outer call can be passed down to a chained call by prefixing it with a dollar sign. Even the results of other chains can be accessed in this way. diff --git a/docs/api/v4/changes.md b/docs/api/v4/changes.md new file mode 100644 index 0000000000000000000000000000000000000000..fbaaca542097531a480eaa7278bfd0b51a2fdaea --- /dev/null +++ b/docs/api/v4/changes.md @@ -0,0 +1,9 @@ +# API v4 Changelog + +This page lists additions to the v4 api with each new release of CiviCRM Core. + +Also see: [Differences Between Api v3 and v4](/api/v4/differences-with-v3.md). + +## Nothing here yet. + +API v4 is brand new. No changes yet! diff --git a/docs/api/v4/custom-data.md b/docs/api/v4/custom-data.md new file mode 100644 index 0000000000000000000000000000000000000000..0fb5cc277005d0fa78d5fd5f979cf9998068b29f --- /dev/null +++ b/docs/api/v4/custom-data.md @@ -0,0 +1,44 @@ +# APIv4 and Custom Data + +CiviCRM has a flexible custom data system which allows nearly any entity to be extended. It comes in two distinct flavors: Single-record and Multi-record. For more background see the user guide chapter: [Creating Custom Fields](https://docs.civicrm.org/user/en/latest/organising-your-data/creating-custom-fields/). + +## Single-Record Custom Data + +Because single-record fields extend an entity 1-to-1, the API treats the custom fields as an extension of the regular fields. For example, normally an Event has fields like `id`, `title`, `start_date`, `end_date`, etc. Adding a custom group named "Event_Extra" and a field named "Room_number" would be accessible from the API as "Event_Extra.Room_number". You would retrieve it and set it as if it were any other field. Note that the `name` of a field is not to be confused with the `label` The API refers to custom groups/fields by name and not user-facing labels which are subject to translation and alteration. + +## Multi-Record Custom Data + +Multiple record custom data sets are treated by the API as entities, which work similarly to other entities attached to contacts (Phone, Email, Address, etc.). For example, creating a multi-record set named "Work_History" could then be accessed via the API as an entity named "Custom_Work_History" (traditional style) or via the `CustomValue` php class (OO style). Creating a record would be done like so: + +**PHP (traditional):** +```php +civicrm_api4('Custom_Work_History', 'create', [ + 'values': ['entity_id': 202, 'Test_Field': 555] +]); +``` +**Javascript:** +```javascript +CRM.api4('Custom_Work_History', 'create', { + values: {"entity_id":202, "Test_Field":555} +}); +``` + +**PHP (OO):** Note that the object-oriented style uses the `CustomValue` class: + +```php +\Civi\Api4\CustomValue::create('Work_History') + ->addValue('entity_id', 202) + ->addValue('Test_Field', 555) + ->execute(); +``` + +## Field Types and I/O Formats + +New custom fields can be configured to store different types of data (Text, Date, Number, URL, etc.). In most cases the I/O format via the api will be a string, however there are a few exceptions: + +- **Date fields:** Input format is anything understood by `strtotime`, e.g. "now" or "-1 week" or "2020-12-25". Output format is the ISO string "YYYY-MM-DD HH:MM:SS". +- **Checkbox/multi-select fields:** I/O format is an array of option values. + +## Try It Out + +Once you have created some custom data in your system, look for it in the API Explorer. Single-record data will appear as fields on the entities they extend, and multi-record data will appear in the list of entities (look under "C" alphabetically as they all start with the prefix "Custom_". diff --git a/docs/api/v4/differences-with-v3.md b/docs/api/v4/differences-with-v3.md new file mode 100644 index 0000000000000000000000000000000000000000..7c04e3815b667ff4c14e43503972e216e087baea --- /dev/null +++ b/docs/api/v4/differences-with-v3.md @@ -0,0 +1,166 @@ +# Differences Between API v3 and v4 + +APIv4 is broadly similar to APIv3. Both are designed for reading and writing data. +Both use *entities*, *actions*, and *parameters*. However, APIv4 is specifically a +breaking-change which aims to reduce *ambiguity* and improve *flexibility* and *consistency*. + +This document walks through a list of specific differences. As you consider +them, it may help to have a concrete example expressed in both APIv3 and APIv4: + +<!-- Would be nice if Markdown made it easier to do side-by-side comparison... --> +<table> + <thead> + <tr> + <th>APIv3</th> + <th>APIv4</th> + </tr> + </thead> + <tbody> + <tr> +<td> + <em>Procedural-array style:</em><br/> + <div class="codehilite"><pre> + 1: $res = civicrm_api3('Contact', 'get', [ + 2: 'sequential' => 1, + 3: 'check_permissions' => 0, + 4: 'first_name' => 'Bob', + 5: 'return' => 'id,display_name', + 6: 'options' => [ + 7: 'limit' => 2, + 8: 'offset' => 2, + 9: ], +10: ]); +11: +12: foreach ($res['values'] as $row) { +13: echo $row['display_name']; +14: } +</pre></div> +</td> +<td> + <em>Procedural-array style:</em><br/> + <div class="codehilite"><pre> + 1: $res = civicrm_api4('Contact', 'get', [ + 2: 'checkPermissions' => FALSE, + 3: 'where' => [['first_name', '=', 'Bob']], + 4: 'select' => ['id', 'display_name'], + + 6: 'limit' => 2, + 7: 'offset' => 2, + + 9: ]); +10: +11: foreach ($res as $row) { +12: echo $row['display_name']; +13: } +</pre></div> + + <em>Object-oriented style:</em><br/> + <div class="codehilite"><pre> + 1: $res = \Civi\Api4\Contact::get() + 2: ->setCheckPermissions(FALSE) + 3: ->addWhere(['first_name', '=', 'Bob']) + 4: ->addSelect(['id', 'display_name']) + + 6: ->setLimit(2) + 7: ->setOffset(2) + + 9: ->execute(); +10: +11: foreach ($res as $row) { +12: echo $row['display_name']; +13: } +</pre></div> +</td> + </tr> + </tbody> +</table> + + +## API Wrapper + +* APIv4 supports two notations in PHP: + * Procedural/array style: `civicrm_api4('Entity', 'action', $params)` + * Object-oriented style: `\Civi\Api4\Entity::action()->...->execute()` +* When using OOP style in an IDE, most actions and parameters can benefit from auto-completion and type-checking. +* `$checkPermissions` always defaults to `TRUE`. In APIv3, the default depended on the environment (`TRUE` in REST/Javascript; `FALSE` in PHP). +* A 4th param `index` controls how results are returned: + * Passing a string will index all results by that key e.g. `civicrm_api4('Contact', 'get', $params, 'id')` will index by id. + * Passing a number will return the result at that index e.g. `civicrm_api4('Contact', 'get', $params, 0)` will return the first result and is the same as `\Civi\Api4\Contact::get()->execute()->first()`. `-1` is the equivalent of `$result->last()`. +* When chaining API calls together, back-references to values from the main API call must be explicitly given (discoverable in the API Explorer). + +## Actions +* For `Get`, the default `limit` has changed. If you send an API call without an explicit limit, then it will return *all* records. (In v3, it would silently apply a default of 25.) However, if you use the API Explorer, it will *recommend* a default limit of 25. +* The `Create` action is now only used for creating *new* items (no more implicit update by passing an id to v3 `create`). +* The `Save` action in v4 is most similar to v3's `create` - it accepts one or more records to create or update, infering the action based on the presence of `id` in each record. +* `Update` and `Delete` can be performed on multiple items at once by specifying a `where` clause, vs a single item by id in v3. +* `getsingle` is gone, use `$result->first()` or `index` `0`. +* `getoptions` is no longer a standalone action, but part of `getFields`. + +## Output +* Output is an object (`Result` aka [`ArrayObject`](https://www.php.net/manual/en/class.arrayobject.php)) rather than a plain `array`. +* In PHP, you can iterate over the `ArrayObject` (`foreach ($myResult as $record)`), or you can call methods like `$result->first()` or `$result->indexBy('foo')`. +* By default, results are indexed sequentially (`0,1,2,3,...` - like APIv3's `sequential => 1`). You may optionally index by `id`, `name`, or any other field, as in: + * (Procedural-style; use `$index` parameter): `civicrm_api4('Contact', 'get', [], 'id')` + * (OOP-style; use `indexBy()` method): `\Civi\Api4\Contact::get()->execute()->indexBy('id')` + +## Input +* Instead of a single `$params` array containing a mishmash of fields, options and parameters, each APIv4 parameter is distinct (see section on Params below). +* Custom fields are refered to by name rather than id. E.g. use `constituent_information.Most_Important_Issue` instead of `custom_4`. + +## Params + +If you used early versions of APIv3, you might have written some code like this: + +```php +civicrm_api3('Contact', 'get', array( + 'check_permissions' => 0, + 'first_name' => 'Elizabeth', + 'return' => 'id,display_name', + 'rowCount' => 2, + 'offset' => 2, +)); +``` + +You may notice that there are no subordinate arrays -- everything goes into one flat list of parameters. +As the system grew, this became a bit awkward: + +* What happens if you want to filter on a field named `return` or `action` or `rowCount`? +* How do you ensure that the same option gets the same name across all entities (`rowCount` vs `limit`)? +* Why does `first_name` use snake_case while `rowCount` uses lowerCamelCase? +* Why is `Contact.get` the only API to support `rowCount`? + +Over time, APIv3 evolved so that this example would be more typical: + +```php +civicrm_api3('Contact', 'get', [ + 'check_permissions' => FALSE, + 'first_name' => 'Elizabeth', + 'return' => ['id','display_name'], + 'options' => ['limit' => 1000, 'offset' => 2], +]); +``` + +Observe: + +* The `options` adds a place where you can define parameters without concern for conflicts. +* The new generation of `options` are more standardized - they often have generic implementations that work with multiple entities/actions. +* The top-level still contains a mix of *option* fields (like `return`) and *data* or *query* fields (like `first_name`). +* The old options at the top-level are deprecated but still around. + +APIv4 presented an opportunity to *break backward compatibility* and thereby *become more consistent*. In APIv4, a typical call would look like: + +```php +civicrm_api4('Contact', 'get', [ + 'checkPermissions' => FALSE, + 'where' => [['first_name', '=', 'Elizabeth']], + 'select' => ['id', 'display_name'], + 'limit' => 2, + 'offset' => 2, +]); +``` + +Key things to note: + +* The `options` array is completely gone. The params array *is* the list of options. +* Most of the options in the params array have shared/generic implementations - ensuring consistent naming and behavior. +* The *data* fields (e.g. `id`, `display_name`, and `first_name`) no longer appear at the top. They always appear beneath some other option, such as `where` or `select`. diff --git a/docs/api/v4/joins.md b/docs/api/v4/joins.md new file mode 100644 index 0000000000000000000000000000000000000000..1bbe0ea0c2bad9d4016538a4e60b78ccc2c778b5 --- /dev/null +++ b/docs/api/v4/joins.md @@ -0,0 +1,89 @@ +# API Joins + +An API "get" action will typically return only the values of the entity requested. However, there are times when it is advantageous to returned data from a related entity. For instance, when querying the API for email addresses, you may want to return the name of the associated contact from the Contact entity. + +The CiviCRM API supports two methods of returning data from associated entities; APIv4 Joins and [APIv4 Chaining](/api/v4/chaining.md). API joins provide higher performance by making a single SQL query with a [SQL join](https://dev.mysql.com/doc/refman/5.7/en/join.html), and are generally preferable to API chaining where available. + +## Using an API Join + +To use a join in an API call, specify the name of the field on which the join happens, a period, and the name of the field to reference. + +For instance, to search for all primary emails, returning the email and joining to also return the contact's display name: + +Object Oriented way: + +```php +$result \Civi\Api4\Email::get() + ->setSelect([ + 'contact.display_name', + 'email', + ]) + ->addWhere('is_primary', '=', 1) + ->setLimit(25) + ->setCheckPermissions(FALSE) + ->execute(); +``` + +Traditional: + +```php +$result = civicrm_api4('Email', 'get', [ + 'select' => ["email", "contact.display_name"], + 'where' => [ + ['is_primary', '=', 1], + ], + 'limit' => 25, +]); +``` + +Alternatively, to return email addresses of everyone whose last name is Smith by joining to the Contact entity: + +Object Oriented way: + +```php +$result \Civi\Api4\Email::get() + ->addWhere('contact.last_name', '=', 'Smith') + ->setLimit(25) + ->setCheckPermissions(FALSE) + ->execute(); +``` + +Traditional: + +```php +$result = civicrm_api4('Email', 'get', [ + 'where' => [ + ['contact.last_name', '=', "Smith"], + ], + 'limit' => 25, +]); +``` + +You can join multiple times in one query. For instance, to return a list of events, displaying their name, the name of the related campaign, and that campaign's type: + +Object Oriented way: + +```php +$result \Civi\Api4\Email::get() + ->setSelect(['title', 'campaign.name', 'campaign.campaign_type_id']) + ->setLimit(25) + ->setCheckPermissions(FALSE) + ->execute(); +``` + +Traditional: + +```php +$result = civicrm_api4('Event', 'get', [ + 'select' => ['title', 'campaign.name', 'campaign.campaign_type_id'], +)); + +``` + +!!! tip + Joins are available only with the [get](/api/v4/actions.md#get) action + +## Identifying fields eligible for a join + +It is possible to join an entity to any other entity if the [xml schema](/framework/database/schema-definition.md) identifies a [foreign key](/framework/database/schema-definition.md#table-foreignKey) or a [pseudoconstant](/framework/database/schema-definition.md#table-field-pseudoconstant). The [getfields](/api/v3/actions.md#getfields) action identifies +fields that are eligible for an API join. diff --git a/docs/api/v4/usage.md b/docs/api/v4/usage.md new file mode 100644 index 0000000000000000000000000000000000000000..833a9957cc5e99b253d19aecf8d9d959589ba09a --- /dev/null +++ b/docs/api/v4/usage.md @@ -0,0 +1,164 @@ +# APIv4 Usage + +Every API call consists of three elements: the *entity*, *action*, and *parameters*. Some commonly used entities in CiviCRM include the following: + +| Entity | Description | +|------------|--------------------------------------------| +| `Contact` | An individual, organization, or household. | +| `Activity` | A phone call, meeting, or email message. that has occurred (or will occur) at a specific date and time. | +| `Address` | A street-address related to a contact. | + +Each entity supports a number of actions. Consider these samples with commonly-used actions and parameters for the `Contact` entity: + +| Action | Parameters | Description | +|----------|--------------------------------------|---------------------------------| +| `create` | `#!json {"values":{"contact_type":"Individual", "first_name":"Jane", "last_name":"Doe"}}` | Create a new contact of type "Individual" with first name "Jane" and last name "Doe" | +| `get` | `#!json {"where":[["last_name", "=", "Doe"]], "limit":25}` | Fetch the first 25 contacts with the last name "Doe" | +| `delete` | `#!json {"where":[["id", "=", 42]]}` | Delete the contact with id "42" | + +(*For full, up-to-date details about specific entities and parameters, use the [API Explorer](/api/index.md#api-explorer).*) + +!!! info + As of CiviCRM version 5.18, not all core entities have been added to APIv4. You should check the API Explorer to see which entities are available. If the entity you require is not available then please open a pull request against the [`civicrm-core` repository](https://github.com/civicrm/civicrm-core) to add the entity or open an [issue](https://lab.civicrm.org/dev/core) and request that the entity is added. + +The API is available in many different environments (such as PHP, REST, and JavaScript), and the notation differs slightly in each environment. +However, if you understand the canonical notation, then other environments will appear as small adaptations. + +Canonically, an API call is processed by the API kernel. The `$entity`, `$action`, and `$params` are passed as inputs, and an `arrayObject` is returned as output. + +```php +$result = Civi::service('civi_api_kernel')->run('Contact', 'get', [ + 'version' => 4, + 'where' => [ + ['first_name', '=', 'Alice'], + ['last_name', '=', 'Roberts'], + ], +]); +``` + +The result of a successful API call typically looks like this: + +```json +[ + { /* DAO Object */ } +] +``` + +The result of a failed API call typically looks like this: + +```json +{ + "error_code": 0 +} +``` + +!!! info + Some parts of APIv4 differ significantly from APIv3, including the handling of `check_permissions` and the default limit for returned objects being removed. For details, refer to [Differences Between APIv3 and APIv4](/api/v4/differences-with-v3.md). + +## PHP + +This is the most common way to call the API. There are two formats of API calls: an object-oriented approach and the more traditional procedural style. + +### Object-Oriented (OOP) + +```php +$contacts = \Civi\Api4\Contact::get() + ->addWhere('last_name', '=', 'Adams') + ->setLimit(25) + ->execute(); +``` + +The API is first invoked using a static method in the form of `#!php Entity::action()`. +The returned object implements a number of helper methods like `#!php addWhere()`. +These helper methods use method chaining, which allows multiple methods to be chained together in one statement as shown above. + +### Traditional (Procedural) + +```php +try { + $contacts = civicrm_api4('Contact', 'get', array( + 'where' => [ + ['first_name', '=', 'Alice'], + ['last_name', '=', 'Roberts'], + ], + ]); +} +catch (\API_Exception $e) { + $error = $e->getMessage(); +} +printf("Found %d item(s)\n", count($contacts)); +``` + +This format matches the canonical format almost exactly, with a few improvements for usability: + +- The `version => 4` parameter is not required. +- Errors are reported as PHP exceptions. You may catch the exceptions or (by default) allow them to bubble up. +- You can immediately iterate over the contacts returned. + +*Note*: If you're writing a Drupal module, a Joomla extension, a WordPress plugin, or a standalone script, then you may need to **bootstrap** CiviCRM before using the API. See the examples in [Bootstrap Reference](/framework/bootstrap.md). + +## REST + +APIv4 is not yet available via REST. This is being tracked in [dev/core#1310](https://lab.civicrm.org/dev/core/issues/1310). + +## AJAX + +```javascript +CRM.api4('entity', 'action', [params], [index]); +``` + +If you wish to do further work based on the result of the API call (e.g use the results from a GET call) you will need to use the [done method](http://api.jquery.com/deferred.done/) to listen for the event. For example: + +```javascript +CRM.api4('EntityTag', 'create', { + values: {"entity_id":5, "tag_id":3} +}).then(function(results) { + // do something with results array +}, function(failure) { + // handle failure +}); +``` + +The AJAX interface is automatically available for web-pages generated through CiviCRM (such as standard CiviCRM web-pages, 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 `#!php CRM_Core_Resources::singleton()->addCoreResources()` +from PHP. Please note that the AJAX interface is subject to [API Security](/security/permissions.md#api-permissions) +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 + +APIv4 is not yet available as a Smarty function. + +## Scheduled jobs + +APIv4 is not yet available for scheduled jobs. + +## Command line + +### drush + +APIv4 is not yet available as a drush command. + +### wp-cli + +APIv4 is not yet available as a wp-cli command. + +### cv + +`cv` supports multiple input formats for APIv4. The API Explorer uses the JSON format in generated code: + +```bash +cv api4 Contact.get '{"where":[["first_name", "=", "Alice"], ["last_name", "=", "Roberts"]]}' +``` + +This format may be cumbersome to enter manually, so the same API request could also be written like this: + +```bash +cv api4 Contact.get +w 'first_name = "Alice"' +w 'last_name = "Roberts"' +``` + +For more examples, refer to the output of `cv --help api4`. + +## API Security + +API has security measures built in depending on the way the API is called that can also be turned off or on. API Permissions are also able to be altered via hook. More information on API Security can be found in the [Security Documentation](/security/permissions.md). diff --git a/docs/core/pr-review.md b/docs/core/pr-review.md index 7ac19e46021a11403d125d5d40d20e2790d2914d..c72eae2e02b057527587c0ac5a10f4f07eedf6f8 100644 --- a/docs/core/pr-review.md +++ b/docs/core/pr-review.md @@ -46,7 +46,7 @@ On the PR, click over to “Files Changed†and understand what the code is doi ## Reproduce the problem -Confirm which branch the PR was created against. This is probably either `master` or the LTS. Setup an instance locally from that branch (e.g. with [buildkit](https://github.com/civicrm/civicrm-buildkit)), or test on the [public demo site if possible](https://civicrm.org/demo). Repeat the steps to reproduce described in the ticket or PR. +Confirm which branch the PR was created against. This is probably either `master` or a Release Candidate branch. Setup an instance locally from that branch (e.g. with [buildkit](https://github.com/civicrm/civicrm-buildkit)), or test on the [public demo site if possible](https://civicrm.org/demo). Repeat the steps to reproduce described in the ticket or PR. Confirm that the issue was a problem and a problem “worth solvingâ€, generally worthy of being in core. diff --git a/docs/extensions/civix.md b/docs/extensions/civix.md index 0dd7c35882fff71d02e8ed30ba8598e3fb1ec0de..aa99c7d74e550a2d793f94605046c83228dbf455 100644 --- a/docs/extensions/civix.md +++ b/docs/extensions/civix.md @@ -159,12 +159,14 @@ If you want your extension to store data in the database, then you will need to 1. Re-install your extension. ```bash - $ cv ext:uninstall org.example.myextension - $ cv ext:enable org.example.myextension + $ cv ext:uninstall myextension + $ cv ext:enable myextension ``` Now your entity should be ready to use. Try it out with `cv api MyEntity.create` and `cv api MyEntity.get`. Then [add some tests](#generate-test). +By default when you generate an entity you will be generating an APIv4 entity. To generate an APIv3 (or both) interface you need to specify `--api-version 3,4` or just `--api-version 3` + !!! note "Troubleshooting" If you've generated an entity within an extension that you created with `civix` v18.01.0 or earlier, then you'll need to add this hook to your `myextension.php` file (changing `myextension` to your extension's short name). diff --git a/docs/extensions/lifecycle.md b/docs/extensions/lifecycle.md index 420b99c03ca8ba77fd3fbffb48346924971d2f39..077626cd125a5868a289183f9150d8bb59f52862 100644 --- a/docs/extensions/lifecycle.md +++ b/docs/extensions/lifecycle.md @@ -94,7 +94,7 @@ Based on these rules, we can fill out a full table of the workflow: | Experimental | Official | Informal Discussion | As above. *Additionally* The author announces to a high-visibility medium (such as blog or mailing-list). If discussion is persuasive, a senior member of core team flags the project as official. | Locate the extension on the website. View a block which says, "Install Instructions", which includes drush/wp-cli commands. | Incubation | Contributed | Self-Assessment | In `civicrm.org`, the author creates an "extension" node and flags it as "Incubation". | Locate the extension on the website. View a block which says, "Install Instructions", which includes drush/wp-cli commands. | Incubation | Official | Informal Discussion | As above. *Additionally* The author announces to a high-visibility medium (such as blog or mailing-list). If discussion is persuasive, a senior member of core team flags the project as official. | Locate the extension on the website. View a block which says, "Install Instructions", which includes drush/wp-cli commands. -| Stable | Contributed | Formal Review (light) | In JIRA, the author requests a formal peer review. Once the reviewer is satisfied, they mark the node in `civicrm.org` as Stable. | In app, go to "Add New" and choose the extension. +| Stable | Contributed | Formal Review (light) | On `lab.civicrm.org`, the author requests a formal peer review (at https://lab.civicrm.org/extensions/extension-review-requests/issues ) . Once the reviewer is satisfied, they mark the node in `civicrm.org` as Stable. | In app, go to "Add New" and choose the extension. | Stable | Official | Formal Review (heavy) | As above. *Additionally* FormalReview criteria are more detailed. Announce to a high-visibility medium. At least one reviewer must be a senior member of the core team. | In app, go to "Add New" and choose the extension. | Deprecated | Contributed | Self-Assessment | In `civicrm.org`, the author marks the "extension" node as deprecated and announce to a high-visibility medium. | Locate the extension on the website. View a block which says, "Install Instructions", which includes drush/wp-cli commands. | Deprecated | Official | Informal Discussion | The author announces intent to deprecate in a high-visibility medium. If discussion is persuasive and no alternative maintainer comes forward, a senior member of core team flags the project as official. | Locate the extension on the website. View a block which says, "Install Instructions", which includes drush/wp-cli commands. diff --git a/docs/extensions/payment-processors/create.md b/docs/extensions/payment-processors/create.md index 0b915a9d85baeb28bfb08d45d6780d975d6c7066..5ea9a890f2af51aa5c81eea0ff784c3569ee6341 100644 --- a/docs/extensions/payment-processors/create.md +++ b/docs/extensions/payment-processors/create.md @@ -66,14 +66,14 @@ Checkout - the info is entered at the processors' site. -## Create the default payment processor file +### Create the Default Payment Processor File Depending on your billing mode there are different considerations. The file will live in `CRM/Core/Payment` and have the same name as entered into your `processor_type` table. -### Create initial processing file +### Create Initial Processing File In our example our file name is UCMPaymentCollection so the name of the file we are going to create is UCMPaymentCollection.php @@ -236,7 +236,7 @@ function doPayment( &$params, $component ) { ``` -### Create return processing file +### Create Return Processing File This is the file that is called by the payment processor after it returns from processing the payment. Let's call it @@ -614,7 +614,7 @@ else { CRM_Utils_System::redirect( $finalURL ); ``` -## Add any additional libraries needed +### Add Any Additional Libraries Needed In the case of this payment processor we needed nusoap. So in the extension directory we created a libraries directory and put it there. diff --git a/docs/financial/PaymentAPI.md b/docs/financial/PaymentAPI.md deleted file mode 100644 index 544807ccb83bec2c399b4d0a16fcd15a0def81d4..0000000000000000000000000000000000000000 --- a/docs/financial/PaymentAPI.md +++ /dev/null @@ -1,15 +0,0 @@ -Payment API - -Historically, one recorded a payment against a contribution by changing its payment status, for example from Pending to Completed. - -It is now best practice to use the Payment.create API call. - -Note that paymentprocessor.pay handles the communication with a payment processor to instigate a payment. Similarly, paymentprocessor.refund handles the communication with a payment processor to instigate a refund. - -After a contribution has been created, for example using the best practice Order.create api call, use the Payment API to: - -- record a full payment -- record a partial payment or subsequent payment -- record that a payment was cancelled (not the same as cancelling the whole contribution) -- record the refund of a payment - diff --git a/docs/financial/financialentities.md b/docs/financial/financialentities.md new file mode 100644 index 0000000000000000000000000000000000000000..ac6ecd5ea4180d06fd2e2c4e26dc078357c4a0b6 --- /dev/null +++ b/docs/financial/financialentities.md @@ -0,0 +1,88 @@ +!!! abstract This area of CiviCRM code and documentation is a work-in-progress. Not all features will be documented and the core code underlying this area may change from version to version. + +This file exists to give an overview of the Financial entities involved in recording Financial data in CiviCRM. + +You should only interact with the Financial entities through the relevant apis - generally Order & Payment apis. + +It is a work in progress! + +The original file for tracking these is [on the old CiviCRM Wik](https://wiki.civicrm.org/confluence/display/CRM/CiviAccounts+Data+Flow). + +## Financial Accounts + +These are accounting financial accounts. They have fields intended to help map to an accounting package that +are not used functionally in CiviCRM but are available in various reports. + +* accounting_code (free-form text) +* account_type_code (free-form text) +* financial_account_type_id (linked to the option group with the name financial_account_type) +* contact id (not used in core but can be used in extensions - e.g. this is used in the [connectors](https://github.com/eileenmcnaughton/nz.co.fuzion.connectors) extension to link some accounts to one Xero account & others to a different one). +* is_header_account + +In addition there are some functional fields that affect how tax is handled: + +* tax_rate +* is_deductible +* is_tax + + + +## Financial Transactions + +Movements into or out of financial accounts are represented by financial transactions in the civicrm_financial_trxn table. + +Each financial transaction has a `from_account_id` and a `to_account_id`. These represent movements between financial accounts. + +They also have various informative fields: + +* trxn_date +* fee_amount, net_amount, total_amount +* currency +* is_payment (is this a payment financial transaction - see section on [payments](#payments)) +* payment_instrument_id (links to payment_instrument option group - e.g check, credit card) +* payment_processor_id (when a payment processor has processed the payment) +* card_type_id, pan_truncation, check_number - these are additional bits of information gathered about the payment +* trxn_id, trxn_result_code, order_reference - these are all generated by the payment processor (when there is one) and +stored in CiviCRM when available. The trxn_id is the processor reference for the gateway. Some processors have references +at the order level. Even though these are at the order level there could be more than one per order as more than one. +payment with more than one processor might be paid against an order (contribution), hence they are stored on the financial transaction +* status_id - the intent is that failed as well as successful payments should be stored (and appropriately filtered in bookkeeping reports) + +## Payments + +Some financial transactions are payments and these are marked with the `is_payment` field on that table. Payments in CiviCRM are a subset +of the rows in `civicrm_financial_trxn`. You should use the Payment API to interact with these payment financial transactions. + +Importantly payments will end up moving money ***to*** an account where payments are collected - ie a Bank account +or a Payment Processor account (which in the real world may be an actual account or just a clearing house for nightly payments.) +Negative payments (or refunds) will have the bank or processor account on the ***from*** side of the transaction. + +## Financial Items + +Financial items exist to track how much has been paid against the various line items within an order / contribution. +In an accounting system this might be called credit-matching. + +Each line item will have one or more financial items denoting payments made against it. On creation of the order there +will be a financial item for each line item and an additional item for every fee amount. Where the preferred flow is used +this item will have a status of 'Unpaid'. + +!!! note + For historical reasons this may not always be true but [it's the goal](https://github.com/civicrm/civicrm-dev-docs/issues/712). + +When a payment is made it might either pay off the line items, or a specific line item, in full. In that case the line item +status is updated to Paid and an `EntityFinancialTrxn` record is created in the `civicrm_entity_financial_trxn` table linking +the line item to the payment and specifying the amount paid. + +If the line item is paid in part then the status is not updated and the `EntityFinancialTrxn` record specifies the portion +of the line item that has been paid by that payment. + +If the line items change then the items financial items have to be updated. Generally the rule is to alter the zero out the +old line item, reverse the financial items and then create a new line item with new financial items. However, this is not +always possible as there are some scenarios where the schema does not permit this. The has led to +adjustment line items being created in these cases. The issue is that the `civicrm_line_item` table has a unique index for +`entity_table + entity_id + contribution_id + price_field_value_id + price_field_id`. + +This means that if a line item with no `price_field_values` (i.e: a text / enter quantity line item) is altered it is not possible +to create a reversal line and a new line within the schema. The same problem occurs when changing a line item with `price_field_values` +***back*** to a `price_field_value` it previously held. In both these scenarios the work around is to have more than one *valid* `financial_item` +against the resulting line item with an *adjustment* entry - i.e: an additional `financial_item`. diff --git a/docs/financial/OrderAPI.md b/docs/financial/orderAPI.md similarity index 73% rename from docs/financial/OrderAPI.md rename to docs/financial/orderAPI.md index beb67a2da65e21c5254d6fdd06de82d4805256d1..82fc08b738c459908551c157396687f96c7ee3f4 100644 --- a/docs/financial/OrderAPI.md +++ b/docs/financial/orderAPI.md @@ -1,18 +1,22 @@ -The Order API is intended to be used as the primary API for adding, updating, and deleting orders. +!!! abstract + This area of CiviCRM code and documentation is a work-in-progress. Not all features + will be documented and the core code underlying this area may change from version + to version. -An 'order' is a non-CiviCRM term that corresponds to how CiviCRM uses its contribution object in terms of handling the full life-cycle of a purchase of memberships, event registrations or making a donation. Unlike most APIs, there is no table directly associated with the Order API. +An 'order' is our developer term for a pseudo-entity that maps to the CiviCRM contribution object but also encompasses related entities like line items, memberships, event registrations and underlying financial entities. There is no single 'order' table but the top level order information is stored in the civicrm_contribution table. -Donations, memberships and event registrations are all potential line items in an order/contribution. Pledge payments via a contribution's line item are a potential future enhancement. +The Order API is intended to be used as the primary API for adding, updating, and deleting orders. When using the Order API you should: -The Order API wraps the creation of associated objects like memberships and event registrations. In other words, don't create the objects first before adding them as an array of `line_item.create` parameters; instead rely on the Order API to create them for you. +1. Rely on the Order API to create related objects like line items, memberships and event registrations. (Don't pre-create them) +2. Always create orders in a pending state (unfortunately you need to pass contribution_status_id = Pending in for historical reasons). +3. Expect the status of contribution and any related memberships or event registrations to be Pending. +4. Call Payment.create to record any payments that have been made against the order. +5. Rely on adding payments to transition any relate entities to completed. -On creation, the status of contribution and any related memberships or event registrations is Pending if the contribution is pending. +You should NOT -If you later remove a line item for a membership or event registration on an update to an order, the Order API will look after changing the status for the related membership and event registration objects. - -Do not try to update the status of a contribution, for example to Completed to reflect a payment, either directly or through the Order API. Instead, do a call to the Payment API for an amount that will complete the required payment. This will transition the status of the contribution to Completed and related membership(s) to New or Current and event registration(s). - -As a best practice which we intend to require going forward, the `Order.create` should be called with a status of Pending. Then a `Payment.create` should be called to record a payment. +1. Pre-create line items memberships or event registrations +1. Update the status of an order to Completed using any method OTHER than adding payments to it (Payment.create api) ## Sample `Order.create` for Simple Contribution @@ -58,7 +62,7 @@ Things to note: 5. The `line_total` *must* equal the `unit_price` × `qty` !!! info - If you provide a value to `total_amount` as we have above, it *must* equal the sum of all the `line_total` values. Before 5.20 there was [a bug](https://lab.civicrm.orog/dev/financial/issues/73) that required the top-level `total_amount` was provided, but from 5.20 onward you can ommit this and it will be calculated automatically from the sum of the `line_items`. + If you provide a value to `total_amount` as we have above, it *must* equal the sum of all the `line_total` values. Before 5.20 there was [a bug](https://lab.civicrm.orog/dev/financial/issues/73) that required the top-level `total_amount` was provided, but from 5.20 onward you can omit this and it will be calculated automatically from the sum of the `line_items`. Currently the data returned from `Order.create` shows only the fields from the created Contribution. However an `Order.get` API call for the ID will also include an array of `line_items` (see below for example). @@ -312,8 +316,8 @@ Notes: 3. The `line_item` entry defines the price field and its value. 4. On calling `Payment.create` for this order, the participant's status would be changed to Registered. -!!! bug - Curently you must pass in `"status_id": "Pending from incomplete transaction"` otherwise the participant is created as Registered even before the paymnet has been made. +!!! info + Before 5.20 there was a bug such that you had to pass in `"status_id": "Pending from incomplete transaction"` otherwise the participant was created as Registered even before the paymnet has been made. ## Sample Order.create for 4 line items @@ -322,3 +326,37 @@ Notes: Here is how to create an order for a membership, an event registration, and two separate contribution line items. [ Rich to provide] + +## Transitioning from Contribution.transact api to Order api + +Contribution.transact api was a v2 api that we left in place in v3. It has never had unit tests & has never been supported. Unfortunately by not being more aggressive about deprecating it some sites have adopted it. + +The Contribution.transact api will create a 'simple' contribution and process a payment. It will not create the line items correctly for anything other than a straight forward donation and does not follow our practice of creating a pending contribution and then adding a payment. It's likely there are other unknown gaps in how it works. + +The simplest first step to migrate off it is to replace the order api call with a call that follows the recommended flow but still does not address the line item creation gaps & it is recommended you look at the patterns above to do that. This first step looks like + +``` +# start with the same parameters as Contribution.transact. +$params = $transactParams; +# it would be better just to include the relevant params but.... +$paymentParams = $transactParams; +$params['contribution_status_id'] = 'Pending'; +if (!isset($params['invoice_id')) { + // Set an invoice_id here if you have not already done so. + // Potentially Order api should do this https://lab.civicrm.org/dev/financial/issues/78 +} +if (!isset($params['invoiceID']) { + // This would be required prior to https://lab.civicrm.org/dev/financial/issues/77 + $params['invoiceID'] = $params['invoice_id']; +} +$order = civicrm_api3('Order', 'create' $params); +try { + civicrm_api3('PaymentProcessor', 'pay', ['contribution_id' => $order['id']]); + civicrm_api3('Payment', 'create', ['contribution_id' => $order['id'], 'amount' => $params['amount']]); +} +catch { + // it failed +} +``` + +The above is a few more lines but it is an important step towards transitioning to a supported method and away from a flawed api. diff --git a/docs/financial/overview.md b/docs/financial/overview.md index 45a60d6d69a8445ce52dde1fdeb0fb9a28f56790..c9397b963be447ccaf26283e5ed8a9017289d777 100644 --- a/docs/financial/overview.md +++ b/docs/financial/overview.md @@ -1,3 +1,8 @@ +!!! abstract + This area of CiviCRM code and documentation is a work-in-progress. Not all features + will be documented and the core code underlying this area may change from version + to version. + The financial subsystem in civicrm encompasses: - contributions @@ -6,7 +11,7 @@ The financial subsystem in civicrm encompasses: - refunds - prices - discounts -- premiums (things given away to contacts who donate alot) +- premiums (things given away to contacts who donate a lot) - accounting information - integrations with payment processors - integrations with accounting systems diff --git a/docs/financial/paymentAPI.md b/docs/financial/paymentAPI.md new file mode 100644 index 0000000000000000000000000000000000000000..fe86e57e1009405502a4a36d60d736c2db1c6ead --- /dev/null +++ b/docs/financial/paymentAPI.md @@ -0,0 +1,20 @@ +!!! abstract + This area of CiviCRM code and documentation is a work-in-progress. Not all features + will be documented and the core code underlying this area may change from version + to version. + +## Payment API + +Historically, one recorded a payment against a contribution by changing its payment status, for example from Pending to Completed. + +It is now best practice to use the Payment.create API call. + +Note that paymentprocessor.pay handles the communication with a payment processor to instigate a payment. Similarly, paymentprocessor.refund handles the communication with a payment processor to instigate a refund. + +After a contribution has been created, for example using the best practice Order.create API call, use the Payment.create API action to + +* record a payment against the contribution - either fully or partially paying the contribution amount +* record a refund against the contribution + +Use the Payment.cancel api to reverse a refunded payment. + diff --git a/docs/hooks/hook_civicrm_apiWrappers.md b/docs/hooks/hook_civicrm_apiWrappers.md index 6fd92da2f388531b93a1805f7798697b9137bce3..c5b8c0416594d4d270568f961b63ff7113adf7c7 100644 --- a/docs/hooks/hook_civicrm_apiWrappers.md +++ b/docs/hooks/hook_civicrm_apiWrappers.md @@ -18,7 +18,7 @@ Introduced in CiviCRM 4.4.0. ## Parameters - API_Wrapper[] $wrappers - an array of objects which implement the [`API_Wrapper`](#wrapper-class) interface. -- array $apiRequest - contains keys 'entity', 'action', and params; see [API Usage](/api/usage.md). +- array $apiRequest - contains keys 'entity', 'action', and params; see [APIv3 Usage](/api/v3/usage.md). ## Returns diff --git a/docs/hooks/hook_civicrm_permission.md b/docs/hooks/hook_civicrm_permission.md index a62d97dae55a2616b18591dcf3b2b3b6c28ed160..37a01d051a468edd6ac6e41ed000d74e534f32e1 100644 --- a/docs/hooks/hook_civicrm_permission.md +++ b/docs/hooks/hook_civicrm_permission.md @@ -29,7 +29,7 @@ to grant it to users. - Simple associative array in the format "permission string => label". Compatible with CiviCRM 4.3+. - $prefix = ts('CiviCRM Grant Program') . ': '; // name of extension or module + $prefix = ts('CiviCRM Grant Program:') . ' '; $permissions['edit grant programs'] = $prefix . ts('edit grant programs'); $permissions['delete in Grant Program'] = $prefix . ts('delete grant program'); @@ -39,14 +39,14 @@ to grant it to users. array item is present, it will appear as a description beneath the permission. - $prefix = ts('CiviCRM Grant Program') . ': '; // name of extension or module - $permissions['edit grant programs'] = array( + $prefix = ts('CiviCRM Grant Program:') . ' '; + $permissions['edit grant programs'] = [ $prefix . ts('edit grant programs'), // label ts('Create or edit grant programs and their criteria'), // description - ); - $permissions['delete in Grant Program'] = array( + ]; + $permissions['delete in Grant Program'] = [ $prefix . ts('delete grant program'), // if no description, just give an array with the label - ); + ]; ## Returns @@ -66,26 +66,28 @@ permissions, so one should adopt unique permission names. ## Example -The following is an excerpt from [the CiviCRM Monitoring for +The following is an excerpt based on [the CiviCRM Monitoring for Nagios](https://github.com/aghstrategies/com.aghstrategies.civimonitor/blob/bc1993fd07e2c730847e5fda6bf3958d41a51341/civimonitor.php#L132) extension, including a check for the CiviCRM version in order to ensure backwards compatibility while providing a description to versions that support it. + use CRM_Civimonitor_ExtensionUtil as E; + function civimonitor_civicrm_permission(&$permissions) { $version = CRM_Utils_System::version(); if (version_compare($version, '4.6.1') >= 0) { - $permissions += array( - 'access CiviMonitor' => array( - ts('Access CiviMonitor', array('domain' => 'com.aghstrategies.civimonitor')), - ts('Grants the necessary API permissions for a monitoring user without Administer CiviCRM', array('domain' => 'com.aghstrategies.civimonitor')), - ), - ); + $permissions += [ + 'access CiviMonitor' => [ + E::ts('Access CiviMonitor'), + E::ts('Grants the necessary API permissions for a monitoring user without Administer CiviCRM'), + ], + ]; } else { - $permissions += array( - 'access CiviMonitor' => ts('Access CiviMonitor', array('domain' => 'com.aghstrategies.civimonitor')), - ); + $permissions += [ + 'access CiviMonitor' => E::ts('Access CiviMonitor'), + ]; } } diff --git a/docs/img/financial/FinancialAccount.png b/docs/img/financial/FinancialAccount.png new file mode 100644 index 0000000000000000000000000000000000000000..43e3439ac10ca8827f19233482e6ebdd29a1e6cd Binary files /dev/null and b/docs/img/financial/FinancialAccount.png differ diff --git a/docs/security/permissions.md b/docs/security/permissions.md index 884eecef9d2f3f78080b2880fca48db079a114d6..e6edec845a124b6bd80ec5573f7c13bb7aac0f8a 100644 --- a/docs/security/permissions.md +++ b/docs/security/permissions.md @@ -25,7 +25,17 @@ When you write code, you can look at `CRM_Core_Permission::check` to see if the ## API Permissions -Depending on how the API is called, it is either called with a `check_permissions` flag turned off or turned on. When it is turned off, it will run the API without checking if the user has the necessary permissions to perform the action needed. If you turn `check_permissions` on then there will be tests done. By default code in CLI tools e.g. drush or WP-cli or within core code or extension code that is done at run time, the default in CiviCRM APIv3 is that the `check_permissions` flag is turned off. If you call the CiviCRM API through the rest interface then by default the `check_permissions` flag will be turned on. The permissions needed to make various API calls are defined in `CRM_Core_Permission::getEntityActionPermissions()` +Depending on how the API is called, it is either called with a `check_permissions` flag turned on or turned off. When it is turned off, it will run the API call without checking if the user has the necessary permissions to perform the action(s) needed. + +If the API call is made with `check_permissions` turned on then the permissions of the user making the API call will be evaluated to ensure the user has the correct permissions to perform the action(s) they are attempting to. + +The **APIv3** interfaces (JavaScript/PHP API interfaces) used by CLI tools (e.g: drush or WP-cli), CiviCRM Core and extensions by default run with the `check_permissions` flag turned off. + +The **APIv3** rest interface, however, defaults to running with the `check_permissions` flag turned on. + +The permissions required to make various API calls are defined in [`CRM_Core_Permission::getEntityActionPermissions()`](https://lab.civicrm.org/dev/core/blob/master/CRM/Core/Permission.php#L935). + +By default in **APIv4** the `check_permissions` flag is turned on regardless of the API interface being used, for further details see the [API wrapper differences between API v3 and APIv4](/api/v4/differences-with-v3.md#api-wrapper). ## Extending and Implementing Permission Structure {:#extensions} diff --git a/mkdocs.yml b/mkdocs.yml index cb9bacd3ed76a40d4b8eb6a27699c854b8c4a2bb..013f4b09079c829e132106f73d6478b12ab29a05 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -32,7 +32,9 @@ pages: - Release Process: core/release-process.md - Financial: - Overview: financial/overview.md - - OrderAPI: financial/OrderAPI.md + - Order API: financial/orderAPI.md + - Payment API: financial/paymentAPI.md + - Entities: financial/financialentities.md - Extensions: - Basics: extensions/index.md - Packaging Options: extensions/packaging.md @@ -49,16 +51,25 @@ pages: - Creating a Payment Processor: extensions/payment-processors/create.md - CMS-specific development: extensions/cms-specific.md - API: - - APIv3 Intro: api/index.md - - APIv3 Usage: api/usage.md - - APIv3 Actions: api/actions.md - - APIv3 Options: api/options.md - - APIv3 Joins: api/joins.md - - APIv3 Chaining: api/chaining.md - - APIv3 Custom Data: api/custom-data.md - - APIv3 Examples: api/examples.md - - APIv3 Interfaces: api/interfaces.md - - APIv3 Changes: api/changes.md + - API Intro: api/index.md + - API Interfaces: api/interfaces.md + - APIv4: + - APIv4 Usage: api/v4/usage.md + - APIv4 Actions: api/v4/actions.md + - APIv4 Joins: api/v4/joins.md + - APIv4 Chaining: api/v4/chaining.md + - APIv4 Custom Data: api/v4/custom-data.md + - Differences Between Api v3 and v4: api/v4/differences-with-v3.md + - APIv4 Changes: api/v4/changes.md + - APIv3: + - APIv3 Usage: api/v3/usage.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 Changes: api/v3/changes.md - Hooks: - Hooks Introduction: hooks/index.md - Usage: diff --git a/redirects/internal.txt b/redirects/internal.txt index 5dcfe138738a4667660cb0a8b5ad82714a647ed1..f11c6395a3884eaf04f9cc007039f454b561c667 100644 --- a/redirects/internal.txt +++ b/redirects/internal.txt @@ -8,7 +8,15 @@ hooks/hook_civicrm_trigger_info hooks/hook_civicrm_triggerInfo testing/setup testing testing/javascript testing/karma framework/schema-definition framework/database/schema-definition -api/params api/options +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 diff --git a/redirects/wiki-crmdoc.txt b/redirects/wiki-crmdoc.txt index 4639376a63f3aa53a17ab9b244eb09048fc0994a..d171dde554821b9738afa1f48e8835c30b518aef 100644 --- a/redirects/wiki-crmdoc.txt +++ b/redirects/wiki-crmdoc.txt @@ -112,7 +112,7 @@ 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/usage/#smarty +Call+the+CiviCRM+API+from+a+custom+template api/v3/usage/#smarty Using+the+API api Hook+examples hooks Database+hooks hooks @@ -137,7 +137,7 @@ 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/examples +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 @@ -146,16 +146,16 @@ Extension+Reference extensions/info-xml Settings+Reference framework/setting Region+Reference framework/region HTML+Header+Region framework/region#header -Chaining api/chaining +Chaining api/v3/chaining Add-on+Formats extensions/packaging IDE+Settings+to+Meet+Coding+Standards tools/phpstorm -API+changes api/changes +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/usage/#api-security +API+Security api/v3/usage/#api-security UI+Elements+Reference framework/ui Accordions framework/ui Buttons framework/ui @@ -165,7 +165,7 @@ 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/custom-data +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