0

I am trying to create a delta token in my module. In hook_tokens, I manage to get the file object, but I have no clue on how to get the delta of my file...

Here is my implementation of hook_token_info

function artprod_token_info() {
  $types = array();
  $tokens = array();

  $types['delta'] = array(
    'name' => t('Delta'),
    'description' => t('Provide the delta of the field.')
  );
  $tokens['delta']['delta'] = array(
    'name' => t('Delta'),
    'description' => t('Provide the delta of the field.')
  );

  return array(
    'types' => $types, 
    'tokens' => $tokens
  );
}

Here is the beginning of my implementation of hook_tokens

function artprod_tokens($type, $tokens, array $data, array $options, BubbleableMetadata $bubbleable_metadata) {
  $replacements = array();
  if ($type == 'delta') {
    $file=$data['file'];
    foreach ($tokens as $name => $original) {
      // Find the desired token by name
      switch ($name) {
        case 'delta':
          $replacements[$original] = $file->delta();// NOT WORKING
          break;
      }
    }
  }
  return $replacements;
}
2

It's the relationship between a file entity and another entity via a reference field that has a delta, not the file entity itself. A single file could, theoretically, be referenced by many entities, via multiple separate fields, or even twice in the same entity - meaning it doesn't conceptually have a single delta related to it.

What you'll need is to run an EntityQuery with sufficient contextual conditions to narrow down to one result, load up that parent entity, and loop through the field values until you find your file, giving you the delta.

If your use case enforces that a file can only be referenced by a single entity, it'll be a lot easier to implement. But it would probably be safer to include at least some kind of limiting.

  • I completely agree with you; but in my use case, my file is used only once. I will vote for your clever comment and I will also update this post with a solution that I found meantime – Baud Jul 22 '16 at 19:59
0

Here is the solution I found:

Firstly, I have slightly rewrite the hook_token_info to "store" the field name of my file field in the token name:

function mymodule_token_info() {
  $types = array();
  $tokens = array();

  $types['delta'] = array(
    'name' => t('Delta'), 
    'description' => t('Provide the delta of the field.')
  );
  //I name the token like my file field name for a futur use
  $tokens['delta']['field_my_file_field'] = array(
    'name' => t('Delta'), 
    'description' => t('Provide the delta of field_my_file_field.')
  );

  return array(
    'types' => $types, 
    'tokens' => $tokens
  );
}

Then in hook_tokens: I get the fid of my file and I compare it with all the fid's values of $mynode->field_my_file_field. When both fid matches, I use the delta for my replacement:

function mymodule_tokens($type, $tokens, array $data, array $options, BubbleableMetadata $bubbleable_metadata) {
  $replacements = array();
  if ($type == 'delta') {
    // Get the fid to compare with the field attached to my node
    $file_fid = $data['file']->id();
    // loop throught all the tokens
    foreach ($tokens as $name => $original) {
      // As the token name is also the name of the field,
      // I can loop the field values. This allow me to create
      // other tokens for other fields
      foreach ($data['node']->{$name} as $delta => $file_item) {
        // compare the value with the fid
        if ($file_item->getValue()['target_id'] == $file_fid) {
          //if it matchs, I can use this delta as a replacement
          //for my token (I add 1 as a personal choice)
          $replacements[$original] = $delta + 1;
        }
      }
    }
  }
  return $replacements;
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.