Hi,

there seems to be a bug on entity handling with the token replacement on custom caption text.
I made a field_collection containing an image and wanted to display it in a colorbox with a custom caption using tokens.

When I displayed it, I got a EntityMalformedException Message.

After a first look in the code, we found in colorbox.theme.inc on line 64

      $caption = token_replace($settings['colorbox_caption_custom'], array('node' => $node));

where should be something like

      $caption = token_replace($settings['colorbox_caption_custom'], array($entity_type => $entity));

this problem starts already in the colorbox_field_formatter_view function in colorbox.module

Thx for your help/work.
greets ifux

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Berdir’s picture

Which means that the entity_type/entity needs to be passed to the theme function.

To fix this in a BC-compatible way, you can keep the #node argument there and additionally add #entity_type and #entity and then use that in your own implementation while overriden implementations can still rely on node being there.

frjo’s picture

Version: 7.x-1.3 » 7.x-1.x-dev
Assigned: Unassigned » frjo
Status: Needs work » Fixed

Committed a fix to 7-dev. Please test and report back here.

Berdir’s picture

Status: Fixed » Needs work
    elseif (!empty($node->title)) {
-        $caption = $node->title;
+      elseif (!empty($entity->title)) {
+        $caption = $entity->title;

You need to use entity_label($entity_type, $entity) here, also once more below.

-  $nid = !empty($node->nid) ? $node->nid : 'nid';
+  $nid = !empty($entity->nid) ? $entity->nid : 'nid';

To get the entity id, you can use http://api.drupal.org/api/drupal/includes%21common.inc/function/entity_e.... Then the identifier should maybe be a combination of the entity type and id?

And, you should also update the field formatter settings form to list the token type there, you should be able to get the entity type out of the field instance I think. Not all token types map to the entity_type (e.g. term and taxonomy_term), but I think entity.module adds that information to entity_info() when it knows it.

frjo’s picture

Status: Needs work » Needs review

@Berdir, thanks for the pointers! I have committed some changes to 7-dev now. Looks ok to you?

Alan D.’s picture

Looking great. I think that you can do a search for the word node and replace by content or image depending on the context.

I would do this too.

- '#node' => $entity, // Left for legacy support.
- '#node' => $entity_type == 'node' ? $entity : NULL, // Left for legacy support.
Alan D.’s picture

Let me know if you need a new issue for this (or a patch for the 2 loc), but it would it would be great to implement file tokens here too. The file tokens are not chained to the entity ([node:field_file:file-tokens....) via core nor token at the moment.

Minimal change, using the latest release (pre-entity changes):

    case 'custom':
-      $caption = token_replace($settings['colorbox_caption_custom'], array('node' => $node));
+      $caption = token_replace($settings['colorbox_caption_custom'], array('node' => $node, 'file' => (object) $item));
      break;
    default:
      $caption = '';

And to get the token help:

  if (module_exists('token')) {
    $element['colorbox_token'] = array(
      '#type' => 'fieldset',
      '#title' => t('Replacement patterns'),
      '#theme' => 'token_tree',
-      '#token_types' => array('node'),
+      '#token_types' => array('node', 'file'),
      '#states' => array(
        'visible' => array(
          ':input[name$="[settings_edit_form][settings][colorbox_caption]"]' => array('value' => 'custom'),
        ),
      ),
    );
  }

We currently do this via a theme override:

/**
 * Returns HTML for an Colorbox image field formatter.
 */
function phptemplate_colorbox_image_formatter($variables) {
  // TODO: After upgrade, we can alter this to just use the entity directly.
  $item = $variables['item'];
  if (!empty($variables['entity'])) {
    $entity_type = $variables['entity_type'];
    $entity = $variables['entity'];
    $entity_title = entity_label($entity_type, $entity);
  }
  else {
    $entity_type = 'node';
    $node = $variables['node'];
    $entity_title = $node->title;
  }

  if ($variables['display_settings']['colorbox_caption'] == 'custom') {
    $variables['display_settings']['colorbox_caption_custom'] =
      token_replace($variables['display_settings']['colorbox_caption_custom'], array(
        'file' => (object) $item,
        $entity_type => $entity,
      ));
  }
  return theme_colorbox_image_formatter($variables);
}

This provides access to the file details, like the file size, etc, as well as possible integration with other modules. I'm porting ImageField Extended to D7 (long story - after high hopes for file entities and field collections we ruled both modules out) and the new version provides token values for each of the additional sub-field elements that it adds. [file:attributes-caption], [file:attributes-date-taken], etc.

Alan D.’s picture

As an aside, the token tree nearly kills the browser tucked into the formatter display. It would be nice to configure this in the global settings: eg: in admin/config/media/colorbox

Enabled field display token help
[*] content tokens
[*] file tokens

Then parse this to decide what tokens to display. Something like:

  if (module_exists('token')) {
    $token_types = array_filter(variable_get('colorbox_formatter_token_types', array('content', 'file')));
    $token_types = array_intersect_key(array('content' => $entity_type, 'file' => file), $token_types);
    if (!empty($token_types)) {
    ....
    }
  }

Worthy of a new feature request thread if you are interested.

Berdir’s picture

Status: Needs review » Fixed

Changes look good to me.

- The #node argument is explicitly always there to not break existing theme function overrides out there that rely on #node. We have for example done that do add support for field collections without having to patch the module, others might have done the same.
- Adding more things to the token_replace() function is probably better suited for a separate issue, and I disagree that the token browser should configurable. The only proper solution there is a lazy-loading ajaxified token browser.

Alan D.’s picture

The only proper solution there is a lazy-loading ajaxified token browser.

lol, that is the best quote that I have heard for a while - been tracking those threads for well over a year, and it is not going to happen for a very very long time.

Anyways, open #1555856: File Token support.

Alan D.’s picture

Title: Custom caption with tokens - Wrong entity type » Support all entity fields
Priority: Major » Minor
Status: Fixed » Needs review
FileSize
2.71 KB

This was a bit perplexing in the user fields :)

Renames a number of comments and some t() strings.

frjo’s picture

Status: Needs review » Fixed

@Alan D, thanks for cleaning it up! Committed to 7-dev.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.