/**
* Add a JavaScript file to the current page using <SCRIPT SRC>.
*
+ * Ex: addScript('alert("Hello world");', ['weight' => 123]);
+ *
* @param string $code
* JavaScript source code.
* @param array $options
- * Open-ended list of options (per add())
- * Ex: ['weight' => 123]
+ * Open-ended list of key-value options. See CollectionInterface docs.
+ * Positional equivalence: addScript(string $code, int $weight, string $region).
* @return static
+ * @see CRM_Core_Resources_CollectionInterface
*/
public function addScript(string $code, ...$options);
/**
* Add a JavaScript file to the current page using <SCRIPT SRC>.
*
- * Options may be use key-value format (preferred) or positional format (legacy).
- *
- * - addScriptFile('myext', 'my.js', ['weight' => 123, 'region' => 'page-footer'])
- * - addScriptFile('myext', 'my.js', 123, 'page-footer')
+ * Ex: addScriptFile('myextension', 'myscript.js', ['weight' => 123]);
*
* @param string $ext
- * extension name; use 'civicrm' for core.
+ * Extension name; use 'civicrm' for core.
* @param string $file
- * file path -- relative to the extension base dir.
+ * File path -- relative to the extension base dir.
* @param array $options
- * Open-ended list of options (per add()).
- * Ex: ['weight' => 123]
- * Accepts some additional options:
- * - bool|string $translate: Whether to load translated strings for this file. Use one of:
- * - FALSE: Do not load translated strings.
- * - TRUE: Load translated strings. Use the $ext's default domain.
- * - string: Load translated strings. Use a specific domain.
- *
+ * Open-ended list of key-value options. See CollectionInterface docs.
+ * Positional equivalence: addScriptFile(string $code, int $weight, string $region, mixed $translate).
* @return static
- *
- * @throws \CRM_Core_Exception
+ * @see CRM_Core_Resources_CollectionInterface
*/
public function addScriptFile(string $ext, string $file, ...$options);
/**
- * Add a JavaScript file to the current page using <SCRIPT SRC>.
+ * Add a JavaScript URL to the current page using <SCRIPT SRC>.
*
- * Options may be use key-value format (preferred) or positional format (legacy).
- *
- * - addScriptUrl('http://example.com/foo.js', ['weight' => 123, 'region' => 'page-footer'])
- * - addScriptUrl('http://example.com/foo.js', 123, 'page-footer')
+ * Ex: addScriptUrl('http://example.com/foo.js', ['weight' => 123])
*
* @param string $url
* @param array $options
- * Open-ended list of options (per add())
+ * Open-ended list of key-value options. See CollectionInterface docs.
+ * Positional equivalence: addScriptUrl(string $url, int $weight, string $region).
* @return static
+ * @see CRM_Core_Resources_CollectionInterface
*/
public function addScriptUrl(string $url, ...$options);
/**
* Add a CSS content to the current page using <STYLE>.
*
+ * Ex: addStyle('p { color: red; }', ['weight' => 100]);
+ *
* @param string $code
* CSS source code.
* @param array $options
- * Open-ended list of options (per add())
- * Ex: ['weight' => 123]
+ * Open-ended list of key-value options. See CollectionInterface docs.
+ * Positional equivalence: addStyle(string $code, int $weight, string $region).
* @return static
+ * @see CRM_Core_Resources_CollectionInterface
*/
public function addStyle(string $code, ...$options);
/**
* Add a CSS file to the current page using <LINK HREF>.
*
+ * Ex: addStyleFile('myextension', 'mystyles.css', ['weight' => 100]);
+ *
* @param string $ext
- * extension name; use 'civicrm' for core.
+ * Extension name; use 'civicrm' for core.
* @param string $file
- * file path -- relative to the extension base dir.
+ * File path -- relative to the extension base dir.
* @param array $options
- * Open-ended list of options (per add())
- * Ex: ['weight' => 123]
+ * Open-ended list of key-value options. See CollectionInterface docs.
+ * Positional equivalence: addStyle(string $code, int $weight, string $region).
* @return static
+ * @see CRM_Core_Resources_CollectionInterface
*/
public function addStyleFile(string $ext, string $file, ...$options);
/**
* Add a CSS file to the current page using <LINK HREF>.
*
+ * Ex: addStyleUrl('http://example.com/foo.css', ['weight' => 100]);
+ *
* @param string $url
* @param array $options
- * Open-ended list of options (per add())
- * Ex: ['weight' => 123]
+ * Open-ended list of key-value options. See CollectionInterface docs.
+ * Positional equivalence: addStyleUrl(string $code, int $weight, string $region).
* @return static
+ * @see CRM_Core_Resources_CollectionInterface
*/
public function addStyleUrl(string $url, ...$options);
* Add JavaScript variables to CRM.vars
*
* Example:
- * From the server:
- * CRM_Core_Resources::singleton()->addVars('myNamespace', array('foo' => 'bar'));
- * Access var from javascript:
- * CRM.vars.myNamespace.foo // "bar"
+ * From the server:
+ * CRM_Core_Resources::singleton()->addVars('myNamespace', array('foo' => 'bar'));
+ * Access var from javascript:
+ * CRM.vars.myNamespace.foo // "bar"
*
* @see https://docs.civicrm.org/dev/en/latest/standards/javascript/
*
* @param array $vars
* Data to export.
* @param array $options
- * Extra processing instructions on where/how to place the data.
+ * Open-ended list of key-value options. See CollectionInterface docs.
+ * Positional equivalence: addVars(string $namespace, array $vars, string $region).
* @return static
+ * @see CRM_Core_Resources_CollectionInterface
*/
public function addVars(string $nameSpace, array $vars, ...$options);
* @param array $settings
* Data to export.
* @param array $options
- * Extra processing instructions on where/how to place the data.
+ * Not used.
+ * Positional equivalence: addSetting(array $settings, string $region).
* @return static
+ * @see CRM_Core_Resources_CollectionInterface
+ * @see CRM_Core_Resources_CollectionAdderInterface::addSetting()
*/
public function addSetting(array $settings, ...$options);
/**
* Class CRM_Core_Resources_CollectionTrait
*
- * This is a building-block for creating classes which maintain a list of resources.
- *
- * The class is generally organized in two sections: First, we have core
- * bit that manages a list of '$snippets'. Second, we have a set of helper
- * functions which add some syntactic sugar for the snippets.
+ * This trait is a building-block for creating classes which maintain a list of
+ * resources. It defines a set of helper functions which provide syntactic sugar
+ * for calling the add() method.
*/
trait CRM_Core_Resources_CollectionAdderTrait {
* @return array
* The full/computed snippet (with defaults applied).
* @see CRM_Core_Resources_CollectionInterface::add()
+ * @see CRM_Core_Resources_CollectionTrait::add()
*/
abstract public function add($snippet);
*
* @param array $options
* @return array
+ * @see CRM_Core_Resources_CollectionTrait::findCreateSettingSnippet()
*/
abstract protected function &findCreateSettingSnippet($options = []): array;
/**
* Export permission data to the client to enable smarter GUIs.
*
- * Note: Application security stems from the server's enforcement
- * of the security logic (e.g. in the API permissions). There's no way
- * the client can use this info to make the app more secure; however,
- * it can produce a better-tuned (non-broken) UI.
- *
* @param string|iterable $permNames
* List of permission names to check/export.
* @return static
+ * @see CRM_Core_Resources_CollectionAdderInterface::addPermissions()
*/
public function addPermissions($permNames) {
// TODO: Maybe this should be its own resource type to allow smarter management?
/**
* Add a JavaScript file to the current page using <SCRIPT SRC>.
*
+ * Ex: addScript('alert("Hello world");', ['weight' => 123]);
+ *
* @param string $code
* JavaScript source code.
* @param array $options
- * Open-ended list of options (per add())
- * Ex: ['weight' => 123]
+ * Open-ended list of key-value options. See CollectionInterface docs.
+ * Positional equivalence: addScript(string $code, int $weight, string $region).
* @return static
+ * @see CRM_Core_Resources_CollectionInterface
+ * @see CRM_Core_Resources_CollectionAdderInterface::addScript()
*/
public function addScript(string $code, ...$options) {
$this->add(self::mergeStandardOptions($options, [
/**
* Add a JavaScript file to the current page using <SCRIPT SRC>.
*
- * Options may be use key-value format (preferred) or positional format (legacy).
- *
- * - addScriptFile('myext', 'my.js', ['weight' => 123, 'region' => 'page-footer'])
- * - addScriptFile('myext', 'my.js', 123, 'page-footer')
+ * Ex: addScriptFile('myextension', 'myscript.js', ['weight' => 123]);
*
* @param string $ext
- * extension name; use 'civicrm' for core.
+ * Extension name; use 'civicrm' for core.
* @param string $file
- * file path -- relative to the extension base dir.
+ * File path -- relative to the extension base dir.
* @param array $options
- * Open-ended list of options (per add()).
- * Ex: ['weight' => 123]
- * Accepts some additional options:
- * - bool|string $translate: Whether to load translated strings for this file. Use one of:
- * - FALSE: Do not load translated strings.
- * - TRUE: Load translated strings. Use the $ext's default domain.
- * - string: Load translated strings. Use a specific domain.
- *
+ * Open-ended list of key-value options. See CollectionInterface docs.
+ * Positional equivalence: addScriptFile(string $code, int $weight, string $region, mixed $translate).
* @return static
- *
- * @throws \CRM_Core_Exception
+ * @see CRM_Core_Resources_CollectionInterface
+ * @see CRM_Core_Resources_CollectionAdderInterface::addScriptFile()
*/
public function addScriptFile(string $ext, string $file, ...$options) {
$this->add(self::mergeStandardOptions($options, [
}
/**
- * Add a JavaScript file to the current page using <SCRIPT SRC>.
- *
- * Options may be use key-value format (preferred) or positional format (legacy).
+ * Add a JavaScript URL to the current page using <SCRIPT SRC>.
*
- * - addScriptUrl('http://example.com/foo.js', ['weight' => 123, 'region' => 'page-footer'])
- * - addScriptUrl('http://example.com/foo.js', 123, 'page-footer')
+ * Ex: addScriptUrl('http://example.com/foo.js', ['weight' => 123])
*
* @param string $url
* @param array $options
- * Open-ended list of options (per add())
+ * Open-ended list of key-value options. See CollectionInterface docs.
+ * Positional equivalence: addScriptUrl(string $url, int $weight, string $region).
* @return static
+ * @see CRM_Core_Resources_CollectionInterface
+ * @see CRM_Core_Resources_CollectionAdderInterface::addScriptUrl()
*/
public function addScriptUrl(string $url, ...$options) {
$this->add(self::mergeStandardOptions($options, [
* @param string|array $text
* @param string|null $domain
* @return static
+ * @see CRM_Core_Resources_CollectionAdderInterface::addString()
*/
public function addString($text, $domain = 'civicrm') {
// TODO: Maybe this should be its own resource type to allow smarter management?
/**
* Add a CSS content to the current page using <STYLE>.
*
+ * Ex: addStyle('p { color: red; }', ['weight' => 100]);
+ *
* @param string $code
* CSS source code.
* @param array $options
- * Open-ended list of options (per add())
- * Ex: ['weight' => 123]
+ * Open-ended list of key-value options. See CollectionInterface docs.
+ * Positional equivalence: addStyle(string $code, int $weight, string $region).
* @return static
+ * @see CRM_Core_Resources_CollectionInterface
+ * @see CRM_Core_Resources_CollectionAdderInterface::addStyle()
*/
public function addStyle(string $code, ...$options) {
$this->add(self::mergeStandardOptions($options, [
/**
* Add a CSS file to the current page using <LINK HREF>.
*
+ * Ex: addStyleFile('myextension', 'mystyles.css', ['weight' => 100]);
+ *
* @param string $ext
- * extension name; use 'civicrm' for core.
+ * Extension name; use 'civicrm' for core.
* @param string $file
- * file path -- relative to the extension base dir.
+ * File path -- relative to the extension base dir.
* @param array $options
- * Open-ended list of options (per add())
- * Ex: ['weight' => 123]
+ * Open-ended list of key-value options. See CollectionInterface docs.
+ * Positional equivalence: addStyle(string $code, int $weight, string $region).
* @return static
+ * @see CRM_Core_Resources_CollectionInterface
+ * @see CRM_Core_Resources_CollectionAdderInterface::addStyleFile()
*/
public function addStyleFile(string $ext, string $file, ...$options) {
$this->add(self::mergeStandardOptions($options, [
/**
* Add a CSS file to the current page using <LINK HREF>.
*
+ * Ex: addStyleUrl('http://example.com/foo.css', ['weight' => 100]);
+ *
* @param string $url
* @param array $options
- * Open-ended list of options (per add())
- * Ex: ['weight' => 123]
+ * Open-ended list of key-value options. See CollectionInterface docs.
+ * Positional equivalence: addStyleUrl(string $code, int $weight, string $region).
* @return static
+ * @see CRM_Core_Resources_CollectionInterface
+ * @see CRM_Core_Resources_CollectionAdderInterface::addStyleUrl()
*/
public function addStyleUrl(string $url, ...$options) {
$this->add(self::mergeStandardOptions($options, [
* @param array $settings
* Data to export.
* @param array $options
- * Extra processing instructions on where/how to place the data.
+ * Not used.
+ * Positional equivalence: addSetting(array $settings, string $region).
* @return static
+ * @see CRM_Core_Resources_CollectionInterface
+ * @see CRM_Core_Resources_CollectionAdderInterface::addSetting()
*/
public function addSetting(array $settings, ...$options) {
$s = &$this->findCreateSettingSnippet($options);
*
* @param callable $callable
* @return static
+ * @see CRM_Core_Resources_CollectionAdderInterface::addSettingsFactory()
*/
public function addSettingsFactory($callable) {
$s = &$this->findCreateSettingSnippet();
* @param string $nameSpace
* Usually the name of your extension.
* @param array $vars
+ * Data to export.
* @param array $options
- * There are no supported options.
+ * Open-ended list of key-value options. See CollectionInterface docs.
+ * Positional equivalence: addVars(string $namespace, array $vars, string $region).
* @return static
+ * @see CRM_Core_Resources_CollectionInterface
+ * @see CRM_Core_Resources_CollectionAdderInterface::addVars()
*/
public function addVars(string $nameSpace, array $vars, ...$options) {
$s = &$this->findCreateSettingSnippet($options);
/**
* Class CRM_Core_Resources_CollectionInterface
*
- * This is a building-block for creating classes which maintain a list of resources.
+ * A resource collection is a mix of *resources* (or *snippets* or *assets*) that can be
+ * added to a page. A fully-formed resource might look like this:
+ *
+ * ```
+ * array(
+ * 'name' => 'jQuery',
+ * 'region' => 'html-header',
+ * 'weight' => 100,
+ * 'type' => 'scriptUrl',
+ * 'scriptUrl' => 'https://example.com/js/jquery.min.js'
+ * )
+ * ```
+ *
+ * Typically, a resource is created with just one option, eg
+ *
+ * ```
+ * // Add resources in array notation
+ * $c->add(['script' => 'alert("Hello");']);
+ * $c->add(['scriptFile' => ['civicrm', 'js/crm.ckeditor.js']]);
+ * $c->add(['scriptUrl' => 'https://example.com/js/jquery.min.js']);
+ * $c->add(['style' => 'p { font-size: 4em; }']);
+ * $c->add(['styleFile' => ['civicrm', 'css/dashboard.css']]);
+ * $c->add(['styleUrl' => 'https://example.com/css/foobar.css']);
+ *
+ * // Add resources with helper methods
+ * $c->addScript('alert("Hello");');
+ * $c->addScriptFile('civicrm', 'js/crm.ckeditor.js');
+ * $c->addScriptUrl('https://example.com/js/jquery.min.js');
+ * $c->addStyle('p { font-size: 4em; }');
+ * $c->addStyleFile('civicrm', 'css/dashboard.css');
+ * $c->addStyleUrl('https://example.com/css/foobar.css');
+ * ```
+ *
+ * The other properties are automatically computed (dependent upon context),
+ * but they may be set explicitly. These options include:
+ *
+ * - type: string (markup, template, callback, script, scriptFile, scriptUrl, jquery, style, styleFile, styleUrl)
+ * - name: string, symbolic identifier for this resource
+ * - weight: int, default=1. Lower weights come before higher weights.
+ * (If two resources have the same weight, then a secondary ordering will be
+ * used to ensure reproducibility. However, the secondary ordering is
+ * not guaranteed among versions/implementations.)
+ * - disabled: int, default=0
+ * - region: string
+ * - translate: bool|string, Autoload translations. (Only applies to 'scriptFile')
+ * - FALSE: Do not load translated strings.
+ * - TRUE: Load translated strings. Use the $ext's default domain.
+ * - string: Load translated strings. Use a specific domain.
+ *
+ * For example, the following are equivalent ways to set the 'weight' option:
+ *
+ * ```php
+ * $c->add([
+ * 'script' => 'alert("Hello");',
+ * 'weight' => 100,
+ * ]);
+ * $c->addScript('alert("Hello");', ['weight' => 100]);
+ * ```
+ *
+ * Passing options in array (key-value) notation is clearest. For backward
+ * compatibility, some methods (eg `addScript()`) accept options in positional form.
+ * Where applicable, the docblock of each `addFoo()` will include a comment about positional form.
*/
interface CRM_Core_Resources_CollectionInterface {
/**
* Add an item to the collection. For example, when working with 'page-header' collection:
*
- * ```
- * CRM_Core_Region::instance('page-header')->add(array(
- * 'markup' => '<div style="color:red">Hello!</div>',
- * ));
- * CRM_Core_Region::instance('page-header')->add(array(
- * 'script' => 'alert("Hello");',
- * ));
- * CRM_Core_Region::instance('page-header')->add(array(
- * 'template' => 'CRM/Myextension/Extra.tpl',
- * ));
- * CRM_Core_Region::instance('page-header')->add(array(
- * 'callback' => 'myextension_callback_function',
- * ));
- * ```
- *
* Note: This function does not perform any extra encoding of markup, script code, or etc. If
* you're passing in user-data, you must clean it yourself.
*
* @param array $snippet
- * Array; keys:.
- * - type: string (auto-detected for markup, template, callback, script, scriptFile, scriptUrl, jquery, style, styleFile, styleUrl)
- * - name: string, optional
- * - weight: int, optional; default=1
- * - disabled: int, optional; default=0
- * - markup: string, HTML; required (for type==markup)
- * - template: string, path; required (for type==template)
- * - callback: mixed; required (for type==callback)
- * - arguments: array, optional (for type==callback)
- * - script: string, Javascript code
- * - scriptFile: array, the name of the extension and file. Ex: ['civicrm', 'js/foo.js']
- * - scriptUrl: string, URL of a Javascript file
- * - jquery: string, Javascript code which runs inside a jQuery(function($){...}); block
- * - settings: array, list of static values to convey.
- * - style: string, CSS code
- * - styleFile: array, the name of the extension and file. Ex: ['civicrm', 'js/foo.js']
- * - styleUrl: string, URL of a CSS file
- *
+ * The resource to add. For a full list of properties, see CRM_Core_Resources_CollectionInterface.
* @return array
* The full/computed snippet (with defaults applied).
+ * @see CRM_Core_Resources_CollectionInterface
*/
public function add($snippet);
* Ex: $region->update('default', ['disabled' => TRUE]);
*
* @param string $name
- * @param $snippet
+ * Symbolic of the resource/snippet to update.
+ * @param array $snippet
+ * Resource options. See CollectionInterface docs.
* @return static
*/
public function update($name, $snippet);
protected $types = [];
/**
- * Add an item to the collection. For example, when working with 'page-header' collection:
- *
- * ```
- * CRM_Core_Region::instance('page-header')->add(array(
- * 'markup' => '<div style="color:red">Hello!</div>',
- * ));
- * CRM_Core_Region::instance('page-header')->add(array(
- * 'script' => 'alert("Hello");',
- * ));
- * CRM_Core_Region::instance('page-header')->add(array(
- * 'template' => 'CRM/Myextension/Extra.tpl',
- * ));
- * CRM_Core_Region::instance('page-header')->add(array(
- * 'callback' => 'myextension_callback_function',
- * ));
- * ```
- *
- * Note: This function does not perform any extra encoding of markup, script code, or etc. If
- * you're passing in user-data, you must clean it yourself.
+ * Add an item to the collection.
*
* @param array $snippet
- * Array; keys:.
- * - type: string (auto-detected for markup, template, callback, script, scriptUrl, jquery, style, styleUrl)
- * - name: string, optional
- * - weight: int, optional; default=1
- * - disabled: int, optional; default=0
- * - markup: string, HTML; required (for type==markup)
- * - template: string, path; required (for type==template)
- * - callback: mixed; required (for type==callback)
- * - arguments: array, optional (for type==callback)
- * - script: string, Javascript code
- * - scriptUrl: string, URL of a Javascript file
- * - jquery: string, Javascript code which runs inside a jQuery(function($){...}); block
- * - settings: array, list of static values to convey.
- * - style: string, CSS code
- * - styleUrl: string, URL of a CSS file
- *
+ * Resource options. See CollectionInterface docs.
* @return array
* The full/computed snippet (with defaults applied).
+ * @see CRM_Core_Resources_CollectionInterface
+ * @see CRM_Core_Resources_CollectionInterface::add()
*/
public function add($snippet) {
$snippet = array_merge($this->defaults, $snippet);
}
/**
+ * Update specific properties of a snippet.
+ *
* @param string $name
- * @param $snippet
+ * Symbolic of the resource/snippet to update.
+ * @param array $snippet
+ * Resource options. See CollectionInterface docs.
+ * @return static
+ * @see CRM_Core_Resources_CollectionInterface::update()
*/
public function update($name, $snippet) {
$this->snippets[$name] = array_merge($this->snippets[$name], $snippet);
$this->isSorted = FALSE;
+ return $this;
}
/**
* Remove all snippets.
*
* @return static
+ * @see CRM_Core_Resources_CollectionInterface::clear()
*/
public function clear() {
$this->snippets = [];
*
* @param string $name
* @return array|NULL
+ * @see CRM_Core_Resources_CollectionInterface::get()
*/
public function &get($name) {
return $this->snippets[$name];
* Get a list of all snippets in this collection.
*
* @return iterable
+ * @see CRM_Core_Resources_CollectionInterface::getAll()
*/
public function getAll(): iterable {
$this->sort();
* - FALSE: The item is not OK and should be omitted from the collection.
* - Array: The item should be revised (using the returned value).
* @return static
+ * @see CRM_Core_Resources_CollectionInterface::filter()
*/
public function filter($callback) {
$this->sort();
* Find all snippets which match the given criterion.
*
* @param callable $callback
+ * The callback is invoked once for each member in the collection.
+ * The callback may return one of three values:
+ * - TRUE: The item is OK and belongs in the collection.
+ * - FALSE: The item is not OK and should be omitted from the collection.
* @return iterable
* List of matching snippets.
+ * @see CRM_Core_Resources_CollectionInterface::find()
*/
public function find($callback): iterable {
$r = [];