Wednesday, January 2, 2013

How to validate the dimensions of an image, and warn the user if it is too small in Drupal

  Isn't that a magical title?  Titles are surprisingly hard to write for this sort of thing.  They are either short and entirely unhelpful, or way too long, but descriptive. At any rate, this is episode 1 of "Learning from the mistakes of others", others, in this case, being me.  Of course.
  So I was assigned an issue at work (as if I don't have plenty of my own issues)(hur hur).  The site we are working on has slideshows on several pages, that are populated by images automatically imported from feed items.  This means there is a very good chance that some of the images that come in with the feed item will be too small, and would look bad in the slideshow.  We needed to verify that any given image was big enough for the slideshow, and throw up a warning notice if it wasn't. Easy peasy, right?  Erm, no.  Not for me.  As it turns out, having no background whatsoever in php/(any programming language at all) makes for a long, hard slog through the Drupal API documents....  Fortunately, I have some awesome co-workers that don't mind helping a girl out when I get stuck.  Which is... frequently.
  If I were to go through all of the iterations of (let's be honest here) psuedo-code that I tried, we would be here all night.  Eventually, one of my worker buddies threw a bucket of cold water over me(figuratively speaking, of course), and pointed out something very valuable.  When coding, you just have to take it step by step.  Write down what you need to do, the order in which it needs to be done, and *then* begin coding.  After each step, check that it is working as you expect it to.  dpm() is your friend.  Also, turn on error reporting in your settings.php if you are working in a local environment.  That saved me oooooodles of time once I did it.  Here is my final product, although keep in mind that it hasn't been given the stamp of approval yet by my superiors, so it is *entirely* possible that there are better ways to do this.  It works, is all I know... ;) I've gone through and commented it more thoroughly, just to be super specific about what I did.

/**
 * Implements hook_form_form_id_alter().
 */
function my_module_form_my_form_id_form_alter(&$form, &$form_state, $form_id) {
  //This is where I've added my custom validate function.
  $form['#validate'][] = 'my_module_image_form_validate';
}





/**
 * Implements hook_node_validate() and image_style_load().
 *
 * Check image dimensions and return warning if image is too small.
 */
function my_module_image_form_validate(&$form, &$form_state) {
 
  // Check if fid exists. This prevents any possible errors if there isn't an image in the field.
  if (isset($form_state['values']['field_media']['und']['0']['fid'])) {
  // Get the fid.
  $fid = ($form_state['values']['field_media']['und']['0']['fid']);
  // You have to load the file before you can check its dimensions, so:
 $file = file_load($fid);

  // Now that the file is loaded, I can set my variables. Use dpm($file) to find them...
  $height = ($file->image_dimensions['height']);
  $width = ($file->image_dimensions['width']);

  // I originally had this without the next 7 lines, and the numbers were hardcoded, i.e., if ($width < 780) etc...  A wise co-worker pointed out that this would cause trouble if the image styles were ever changed, and that I should use the image style presets.  So next I:
  // Get the image style presets.
  $styles = image_styles();
  // Now I can set my variables to check against.
  $minheight = ($styles['iin_wide_780x438']['effects']['15']['data']['height']);
  $minwidth = ($styles['iin_wide_780x438']['effects']['15']['data']['width']);
  //dsm($styles); (always check your work)


  // And here is the magic:
  if (isset($height) && isset($width)) {
  if ($width < $minwidth || $height < $minheight) {

  // This just sets a message right above the image field (field_media) to warn the user that the image is too small.
  $form['field_media']['#prefix'] = '<div class="messages warning">Image is smaller than recommended size.</div>';
      }
    }
  }
}
And KA-BLOW!  Bob, so to speak, is your uncle!
And now I must go to bed.
Minion out.