Media Block for Parent-Child Entities

Posted by Lucas Hedding on April 4, 2013

Here's the requirements. You have a parent-child relationship (one-to-many) between two content types. There are three media related fields on these content types. Your assignment is to display the first populated field in a block for a panels managed page. The order is 1) brightcove video 2) flickr photoset 3) file image. If one of the fields isn't populated on the child content type, find its parent and see if the parent has a field populated. The first hammer I picked up was Views. There is an add-on module called views_ifempty that seems to perfectly fit the bill.  However, it only works on the same node.  It doesn't chain up the request to a parent node.  So I went with strait PHP and the entity module's entity_metadata_wrapper.

The code is fairly strait forward, except for some fancy logic at the beginning on line 6 and a recursive callback down at the bottom on line 56. On line 6, if we haven't done a recursive callback, then $entity is NULL and we go ahead and process the node normally.  At the bottom, if we've gone through all the logic to check the population of a field and we are on a child node, then call example_block_media() recursively with the parent node. This time when we check for the entity on line 6, it will not be empty.

The rest of the code just spits out appropriately themed HTML for brightcove videos, flickr photosets and photos.  Here's the full working code.

/**
 * Block call back for a media block.
 */
function example_block_media($entity = NULL, $child_title = NULL) {
  $block = array();
  $wrapper = empty($entity) ? entity_metadata_wrapper('node', menu_get_object()) : $entity;
 
  if ($wrapper->type->value() == 'parent' || $wrapper->type->value() == 'child') {
    if ($value = $wrapper->field_video_embed_code->value(array(
      'sanitize' => TRUE
    ))) {
      $block['content'] = theme('example_brightcove', array(
        '@videoPlayer' => $value[0],
        'videoID' => '1234567910',
        'attributes' => array(
          'class' => 'example-media',
        ),
      ));
    }
    elseif ($value = $wrapper->field_flickr->value(array(
      'sanitize' => TRUE
    ))) {
      $block['content'] = theme('example_flickr_set_slideshow', array(
        'set_id' => $value,
        'attributes' => array(
          'class' => 'example-media',
        ),
      ));
    }
    elseif ($wrapper->field_files->value()) {
      $description = $wrapper->field_files[0]->description->value() !== '' ? $wrapper->field_files[0]->description->value()
          : $description = $wrapper->title->value();
 
      // If we call recursively, and no description is set, then use the title of the child
      if (isset($child_title) && $wrapper->field_files[0]->description->value() == '') {
        $description = $child_title;
      }
 
      $description = filter_xss($description);
 
      $block['content'] = theme('image', array(
        'path' => $wrapper->field_files[0]->file->url->value(),
        'alt' => $description,
        'title' => $description,
        'width' => '300px',
        'height' => '220px',
        'attributes' => array(
          'class' => 'example-media',
        ),
      ));
    }
    elseif ($wrapper->type->value() == 'child') {
      // Pass in the title of the child node to use as the title/alt
      // text of the image (in case one wasn't set).
      // field_parent_node_ref is a required field on child content type.
      $block = example_block_media($wrapper->field_parent_node_ref, $wrapper->title->value());
    }
  }
  return $block;
}

 

Are you going to need extra help managing a complicated project? Try our project management services.

Write us about your project, and we’ll get back to you within 48 hours.