->addPermissions(['access debug output'])
->addScriptFile('civicrm', 'js/load-bootstrap.js')
->addScriptFile('civicrm', 'bower_components/js-yaml/dist/js-yaml.min.js')
+ ->addScriptFile('civicrm', 'bower_components/marked/marked.min.js')
->addScriptFile('civicrm', 'bower_components/google-code-prettify/bin/prettify.min.js')
->addStyleFile('civicrm', 'bower_components/google-code-prettify/bin/prettify.min.css');
*
* An ACL record consists of:
*
- * - an Operation (e.g. 'View' or 'Edit')
- * - a set of Data that the operation can be performed on (e.g. a group of contacts)
- * - and a Role that has permission to do this operation.
+ * 1. An Operation (e.g. 'View' or 'Edit').
+ * 2. A set of Data that the operation can be performed on (e.g. a group of contacts).
+ * 3. A Role that has permission to do this operation.
*
- * Creating a new ACL requires at minimum a entity table, entity ID and object_table.
+ * Creating a new ACL requires at minimum an entity table, entity ID and object_table.
*
* @see https://docs.civicrm.org/user/en/latest/initial-set-up/permissions-and-access-control
* @package Civi\Api4
}
/**
- * Checks that really ought to be taken care of by Civi::settings
+ * Checks that really ought to be taken care of by `Civi::settings`.
*
* @param int $domain
* @return array
*
* Each action takes the name of the custom group as a parameter, or in traditional syntax the entity is prefixed with 'Custom_'
*
- * Ex. OOP: \Civi\Api4\CustomValue::get('MyStuff')->addWhere('id', '=', 123)
- * Non-OOP: civicrm_api4('Custom_MyStuff', 'get', ['where' => [['id', '=', 123]]]);
+ * **Ex. OOP:** `\Civi\Api4\CustomValue::get('MyStuff')->addWhere('id', '=', 123);`
+ * **Non-OOP:** `civicrm_api4('Custom_MyStuff', 'get', ['where' => [['id', '=', 123]]]);`
*
* Note: This class does NOT extend AbstractEntity so it doesn't get mistaken for a "real" entity.
* @package Civi\Api4
*
* Keys can be any string - this will be the name given to the output.
*
- * You can reference other values in the api results in this call by prefixing them with $
+ * You can reference other values in the api results in this call by prefixing them with `$`.
*
* For example, you could create a contact and place them in a group by chaining the
- * GroupContact api to the Contact api:
+ * `GroupContact` api to the `Contact` api:
*
+ * ```php
* Contact::create()
* ->setValue('first_name', 'Hello')
- * ->addChain('add_to_a_group', GroupContact::create()->setValue('contact_id', '$id')->setValue('group_id', 123))
+ * ->addChain('add_a_group', GroupContact::create()
+ * ->setValue('contact_id', '$id')
+ * ->setValue('group_id', 123)
+ * )
+ * ```
*
- * This will substitute the id of the newly created contact with $id.
+ * This will substitute the id of the newly created contact with `$id`.
*
* @var array
*/
/**
* Add debugging info to the api result.
*
- * When enabled, the $result->debug will be populated with information about the api call,
+ * When enabled, `$result->debug` will be populated with information about the api call,
* including sql queries executed.
*
- * Note: with checkPermissions enabled, debug info will only be returned if the user has "view debug output" permission.
+ * **Note:** with checkPermissions enabled, debug info will only be returned if the user has "view debug output" permission.
*
* @var bool
*/
* @param string $name
* Unique name for this chained request
* @param \Civi\Api4\Generic\AbstractAction $apiRequest
- * @param string|int $index
- * Either a string for how the results should be indexed e.g. 'name'
- * or the index of a single result to return e.g. 0 for the first result.
+ * @param string|int|array $index
+ * See `civicrm_api4()` for documentation of `$index` param
* @return $this
*/
public function addChain($name, AbstractAction $apiRequest, $index = NULL) {
abstract class AbstractGetAction extends AbstractQueryAction {
/**
- * Fields to return. Defaults to all fields ["*"].
+ * Fields to return. Defaults to all fields `["*"]`.
*
* Use the * wildcard by itself to select all available fields, or use it to match similarly-named fields.
- * E.g. "is_*" will match fields named is_primary, is_active, etc.
+ * E.g. `is_*` will match fields named is_primary, is_active, etc.
*
- * Set to ["row_count"] to return only the number of items found.
+ * Set to `["row_count"]` to return only the number of items found.
*
* @var array
*/
*
* Ex: If getRecords fetches a long list of items each with a unique name,
* but the user has specified a single record to retrieve, you can optimize the call
- * by checking $this->_itemsToGet('name') and only fetching the item(s) with that name.
+ * by checking `$this->_itemsToGet('name')` and only fetching the item(s) with that name.
*
* @param string $field
* @return array|null
use Traits\DAOActionTrait;
/**
- * Fields to return. Defaults to all non-custom fields ["*"].
+ * Fields to return. Defaults to all non-custom fields `["*"]`.
*
- * Use the dot notation to perform joins in the select clause, e.g. selecting ["*", "contact.*"] from Email.get
+ * Use the dot notation to perform joins in the select clause, e.g. selecting `["*", "contact.*"]` from `Email::get()`
* will select all fields for the email + all fields for the related contact.
*
* @var array
if (!$num || strpos($line, '*/') !== FALSE) {
continue;
}
- $line = preg_replace('/[ ]+/', ' ', ltrim(trim($line), '* '));
- if (strpos($line, '@') === 0) {
- $words = explode(' ', $line);
- $key = substr(array_shift($words), 1);
+ $line = ltrim(trim($line), '*');
+ if (strlen($line) && $line[0] === ' ') {
+ $line = substr($line, 1);
+ }
+ if (strpos(ltrim($line), '@') === 0) {
+ $words = explode(' ', ltrim($line, ' @'));
+ $key = array_shift($words);
$param = NULL;
if ($key == 'var') {
$info['type'] = explode('|', $words[0]);
<h3 class="panel-title" crm-icon="fa-info-circle">{{ helpTitle }}</h3>
</div>
<div class="panel-body">
- <h4>{{ helpContent.description }}</h4>
- <div ng-if="helpContent.comment">
- <div ng-repeat='text in helpContent.comment.split("\n\n")'>
- <p ng-if="text[0] !== '-' && text[0] !== '*'">{{ text }}</p>
- <ul ng-if="text[0] === '-' || text[0] === '*'">
- <li ng-repeat='item in text.split("\n")'>{{ item.substr(1) }}</li>
- </ul>
- </div>
- </div>
+ <h4 ng-bind-html="helpContent.description"></h4>
+ <div ng-bind-html="helpContent.comment"></div>
<p ng-repeat="(key, item) in helpContent" ng-if="key !== 'description' && key !== 'comment' && key !== 'see'">
<strong>{{ key }}:</strong> {{ item }}
</p>
$scope.perm = {
accessDebugOutput: CRM.checkPerm('access debug output')
};
+ marked.setOptions({highlight: prettyPrintOne});
var getMetaParams = {},
objectParams = {orderBy: 'ASC', values: '', chain: ['Entity', '', '{}']},
docs = CRM.vars.api4.docs,
return fields;
}
- $scope.help = function(title, param) {
- if (!param) {
+ $scope.help = function(title, content) {
+ if (!content) {
$scope.helpTitle = helpTitle;
$scope.helpContent = helpContent;
} else {
$scope.helpTitle = title;
- $scope.helpContent = param;
+ $scope.helpContent = convertMarkdown(content);
}
};
+ // Sets the static help text (which gets overridden by mousing over other elements)
+ function setHelp(title, content) {
+ $scope.helpTitle = helpTitle = title;
+ $scope.helpContent = helpContent = convertMarkdown(content);
+ }
+
+ function convertMarkdown(rawContent) {
+ var formatted = _.cloneDeep(rawContent);
+ if (formatted.description) {
+ formatted.description = marked(formatted.description);
+ }
+ if (formatted.comment) {
+ formatted.comment = marked(formatted.comment);
+ }
+ return formatted;
+ }
+
// Format the href for a @see help annotation
$scope.formatRef = function(see) {
var match = see.match(/^\\Civi\\Api4\\([a-zA-Z]+)$/);
// Help for an entity with no action selected
function showEntityHelp(entityName) {
var entityInfo = getEntity(entityName);
- $scope.helpTitle = helpTitle = $scope.entity;
- $scope.helpContent = helpContent = {
+ setHelp($scope.entity, {
description: entityInfo.description,
comment: entityInfo.comment,
see: entityInfo.see
- };
+ });
}
if (!$scope.entity) {
- $scope.helpTitle = helpTitle = ts('APIv4 Explorer');
- $scope.helpContent = helpContent = {description: docs.description, comment: docs.comment, see: docs.see};
+ setHelp(ts('APIv4 Explorer'), {description: docs.description, comment: docs.comment, see: docs.see});
} else if (!actions.length && !getEntity().actions) {
getMetaParams.actions = [$scope.entity, 'getActions', {chain: {fields: [$scope.entity, 'getFields', {action: '$name'}]}}];
fetchMeta();
if ($scope.entity && $routeParams.api4action !== newVal && !_.isUndefined(newVal)) {
$location.url('/explorer/' + $scope.entity + '/' + newVal);
} else if (newVal) {
- $scope.helpTitle = helpTitle = $scope.entity + '::' + newVal;
- $scope.helpContent = helpContent = _.pick(_.findWhere(getEntity().actions, {name: newVal}), ['description', 'comment', 'see']);
+ setHelp($scope.entity + '::' + newVal, _.pick(_.findWhere(getEntity().actions, {name: newVal}), ['description', 'comment', 'see']));
}
});
* @see https://docs.civicrm.org/dev/en/latest/api/v4/usage/
*
* @param string $entity Name of the CiviCRM entity to access.
- * All entity names are capitalized CamelCase, e.g. "ContributionPage".
- * Most entities correspond to a database table (e.g. "Contact" is the table "civicrm_contact").
- * For a complete list of available entities, call civicrm_api4('Entity', 'get');
+ * All entity names are capitalized CamelCase, e.g. `ContributionPage`.
+ * Most entities correspond to a database table (e.g. `Contact` is the table `civicrm_contact`).
+ * For a complete list of available entities, call `civicrm_api4('Entity', 'get');`
*
* @param string $action The "verb" of the api call.
- * For a complete list of actions for a given entity (e.g. Contact), call civicrm_api4('Contact', 'getActions');
+ * For a complete list of actions for a given entity (e.g. `Contact`), call `civicrm_api4('Contact', 'getActions');`
*
* @param array $params An array of API input keyed by parameter name.
* The easiest way to discover all available parameters is to visit the API Explorer on your CiviCRM site.
* @param string|int|array $index Controls the Result array format.
* By default the api Result contains a non-associative array of data. Passing an $index tells the api to
* automatically reformat the array, depending on the variable type passed:
- *
- * - Integer: return a single result array; e.g. index = 0 will return the first result, 1 will return the second, and -1 will return the last.
- * - String: index the results by a field value; e.g. index = "name" will return an associative array with the field 'name' as keys.
- * - Non-associative array: return a single value from each result; e.g. index = ['title'] will return a non-associative array of strings - the 'title' field from each result.
- * - Associative array: a combination of the previous two modes; e.g. index = ['name' => 'title'] will return an array of strings - the 'title' field keyed by the 'name' field.
+ * - **Integer:** return a single result array;
+ * e.g. `$index = 0` will return the first result, 1 will return the second, and -1 will return the last.
+ * - **String:** index the results by a field value;
+ * e.g. `$index = "name"` will return an associative array with the field 'name' as keys.
+ * - **Non-associative array:** return a single value from each result;
+ * e.g. `$index = ['title']` will return a non-associative array of strings - the 'title' field from each result.
+ * - **Associative array:** a combination of the previous two modes;
+ * e.g. `$index = ['name' => 'title']` will return an array of strings - the 'title' field keyed by the 'name' field.
*
* @return \Civi\Api4\Generic\Result
* @throws \API_Exception
"url": "https://github.com/FortAwesome/Font-Awesome/archive/v4.7.0.zip",
"ignore": ["*/.*", "*.json", "src", "*.yml", "Gemfile", "Gemfile.lock", "*.md"]
},
+ "marked": {
+ "url": "https://github.com/markedjs/marked/archive/v0.8.0.zip",
+ "ignore": [".*", "*.json", "*.md", "Makefile", "*/*"]
+ },
"google-code-prettify": {
"url": "https://github.com/tcollard/google-code-prettify/archive/v1.0.5.zip",
"ignore": ["closure-compiler", "js-modules", "tests", "yui-compressor", "Makefile"]
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "b3fb18d6fdb3244cc94be8eaa883b7ae",
+ "content-hash": "36eeb97f14e2af530920b89c59124de3",
"packages": [
{
"name": "civicrm/civicrm-cxn-rpc",
'$foo' => [
'type' => ['int', 'string'],
'description' => '',
- 'comment' => "Nothing interesting.\n",
+ 'comment' => " Nothing interesting.\n",
],
'$bar' => [
'type' => NULL,