3

In a given content type, I have three Image fields, each of them set to Unlimited cardinality. It's like a little gallery with 3 fixed albums: when using Display Suite, I have the ability to limit the number of values getting displayed, I limited it to 1: Image - Display Suite, gallery and this way only the first image gets displayed. The fields link to a page created by Views, which shows the images separately as a gallery, etc...

Here's an example of the result:

Gallery, 3 albums

What I would like to achieve is to provide a radio button near the images to the user when editing these fields to be able to select which image I would like to show as a "cover photo" without reordering the images. In the example above, I can only show the 1st one in the "album".

Do you have any ideas for that? Is there a module for this task, or do I have to code?
Can I solve this problem without converting my solution to other gallery solutions? I was thinking about Flag module, but I couldn't find out how I could use it for this task. I'm using File entity (fieldable files) module, which may help in solving this question.

1 Answer 1

4

One approach would be to use file entity and add a field to the image file entity, but that would require re-working your current solution quite a bit.

Another approach would be to use the

Field Attach API

e.g:

to attach the additional field to the image. The field would then need to be checked during output to show/hide that image as the cover image.

Update:

Here's an example to add a checkbox to an image field. I had some settings on the instance form to show/hide the extra fields, removed for conciseness here. You may be able to use hook_field_attach_form though I used a element process hook instead.

/**
 * Implements hook_element_info().
 */
function MODULE_element_info() {
  $extra = array(
    '#process' => array('MODULE_element_process'),
  );

  $elements = array();
  // Add our process function to all managed_file elements
  $elements['managed_file'] = $extra;

  return $elements;
}

/**
 * An additional preprocess callback to append the form.
 */
function MODULE_element_process($element, $form_state, $complete_form) {

  if (!isset($element['#entity_type']) || !isset($element['#field_name'])) {
    return $element;
  }

  // You can get the field data, settings etc.. like this
  $item = $element['#value'];
  $field = field_info_field($element['#field_name']);
  $instance = field_info_instance($element['#entity_type'], $element['#field_name'], $element['#bundle']);
  $settings = $instance['settings'];
  $widget_type = $instance['widget']['type'];

  // Add element, only if file id available
  if ($element['fid']['#value']) {
    // Note default value selects from cache / db table TABLE_file_data
    $element['cover'] = array(
     '#type' => 'checkbox',
     '#title' => t('Cover'),
     '#default_value' => MODULE_file_data_value($element['fid']['#value'], 'cover', '')
    );
  }

  return $element;

}

/**
 * Implements hook_field_attach_presave
 *
 * Saves a files additional field data.
 */
function MODULE_field_attach_presave($entity_type, $entity) {
  list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);
  $supported_widgets = array('image_image', 'imagefield_crop_widget');
  $instances = field_info_instances($entity_type, $bundle);
  foreach ($instances as $field_name => $instance) {
    if (in_array($instance['widget']['type'], $supported_widgets)) {

      $settings = $instance['settings'];
      // I have some settings I check as well, if enabled on field instance..
      //if (empty($settings['display_cover'])){
      //  continue;
      //}
      // Find all of the field items.
      $items = field_get_items($entity_type, $entity, $instance['field_name']);

      if (is_array($items)) {
        // Loop over and save extended field values
        foreach ($items as $delta => $item) {
          $fields = array();
          if (!empty($item['fid'])) {
            if(isset($item['cover'])){
              $fields['cover'] = $item['cover'];
            }
            $fields['changed'] = REQUEST_TIME;
            db_merge('TABLE_file_data')
              ->key(array('fid' => $item['fid']))
              ->fields($fields)->execute();
            // Need to clear entity cache for this file
            // as update was not with api but direct query
            cache_clear_all($item['fid'], 'cache_entity_file');
          }
        }
      }
    }
  }
}
9
  • 1
    +1, thanks for your answer, David! "use file entity and add a field to the image file entity, but that would require re-working your current solution quite a bit." This sounds good, I'm already using this module. I thought about using Flag module, and adding this to the file entity, but couldn't work out the how-to yet (maybe it's not the best solution). Reworking? How? I don't really know Field Attach API, but I'm open to this idea too. Could you show me a little example how it would look like? Or if you have more ideas, please share them. I'm starting a bounty as a motivation :)
    – Sk8erPeter
    Commented Aug 26, 2013 at 0:08
  • David, could you provide any additional information regarding using Field Attach API? :) I haven't found out how I could use it for the given task, but I'm really curious. Or adding a field to file entity also seems like a good idea, but it should behave as a conditional field which operates only when used for given Image fields. Thanks for any ideas in advance!
    – Sk8erPeter
    Commented Sep 3, 2013 at 13:43
  • @Sk8erPeter code example added, cheers. Commented Sep 9, 2013 at 22:20
  • David, thanks for your code! 1st of all, I was a fool, I wrote "checkbox" instead of "radio button". :(( With a radio button using the same name attr., only one option could be selected, and that's the main task. I'm really sorry for this mistake. If '#type' => 'radio' is used, should #name be used? Some more questions before acceptance: 1. Why not using hook_element_info_alter() instead? 2. Could you show me a small example of MODULE_file_data_value() function too? 3. You used TABLE_file_data - so should an own table be defined via hook_schema?Thank you very much in advance!
    – Sk8erPeter
    Commented Sep 12, 2013 at 16:44
  • OK, here's what I did: I created a simple custom table with hook_schema with field_name and fid fields (OK, cool, not too complicated), changed the $element['cover'] field element's properties in MODULE_element_process() to '#type' => 'radio', '#parents' => array($field_name, 'cover'), '#return_value' => $element['#value']['fid'], '#default_value' => testmodule_get_image_field_cover($field_name),, implemented the testmodule_get_image_field_cover with using a simple db_select query (storing the value in a static variable) - OK, radio buttons appear correctly, BUT... (cont'd...)
    – Sk8erPeter
    Commented Sep 20, 2013 at 18:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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