- <?php
- * @file
- * Backdrop placeholder/token replacement system.
- *
- * API functions for replacing placeholders in text with meaningful values.
- *
- * For example: When configuring automated emails, an administrator enters
- * standard text for the email. Variables like the title of a node and the date
- * the email was sent can be entered as placeholders like [node:title] and
- * [date:short]. When a Backdrop module prepares to send the email, it can call
- * the token_replace() function, passing in the text. The token system will
- * scan the text for placeholder tokens, give other modules an opportunity to
- * replace them with meaningful text, then return the final product to the
- * original module.
- *
- * Tokens follow the form: [$type:$name], where $type is a general class of
- * tokens like 'node', 'user', or 'comment' and $name is the name of a given
- * placeholder. For example, [node:title] or [node:created:since].
- *
- * In addition to raw text containing placeholders, modules may pass in an array
- * of objects to be used when performing the replacement. The objects should be
- * keyed by the token type they correspond to. For example:
- *
- * @code
- * // Load a node and a user, then replace tokens in the text.
- * $text = 'On [date:short], [user:name] read [node:title].';
- * $node = node_load(1);
- * $user = user_load(1);
- *
- * // [date:...] tokens use the current date automatically.
- * $data = array('node' => $node, 'user' => $user);
- * return token_replace($text, $data);
- * @endcode
- *
- * Some tokens may be chained in the form of [$type:$pointer:$name], where $type
- * is a normal token type, $pointer is a reference to another token type, and
- * $name is the name of a given placeholder. For example, [node:author:mail]. In
- * that example, 'author' is a pointer to the 'user' account that created the
- * node, and 'mail' is a placeholder available for any 'user'.
- *
- * @see token_replace()
- * @see hook_tokens()
- * @see hook_token_info()
- */
-
- * Replaces all tokens in a given string with appropriate values.
- *
- * @param string $text
- * A string potentially containing replaceable tokens.
- * @param array $data
- * (optional) An array of keyed objects. For simple replacement scenarios
- * 'node', 'user', and others are common keys, with an accompanying node or
- * user object being the value. Some token types, like 'site', do not require
- * any explicit information from $data and can be replaced even if it is
- * empty.
- * @param array $options
- * (optional) A keyed array of settings and flags to control the token
- * replacement process. Supported options are:
- * - language: A language object to be used when generating locale-sensitive
- * tokens.
- * - callback: A callback function that will be used to post-process the array
- * of token replacements after they are generated. For example, a module
- * using tokens in a text-only email might provide a callback to strip HTML
- * entities from token values before they are inserted into the final text.
- * - clear: A boolean flag indicating that tokens should be removed from the
- * final text if no replacement value can be generated.
- * - sanitize: A boolean flag indicating that tokens should be sanitized for
- * display to a web browser. Defaults to TRUE. Developers who set this
- * option to FALSE assume responsibility for running filter_xss(),
- * check_plain() or other appropriate scrubbing functions before displaying
- * data to users.
- *
- * @return
- * Text with tokens replaced.
- */
- function token_replace($text, array $data = array(), array $options = array()) {
- $text_tokens = token_scan($text);
- if (empty($text_tokens)) {
- return $text;
- }
-
- $replacements = array();
- foreach ($text_tokens as $type => $tokens) {
- $replacements += token_generate($type, $tokens, $data, $options);
- if (!empty($options['clear'])) {
- $replacements += array_fill_keys($tokens, '');
- }
- }
-
-
- if (!empty($options['callback'])) {
- $function = $options['callback'];
- $function($replacements, $data, $options);
- }
-
- $tokens = array_keys($replacements);
- $values = array_values($replacements);
-
- return str_replace($tokens, $values, $text);
- }
-
- * Builds a list of all token-like patterns that appear in the text.
- *
- * @param string $text
- * The text to be scanned for possible tokens.
- *
- * @return array
- * An associative array of discovered tokens, grouped by type.
- */
- function token_scan($text) {
-
-
-
- preg_match_all('/
- \[ # [ - pattern start
- ([^\s\[\]:]*) # match $type not containing whitespace : [ or ]
- : # : - separator
- ([^\[\]]*) # match $name not containing [ or ]
- \] # ] - pattern end
- /x', (string) $text, $matches);
-
- $types = $matches[1];
- $tokens = $matches[2];
-
-
-
-
- $results = array();
- for ($i = 0; $i < count($tokens); $i++) {
- $results[$types[$i]][$tokens[$i]] = $matches[0][$i];
- }
-
- return $results;
- }
-
- * Generates replacement values for a list of tokens.
- *
- * @param string $type
- * The type of token being replaced. 'node', 'user', and 'date' are common.
- * @param array $tokens
- * An array of tokens to be replaced, keyed by the literal text of the token
- * as it appeared in the source text.
- * @param array $data
- * (optional) An array of keyed objects. For simple replacement scenarios
- * 'node', 'user', and others are common keys, with an accompanying node or
- * user object being the value. Some token types, like 'site', do not require
- * any explicit information from $data and can be replaced even if it is
- * empty.
- * @param array $options
- * (optional) A keyed array of settings and flags to control the token
- * replacement process. Supported options are:
- * - language: A language object to be used when generating locale-sensitive
- * tokens.
- * - callback: A callback function that will be used to post-process the
- * array of token replacements after they are generated. Can be used when
- * modules require special formatting of token text, for example URL
- * encoding or truncation to a specific length.
- * - sanitize: A boolean flag indicating that tokens should be sanitized for
- * display to a web browser. Developers who set this option to FALSE assume
- * responsibility for running filter_xss(), check_plain() or other
- * appropriate scrubbing functions before displaying data to users.
- *
- * @return array
- * An associative array of replacement values, keyed by the original 'raw'
- * tokens that were found in the source text. For example:
- * $results['[node:title]'] = 'My new node';
- *
- * @see hook_tokens()
- * @see hook_tokens_alter()
- */
- function token_generate($type, array $tokens, array $data = array(), array $options = array()) {
- $options += array('sanitize' => TRUE);
- $replacements = module_invoke_all('tokens', $type, $tokens, $data, $options);
-
-
- $context = array(
- 'type' => $type,
- 'tokens' => $tokens,
- 'data' => $data,
- 'options' => $options,
- );
- backdrop_alter('tokens', $replacements, $context);
-
- return $replacements;
- }
-
- * Returns a list of tokens that begin with a specific prefix.
- *
- * Used to extract a group of 'chained' tokens (such as [node:author:name])
- * from the full list of tokens found in text. For example:
- * @code
- * $data = array(
- * 'author:name' => '[node:author:name]',
- * 'title' => '[node:title]',
- * 'created' => '[node:created]',
- * );
- * $results = token_find_with_prefix($data, 'author');
- * $results == array('name' => '[node:author:name]');
- * @endcode
- *
- * @param array $tokens
- * A keyed array of tokens, and their original raw form in the source text.
- * @param string $prefix
- * A textual string to be matched at the beginning of the token.
- * @param string $delimiter
- * An optional string containing the character that separates the prefix from
- * the rest of the token. Defaults to ':'.
- *
- * @return array
- * An associative array of discovered tokens, with the prefix and delimiter
- * stripped from the key.
- */
- function token_find_with_prefix(array $tokens, $prefix, $delimiter = ':') {
- $results = array();
- foreach ($tokens as $token => $raw) {
- $parts = explode($delimiter, $token, 2);
- if (count($parts) == 2 && $parts[0] == $prefix) {
- $results[$parts[1]] = $raw;
- }
- }
- return $results;
- }
-
- * Returns metadata describing supported tokens.
- *
- * The metadata array contains token type, name, and description data as well
- * as an optional pointer indicating that the token chains to another set of
- * tokens.
- *
- * For example:
- * @code
- * $data['types']['node'] = array(
- * 'name' => t('Nodes'),
- * 'description' => t('Tokens related to node objects.'),
- * );
- * $data['tokens']['node']['title'] = array(
- * 'name' => t('Title'),
- * 'description' => t('The title of the current node.'),
- * );
- * $data['tokens']['node']['author'] = array(
- * 'name' => t('Author'),
- * 'description' => t('The author of the current node.'),
- * 'type' => 'user',
- * );
- * @endcode
- *
- * @return array
- * An associative array of token information, grouped by token type.
- */
- function token_info() {
- $data = &backdrop_static(__FUNCTION__);
- if (!isset($data)) {
- $data = module_invoke_all('token_info');
- backdrop_alter('token_info', $data);
- }
- return $data;
- }
-
- * Retrieve, sort, store token info from the cache.
- *
- * @param string|NULL $token_type
- * The optional token type that if specified will return
- * $info['types'][$token_type].
- * @param string|NULL $token_name
- * The optional token name if specified will return
- * $info['tokens'][$token_type][$token_name].
- *
- * @return array
- * An array of all token information from hook_token_info(), or the array
- * of a token type or specific token.
- *
- * @see hook_token_info()
- * @see hook_token_info_alter()
- */
- function token_get_info($token_type = NULL, $token_name = NULL) {
- global $language_content;
-
- $cache_token = cache('token');
-
-
- static $backdrop_static_fast;
- if (!isset($backdrop_static_fast)) {
- $backdrop_static_fast['token_info'] = &backdrop_static(__FUNCTION__);
- }
- $token_info = &$backdrop_static_fast['token_info'];
-
- if (empty($token_info)) {
- $cid = "info:{$language_content->langcode}";
-
- if ($cache = $cache_token->get($cid)) {
- $token_info = $cache->data;
- }
- else {
- $token_info = token_info();
- foreach (array_keys($token_info['types']) as $type_key) {
- if (isset($token_info['types'][$type_key]['type'])) {
- $base_type = $token_info['types'][$type_key]['type'];
-
-
- if (isset($token_info['tokens'][$base_type])) {
- $token_info['tokens'] += array($type_key => array());
- $token_info['tokens'][$type_key] += $token_info['tokens'][$base_type];
- }
- }
- else {
-
-
- $token_info['types'][$type_key]['type'] = $type_key;
- }
- }
-
-
- backdrop_sort($token_info['types'], array('name' => SORT_STRING));
-
-
- $cache_token->set($cid, $token_info);
- }
- }
-
- if (isset($token_type) && isset($token_name)) {
- return isset($token_info['tokens'][$token_type][$token_name]) ? $token_info['tokens'][$token_type][$token_name] : NULL;
- }
- elseif (isset($token_type)) {
- return isset($token_info['types'][$token_type]) ? $token_info['types'][$token_type] : NULL;
- }
- else {
- return $token_info;
- }
- }
-
- * Return the module responsible for a token.
- *
- * @param string $token_type
- * The token type.
- * @param string $token_name
- * The token name.
- *
- * @return mixed
- * The module name that provides the token or NULL if the value does not
- * exist.
- */
- function token_get_module($token_type, $token_name) {
- $token_info = token_get_info($token_type, $token_name);
- return isset($token_info['module']) ? $token_info['module'] : NULL;
- }
-
- * Get a list of token types that can be used without any context (global).
- *
- * @return array
- * An array of global token types.
- */
- function token_get_global_token_types() {
- $global_types = &backdrop_static(__FUNCTION__, array());
-
- if (empty($global_types)) {
- $token_info = token_get_info();
- foreach ($token_info['types'] as $type => $type_info) {
-
-
- if (empty($type_info['needs-data'])) {
- $global_types[] = $type;
- }
- }
- }
-
- return $global_types;
- }
-
- * Clear token caches and static variables.
- */
- function token_cache_clear() {
- if (db_table_exists('cache_token')) {
- cache('token')->flush();
- }
- backdrop_static_reset('token_get_info');
- backdrop_static_reset('token_get_global_token_types');
- backdrop_static_reset('token_build_tree');
- backdrop_static_reset('_menu_token_link_load');
- backdrop_static_reset('_menu_token_node_link_load');
- backdrop_static_reset('_field_token_info');
- }
-
- * Retrieves the current list of all site tokens and checks for common problems.
- *
- * @return array
- * An array with problems detected. Each item is keyed by a machine name for
- * the error and includes:
- * - label: A description of the problem.
- * - problems: An array of the problematic tokens.
- *
- * @see system_requirements()
- */
- function token_get_token_problems() {
- $token_info = token_info();
- $token_problems = array(
- 'not-array' => array(
- 'label' => t('The following tokens or token types are not defined as arrays:'),
- ),
- 'missing-info' => array(
- 'label' => t('The following tokens or token types are missing required name and/or description information:'),
- ),
- 'type-no-tokens' => array(
- 'label' => t('The following token types do not have any tokens defined:'),
- ),
- 'tokens-no-type' => array(
- 'label' => t('The following token types are not defined but have tokens:'),
- ),
- 'duplicate' => array(
- 'label' => t('The following token or token types are defined by multiple modules:')
- ),
- );
-
-
- foreach ($token_info['types'] as $type => $type_info) {
- $real_type = !empty($type_info['type']) ? $type_info['type'] : $type;
- if (!is_array($type_info)) {
- $token_problems['not-array']['problems'][] = "\$info['types']['$type']";
- continue;
- }
- elseif (!isset($type_info['name']) || !isset($type_info['description'])) {
- $token_problems['missing-info']['problems'][] = "\$info['types']['$type']";
- }
- elseif (empty($token_info['tokens'][$real_type])) {
- $token_problems['type-no-tokens']['problems'][] = "\$info['tokens']['$real_type']";
- }
- }
-
-
- foreach ($token_info['tokens'] as $type => $tokens) {
- if (!is_array($tokens)) {
- $token_problems['not-array']['problems'][] = "\$info['tokens']['$type']";
- continue;
- }
- else {
- foreach (array_keys($tokens) as $token) {
- if (!is_array($tokens[$token])) {
- $token_problems['not-array']['problems'][] = "\$info['tokens']['$type']['$token']";
- continue;
- }
- elseif (!isset($tokens[$token]['name']) || !isset($tokens[$token]['description'])) {
- $token_problems['missing-info']['problems'][] = "\$info['tokens']['$type']['$token']";
- }
- elseif (is_array($tokens[$token]['name']) || is_array($tokens[$token]['description'])) {
- $token_problems['duplicate']['problems'][] = "\$info['tokens']['$type']['$token']";
- }
- }
- }
- if (!isset($token_info['types'][$type])) {
- $token_problems['tokens-no-type']['problems'][] = "\$info['types']['$type']";
- }
- }
-
- return $token_problems;
- }
-
- * Loads a token type.
- *
- * @param string $token_type
- * A token type name.
- *
- * @return array
- * An array representing the token type. FALSE if no type found.
- */
- function token_type_load($token_type) {
- $info = token_get_info();
- return isset($info['types'][$token_type]) ? $info['types'][$token_type] : FALSE;
- }
-
- * Build a tree array of tokens, commonly used for rendering the token browser.
- *
- * @param string $token_type
- * The token type.
- * @param array $options
- * An array of options including the following keys:
- * - flat: A boolean if TRUE will only make a flat array of tokens, otherwise
- * child tokens will be inside the 'children' parameter of a token.
- * - restricted: A boolean if TRUE will show restricted tokens. Otherwise they
- * will be hidden. Default is FALSE.
- * - depth: An integer with the maximum number of token levels to recurse.
- * - parents: An optional array with the current parents of the tokens.
- *
- * @return array
- * An array of token information, keyed by the full token and each containing:
- * - name: The translated human-readable name of the token.
- * - description: The translated description of the token.
- * - raw token: The full token (same as the key of this entry).
- * - restricted: Optionally present if the token should only be available
- * in trusted environments.
- * - deprecated: Optionally present if the token will be removed from a future
- * version of Backdrop and should not be used.
- * - token: The last portion of the token. e.g. in [node:nid], the value would
- * be nid.
- */
- function token_build_tree($token_type, array $options = array()) {
- global $language_content;
-
- $cache_token = cache('token');
-
-
- $trees = &backdrop_static(__FUNCTION__, array());
-
- $options += array(
- 'restricted' => FALSE,
- 'depth' => 4,
- 'data' => array(),
- 'values' => FALSE,
- 'flat' => FALSE,
- );
-
-
- $options['depth'] = min($options['depth'], TOKEN_MAX_DEPTH);
-
- $tree_cid = "tree:{$token_type}:{$language_content->langcode}:{$options['depth']}";
-
-
-
- if (!isset($trees[$tree_cid])) {
- if ($cache = $cache_token->get($tree_cid)) {
- $trees[$tree_cid] = $cache->data;
- }
- else {
- $options['parents'] = array();
- $trees[$tree_cid] = _token_build_tree($token_type, $options);
- cache_set($tree_cid, $trees[$tree_cid], 'cache', CACHE_PERMANENT);
- }
- }
-
- $tree = $trees[$tree_cid];
-
-
- if (!empty($options['flat'])) {
- $tree = token_flatten_tree($tree);
- }
-
-
- if (!empty($options['values'])) {
- $token_values = array();
- foreach ($tree as $token => $token_info) {
- if (!empty($token_info['dynamic']) || !empty($token_info['restricted'])) {
- continue;
- }
- elseif (!isset($token_info['value'])) {
- $token_values[$token_info['token']] = $token;
- }
- }
- if (!empty($token_values)) {
- $token_values = token_generate($token_type, $token_values, $options['data']);
- foreach ($token_values as $token => $replacement) {
- $tree[$token]['value'] = $replacement;
- }
- }
- }
-
- return $tree;
- }
-
- * Flatten a token tree.
- *
- * @param array $tree
- * An array of tokens as returned by token_build_tree().
- * @return array
- * The array of tokens as flat array.
- */
- function token_flatten_tree($tree) {
- $result = array();
- foreach ($tree as $token => $token_info) {
- $result[$token] = $token_info;
- if (isset($token_info['children']) && is_array($token_info['children'])) {
- $result += token_flatten_tree($token_info['children']);
- unset($result[$token]['children']);
- }
- }
- return $result;
- }
-
- * Recursive helper for token_build_tree().
- */
- function _token_build_tree($token_type, array $options, $parent_restricted = FALSE) {
- $options += array(
- 'parents' => array(),
- );
-
- $info = token_get_info();
- if ($options['depth'] <= 0 || !isset($info['types'][$token_type]) || !isset($info['tokens'][$token_type])) {
- return array();
- }
-
- $tree = array();
- foreach ($info['tokens'][$token_type] as $token => $token_info) {
-
- $token_parents = $options['parents'];
- if (empty($token_parents)) {
-
-
- $token_parents[] = $token_type;
- }
- elseif (in_array($token, array_slice($token_parents, 1))) {
-
-
-
-
- continue;
- }
- elseif (!empty($token_info['restricted']) && !$options['restricted']) {
-
- continue;
- }
-
- $token_parents[] = $token;
- if (!empty($token_info['dynamic'])) {
- $token_parents[] = '?';
- }
- $raw_token = '[' . implode(':', $token_parents) . ']';
- $tree[$raw_token] = $token_info;
- $tree[$raw_token]['raw token'] = $raw_token;
-
-
- $tree[$raw_token]['token'] = implode(':', array_slice($token_parents, 1));
-
-
- if (!empty($options['parents'])) {
- $tree[$raw_token]['parent'] = '[' . implode(':', $options['parents']) . ']';
- }
-
-
- if ($parent_restricted) {
- $tree[$raw_token]['restricted'] = TRUE;
- }
-
-
- if (!empty($token_info['type'])) {
- $child_options = $options;
- $child_options['depth']--;
- $child_options['parents'] = $token_parents;
- $child_parent_restricted = $parent_restricted || !empty($tree[$raw_token]['restricted']) || !empty($token_info['restricted']);
- $tree[$raw_token]['children'] = _token_build_tree($token_info['type'], $child_options, $child_parent_restricted);
- }
- }
-
- return $tree;
- }
-
- * Validate a form element that should have tokens in it.
- *
- * Form elements that want to add this validation should have the #token_types
- * parameter defined.
- *
- * For example:
- * @code
- * $form['my_node_text_element'] = array(
- * '#type' => 'textfield',
- * '#title' => t('Some text to token-ize that has a node context.'),
- * '#default_value' => 'The title of this node is [node:title].',
- * '#element_validate' => array('token_element_validate'),
- * '#token_types' => array('node'),
- * '#min_tokens' => 1,
- * '#max_tokens' => 10,
- * );
- * @endcode
- */
- function token_element_validate(&$element, &$form_state) {
- $value = isset($element['#value']) ? $element['#value'] : $element['#default_value'];
-
- if (!backdrop_strlen($value)) {
-
-
- return $element;
- }
-
- $tokens = token_scan($value);
- $title = empty($element['#title']) ? $element['#parents'][0] : $element['#title'];
-
-
- if (isset($element['#min_tokens']) && count($tokens) < $element['#min_tokens']) {
- $error = format_plural($element['#min_tokens'], 'The !element-title cannot contain fewer than one token.', 'The !element-title must contain at least @count tokens.', array('!element-title' => $title));
- form_error($element, $error);
- }
-
-
- if (isset($element['#max_tokens']) && count($tokens) > $element['#max_tokens']) {
- $error = format_plural($element['#max_tokens'], 'The !element-title may not contain more than one token.', 'The !element-title may not contain more than @count tokens.', array('!element-title' => $title));
- form_error($element, $error);
- }
-
-
- if (isset($element['#token_types'])) {
- $invalid_tokens = token_get_invalid_tokens_by_context($tokens, $element['#token_types']);
- if ($invalid_tokens) {
- form_error($element, t('The !element-title is using the following invalid tokens: @invalid-tokens.', array('!element-title' => $title, '@invalid-tokens' => implode(', ', $invalid_tokens))));
- }
- }
-
- return $element;
- }
-
- * Prepare a string for use as a valid token name.
- *
- * @param string $name
- * The token name to clean.
- * @return string
- * The cleaned token name.
- */
- function token_clean_token_name($name) {
- static $names = array();
-
- if (!isset($names[$name])) {
- $cleaned_name = strtr($name, array(' ' => '-', '_' => '-', '/' => '-', '[' => '-', ']' => ''));
- $cleaned_name = preg_replace('/[^\w\-]/i', '', $cleaned_name);
- $cleaned_name = trim($cleaned_name, '-');
- $names[$name] = $cleaned_name;
- }
-
- return $names[$name];
- }
-
- * Validate an tokens in raw text based on possible contexts.
- *
- * @param string $value
- * A string with the raw text containing the raw tokens, or an array of
- * tokens from token_scan().
- * @param array $valid_types
- * An array of token types that will be used when token replacement is
- * performed.
- * @return array
- * An array with the invalid tokens in their original raw forms.
- */
- function token_get_invalid_tokens_by_context($value, array $valid_types = array()) {
- if (in_array('all', $valid_types)) {
- $info = token_get_info();
- $valid_types = array_keys($info['types']);
- }
- else {
-
- $valid_types = array_merge($valid_types, token_get_global_token_types());
- }
-
- $invalid_tokens = array();
- $value_tokens = is_string($value) ? token_scan($value) : $value;
-
- foreach ($value_tokens as $type => $tokens) {
- if (!in_array($type, $valid_types)) {
-
- $invalid_tokens = array_merge($invalid_tokens, array_values($tokens));
- }
- else {
-
- $invalid_tokens = array_merge($invalid_tokens, token_get_invalid_tokens($type, $tokens));
- }
- }
-
- array_unique($invalid_tokens);
- return $invalid_tokens;
- }
-
- * Validate an array of tokens based on their token type.
- *
- * @param string $type
- * The type of tokens to validate (e.g. 'node', etc.)
- * @param array $tokens
- * A keyed array of tokens, and their original raw form in the source text.
- * @return array
- * An array with the invalid tokens in their original raw forms.
- */
- function token_get_invalid_tokens($type, array $tokens) {
- $token_info = token_get_info();
- $invalid_tokens = array();
-
- foreach ($tokens as $token => $full_token) {
-
- $parts = explode(':', $token, 2);
-
- if (!isset($token_info['tokens'][$type][$parts[0]])) {
-
- $invalid_tokens[] = $full_token;
- }
- elseif (count($parts) == 2) {
- $sub_token_info = $token_info['tokens'][$type][$parts[0]];
- if (!empty($sub_token_info['dynamic'])) {
-
- continue;
- }
- elseif (empty($sub_token_info['type'])) {
-
- $invalid_tokens[] = $full_token;
- }
- else {
-
- $sub_tokens = token_find_with_prefix(array($token => $full_token), $parts[0]);
- $invalid_tokens = array_merge($invalid_tokens, token_get_invalid_tokens($sub_token_info['type'], $sub_tokens));
- }
- }
- }
-
- return $invalid_tokens;
- }
-
- * Renders a render array for display as a token.
- *
- * @param array $array
- * The render array to be converted to HTML.
- * @param array $options
- * Array of options for rendering. Values can include:
- * - sanitize: Runs check_plain() on the rendered output.
- * - join: Joins rendered items together with a comma.
- *
- * @return string
- * HTML of rendered item.
- *
- * @see token_render_array_value()
- */
- function token_render_array(array $array, array $options = array()) {
- $rendered = array();
- foreach ($array as $key => $value) {
- if (substr($key, 0, 1) === '#') {
- continue;
- }
- $rendered[] = is_array($value) ? render($value) : (string) $value;
- }
- if (!empty($options['sanitize'])) {
- $rendered = array_map('check_plain', $rendered);
- }
- $join = isset($options['join']) ? $options['join'] : ', ';
- return implode($join, $rendered);
- }
-
- * Renders a render array for display as a token.
- *
- * @param string $value
- * Value OR Render array.
- * @param array $options
- * Array of options for rendering. Values can include:
- * - sanitize: Runs check_plain() on the rendered output.
- *
- * @return
- * HTML of rendered item.
- *
- * @see token_render_array_value()
- */
- function token_render_array_value($value, array $options = array()) {
- $rendered = is_array($value) ? render($value) : (string) $value;
- if (!empty($options['sanitize'])) {
- $rendered = check_plain($rendered);
- }
- return $rendered;
- }