diff --git a/token.module b/token.module index 66b13ac..69804cd 100644 --- a/token.module +++ b/token.module @@ -40,7 +40,7 @@ function token_system_info_alter(&$info, $file, $type) { * Return an array of the core modules supported by token.module. */ function _token_core_supported_modules() { - return array('book', 'menu', 'profile'); + return array('book', 'field', 'menu', 'profile'); } /** diff --git a/token.tokens.inc b/token.tokens.inc index 2f664b6..d48af88 100644 --- a/token.tokens.inc +++ b/token.tokens.inc @@ -693,8 +693,8 @@ function token_tokens($type, $tokens, array $data = array(), array $options = ar $replacements += token_generate('url', $url_tokens, entity_uri($entity_type, $entity), $options); } - // @todo Pass through to an 'entity' token type generation? - // $replacements += token_generate('entity', $tokens, array('entity_type' => $entity_type, 'entity' => $entity), $options); + // Pass through to an generic 'entity' token type generation. + $replacements += token_generate('entity', $tokens, array('entity_type' => $entity_type, 'entity' => $entity), $options); } // Array tokens. @@ -1162,3 +1162,138 @@ function _token_profile_fields() { return $fields; } + +/** + * Implements hook_token_info_alter() on behalf of field.module. + * + * We use hook_token_info_alter() rather than hook_token_info() as other + * modules may already have defined some field tokens. + */ +function field_token_info_alter(&$info) { + $fields = field_info_fields(); + $instances = field_info_instances(); + + // Attach field tokens to their respecitve entity tokens. + foreach ($fields as $field_name => $field) { + if (!empty($field['bundles'])) { + list($label) = _token_field_label($field_name); + + foreach (array_keys($field['bundles']) as $entity) { + // Make sure a token type exists for this entity. + $token_type = token_get_entity_mapping('entity', $entity); + if (empty($token_type)) { + continue; + } + + // If a token already exists for this field, then don't add it. + if (isset($info['tokens'][$token_type][$field_name]) || ($entity == 'comment' && $field_name == 'comment_body')) { + continue; + } + + // Yay! Add the field token to this entity's tokens. + $info['tokens'][$token_type][$field_name] = array( + // @todo How the &#!% do we figure out what this token should be + // named when each bundle can have a different label??? + 'name' => $label, + 'description' => 'TODO: WTF DO WE PUT HERE?', + 'module' => 'token', + ); + } + } + } +} + +/** + * Returns the label of a certain field. + * + * Therefore it looks up in all bundles to find the most used instance. + * + * @see field_views_field_label() + */ +function _token_field_label($field_name) { + $label_counter = array(); + $all_labels = array(); + // Count the amount of instances per label per field. + $instances = field_info_instances(); + foreach ($instances as $entity_name => $entity_type) { + foreach ($entity_type as $bundle) { + if (isset($bundle[$field_name])) { + $label_counter[$bundle[$field_name]['label']] = isset($label_counter[$bundle[$field_name]['label']]) ? ++$label_counter[$bundle[$field_name]['label']] : 1; + $all_labels[$entity_name][$bundle[$field_name]['label']] = TRUE; + } + } + } + if (empty($label_counter)) { + return array($field_name, $all_labels); + } + // Sort the field lables by it most used label and return the most used one. + arsort($label_counter); + $label_counter = array_keys($label_counter); + return array($label_counter[0], $all_labels); +} + +/** + * Implements hook_tokens() on behalf of field.module. + */ +function field_tokens($type, $tokens, array $data = array(), array $options = array()) { + $replacements = array(); + $sanitize = !empty($options['sanitize']); + $langcode = isset($options['language']) ? $options['language']->language : NULL; + + // Entity tokens. + if ($type == 'entity' && !empty($data['entity_type']) && !empty($data['entity'])) { + $entity_type = $data['entity_type']; + $token_type = token_get_entity_mapping('entity', $entity_type); + + // The field API does weird stuff to the entity, so let's clone it. + $entity = clone $data['entity']; + + list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity); + $fields = field_info_instances($entity_type, $bundle); + + foreach ($fields as $field_name => $field_instance) { + // Do not continue if the field is empty. + if (empty($entity->{$field_name})) { + continue; + } + + // Assert that this field was added by token.module. + $token_info = token_get_info($token_type, $field_name); + if (!isset($token_info['module']) || $token_info['module'] != 'token') { + continue; + } + + // Replace the [entity:field-name] token. + if (isset($tokens[$field_name])) { + $display = array('label' => 'hidden'); + $field_output = field_view_field($entity_type, $entity, $field_name, $display, $langcode); + $field_output['#pre_render'][] = 'token_field_token_pre_render'; + $original = $tokens[$field_name]; + $replacements[$original] = drupal_render($field_output); + } + } + + // Remove the cloned object from memory. + unset($entity); + } + + return $replacements; +} + +/** + * Add a space in-between field items so they do not appear smooshed. + */ +function token_field_token_pre_render(&$elements) { + $deltas = element_children($elements); + $count = count($deltas); + if ($count > 1) { + foreach ($deltas as $index => $delta) { + // Add a space character as a suffix since multi-value fields will + // appear smooshed together after rendering. + if ($index < ($count - 1)) { + $elements[$delta] += array('#suffix' => ' '); + } + } + } + return $elements; +}