You are here

ad_image.module in Advertisement 5

Enhances the ad module to support banner ads.

Copyright (c) 2005-2008. Jeremy Andrews <jeremy@kerneltrap.org>. All rights reserved.

File

image/ad_image.module
View source
<?php

/**
 * @file
 * Enhances the ad module to support banner ads.
 *
 * Copyright (c) 2005-2008.
 *   Jeremy Andrews <jeremy@kerneltrap.org>.  All rights reserved.
 */

/**
 * Function used to display the selected ad.
 */
function ad_image_display_ad($ad) {

  // Strip module path from image path if serving images from adserve.php.
  $image_path = preg_replace('&' . drupal_get_path('module', 'ad') . '/&', '', file_create_url($ad->filepath));
  if ($ad->url) {
    $ad_image = "<div class=\"image-advertisement\" id=\"ad-{$ad->aid}\"><a href=\"{$ad->redirect}/@HOSTID___\" title=\"" . check_plain($ad->tooltip) . '"' . ad_link_attributes() . "><img src=\"{$image_path}\" width=\"{$ad->width}\" height=\"{$ad->height}\" alt=\"" . check_plain($ad->tooltip) . "\" /></a></div>";
  }
  else {
    $ad_image = "<div class=\"image-advertisement\" id=\"ad-{$ad->aid}\"><img src=\"{$image_path}\" width=\"{$ad->width}\" height=\"{$ad->height}\" alt=\"" . check_plain($ad->tooltip) . "\" /></div>";
  }
  return $ad_image;
}

/*****/

/**
 * Drupal _init hook.  Include ad_image_views.inc if the views.module is 
 * enabled.
 */
function ad_image_init() {
  if (function_exists('drupal_set_content')) {
    if (module_exists('views')) {
      include drupal_get_path('module', 'ad_image') . '/ad_image_views.inc';
    }
  }
}

/**
 * Implementation of hook_help().
 */
function ad_image_help($path) {
  switch ($path) {
    case 'node/add/ad#image':
      $output = t('An image or banner advertisement.');
      break;
  }
  return $output;
}
function ad_image_global_settings($edit = array()) {
  $form = array();
  $groups = module_invoke('ad', 'groups_list', TRUE);
  foreach ($groups as $tid => $group) {
    $form["group-{$tid}"] = array(
      '#type' => 'fieldset',
      '#title' => $group->name,
      '#collapsible' => TRUE,
    );
    $form["group-{$tid}"]["description-{$tid}"] = array(
      '#type' => 'markup',
      '#prefix' => '<div>',
      '#suffix' => '</div>',
      '#value' => theme_placeholder("{$group->description}"),
    );
    $format = db_fetch_object(db_query('SELECT * FROM {ad_image_format} WHERE gid = %d', $tid));
    $form["group-{$tid}"]["min-height-{$tid}"] = array(
      '#type' => 'textfield',
      '#title' => t('Minimum height'),
      '#size' => 5,
      '#maxlength' => 5,
      '#default_value' => $format->min_height ? $format->min_height : 0,
      '#description' => t('Optionally specify a minimum height in pixels for images in this group.  To specify no minimum height, enter <em>0</em>.'),
    );
    $form["group-{$tid}"]["min-width-{$tid}"] = array(
      '#type' => 'textfield',
      '#title' => t('Minimum width'),
      '#size' => 5,
      '#maxlength' => 5,
      '#default_value' => $format->min_width ? $format->min_width : 0,
      '#description' => t('Optionally specify a minimum width in pixels for images in this group.  To specify no minimum width, enter <em>0</em>.'),
    );
    $form["group-{$tid}"]["max-height-{$tid}"] = array(
      '#type' => 'textfield',
      '#title' => t('Maximum height'),
      '#size' => 5,
      '#maxlength' => 5,
      '#default_value' => $format->max_height ? $format->max_height : 0,
      '#description' => t('Optionally specify a maximum height in pixels for images in this group.  To specify no maximum height, enter <em>0</em>.'),
    );
    $form["group-{$tid}"]["max-width-{$tid}"] = array(
      '#type' => 'textfield',
      '#title' => t('Maximum width'),
      '#size' => 5,
      '#maxlength' => 5,
      '#default_value' => $format->max_width ? $format->max_width : 0,
      '#description' => t('Optionally specify a maximum width in pixels for images in this group.  To specify no maximum width, enter <em>0</em>.'),
    );
  }
  $form['save'] = array(
    '#type' => 'submit',
    '#value' => t('Save'),
  );
  return $form;
}

/**
 * Save min and max image width and height values for ad groups.
 */
function ad_image_global_settings_submit($form_id, $form_values) {
  $groups = module_invoke('ad', 'groups_list', TRUE);
  foreach ($groups as $group) {

    // TODO: Update the database schema, convert gid to tid.
    $gid = db_result(db_query('SELECT gid FROM {ad_image_format} WHERE gid = %d', $group->tid));
    if (is_numeric($gid)) {
      db_query("UPDATE {ad_image_format} SET min_width = %d, max_width = %d, min_height = %d, max_height = %d WHERE gid = %d", $form_values["min-width-{$group->tid}"], $form_values["max-width-{$group->tid}"], $form_values["min-height-{$group->tid}"], $form_values["max-height-{$group->tid}"], $group->tid);
    }
    else {
      db_query("INSERT INTO {ad_image_format} (gid, min_width, max_width, min_height, max_height) VALUES (%d, %d, %d, %d, %d)", $group->tid, $form_values["min-width-{$group->tid}"], $form_values["max-width-{$group->tid}"], $form_values["min-height-{$group->tid}"], $form_values["max-height-{$group->tid}"]);
    }
  }
  drupal_set_message('Image ad global settings updated.');
}

/**
 * Adapi implementation.
 */
function ad_image_adapi($op, &$node) {
  $output = NULL;
  switch ($op) {
    case 'load':
      $return = db_fetch_array(db_query("SELECT a.*, f.filepath FROM {ad_image} a LEFT JOIN {files} f ON a.fid = f.fid WHERE aid = %d", $node['aid']));
      $return['ad'] = '<img src="' . file_create_url($return['filepath']) . '" width="' . $return['width'] . '" height="' . $return['height'] . '" alt="' . check_plain($return['tooltip']) . '" />';
      return $return;
    case 'insert':
    case 'update':
      $image = ad_image_load_image($node);
      $fid = (int) ad_image_active_file($node->files);

      // This is ugly, but as "a" comes before "u" we don't seem to be able
      // to modify the upload module's form.  Instead, we check after the fact
      // if someone is editing images when they're not allowed, and if so we
      // prevent the ad from being saved.
      if ($op == 'update' && !ad_adaccess($node->nid, 'manage active ad')) {

        // See if fid is changing -- it's okay if new images are uploaded, it's
        // just not okay if the active fid is changed.
        if ($fid != $image->fid) {
          drupal_set_message('You do not have the necessary permissions to change the active advertisement.', 'error');

          // This causes upload_save() to simply return without making any
          // changes to the files attached to this node.
          unset($node->files);
        }
      }
      else {

        // Check that all values are valid -- this is a kludge to work around
        // bug #146147 until the problem is better understood.
        if ($image !== FALSE && (int) $image->width != 0 && (int) $image->height != 0 && (int) $image->fid != 0) {
          $node->fid = $image->fid;
          $node->width = $image->width;
          $node->height = $image->height;
        }
        else {
          $image = FALSE;
        }
      }
      if ($op == 'insert') {
        db_query("INSERT INTO {ad_image} (aid, fid, url, tooltip, width, height) VALUES(%d, %d, '%s', '%s', %d, %d)", $node->nid, $node->fid, $node->url, $node->tooltip, $node->width, $node->height);
      }
      else {
        db_query("UPDATE {ad_image} SET fid = %d, url = '%s', tooltip = '%s', width = %d, height = %d WHERE aid = %d", $node->fid, $node->url, $node->tooltip, $node->width, $node->height, $node->nid);
      }

      // No valid image has been uploaded, don't allow ad to be 'active'.
      if ($image === FALSE || !ad_image_active_file($node->files)) {
        db_query("UPDATE {ads} SET adstatus = '%s' WHERE aid = %d AND adstatus = '%s'", t('pending'), $node->nid, t('active'));
        if (db_affected_rows()) {
          drupal_set_message(t('Image validation failed, unable to mark ad as %active.  Setting ad as %pending.  If you do not see any more errors, you should now be able to set your ad as %active.', array(
            '%active' => t('active'),
            '%pending' => t('pending'),
          )), 'error');
        }
      }
      else {
        if (!$fid) {
          db_query("UPDATE {ads} SET adstatus = '%s' WHERE aid = %d AND adstatus = '%s'", t('pending'), $node->nid, t('active'));
          if (db_affected_rows()) {
            drupal_set_message(t('Unable to mark ad as <em>active</em> until uploaded image is validated.  If you do not see any more errors, you should now be able to set your ad as <em>active</em>.'), 'error');
          }
        }
      }
      break;
    case 'validate':
      if ($node->url && variable_get('ad_validate_url', 1) && !valid_url($node->url, TRUE)) {
        form_set_error('url', t('You must specify a valid %field.', array(
          '%field' => t('Destination URL'),
        )));
      }
      if (!ad_image_active_file($node->files)) {
        form_set_error('upload', t('It is required that you upload an image for your image advertisement.'));
      }
      break;
    case 'delete':
      db_query('DELETE FROM {ad_image} WHERE aid = %d', $node->nid);
      break;
    case 'form':
      return ad_image_node_form($node);
    case 'view':
      return ad_image_node_view($node);
    case 'redirect':
      return db_result(db_query('SELECT url FROM {ad_image} WHERE aid = %d', $node->nid));
    case 'type':
      return 'image';
    case 'permissions':
      if (!isset($node->adtype) || $node->adtype == 'image') {
        return array(
          'manage active ad',
        );
      }
    case 'check_install':
      if (!module_exists('upload')) {
        drupal_set_message(t("The required <em>upload module</em> is not enabled, you will not be able to upload image ads.  Please %enable the upload module, or %disable the ad_image module.", array(
          '%enable' => l('enable', 'admin/modules'),
          '%disable' => l('disable', 'admin/modules'),
        )), 'error');
      }
      if (!variable_get("upload_{$node->type}", TRUE)) {
        drupal_set_message(t('You will not be able to upload image ads until you !enable for the advertisement content type.', array(
          '!enable' => l(t('enable attachments'), 'admin/content/types/ad'),
        )), 'error');
      }
      if (empty($node)) {
        if (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) == FILE_DOWNLOADS_PRIVATE) {
          drupal_set_message(t('Your website is configured to use Drupal\'s private !method.  You have to enable "!view" permissions in addition to the ad module\'s standard "!show" permissions for all roles that you wish to view image advertisements.', array(
            '!method' => l(t('download method'), 'admin/settings/file-system'),
            '!view' => l(t('view uploaded files'), 'admin/user/access'),
            '!show' => l(t('show advertisements'), 'admin/user/access'),
          )));
        }
      }
      break;
  }
  return $output;
}

/**
 * Determine the currently active ad.
 */
function ad_image_active_file($files = array()) {
  if (is_array($files)) {
    foreach ($files as $fid => $data) {
      if (is_array($data)) {
        if ($data['list'] && !$data['remove']) {
          return $fid;
        }
      }
      else {
        if ($data->list && !$data->remove) {
          return $fid;
        }
      }
    }
  }
  return 0;
}
function ad_image_format_load($gid) {
  static $format;
  if (!is_null($format[$gid])) {
    return $format[$gid];
  }
  $format[$gid] = db_fetch_object(db_query('SELECT * FROM {ad_image_format} WHERE gid = %d', $gid));
  return $format[$gid];
}

/**
 * Validate that the size of the uploaded image is within the defined limits.
 */
function ad_image_validate_size($file, $nid) {
  $size = NULL;
  $error = FALSE;
  $edit = $_POST['edit'];
  if (is_object($file)) {

    // TODO: Detect if new terms have been set, and if so validate against
    // them, not the old ones.  See what's in $edit['taxonomy'].
    $terms = module_invoke('taxonomy', 'node_get_terms', $nid);
    if (count($terms) == 0) {

      // We need at least a single (NULL) term to be ensure we still get the
      // default image size.
      $terms[] = NULL;
    }
    foreach ($terms as $tid => $term) {
      $format = ad_image_format_load($tid);
      list($size->width, $size->height) = getimagesize($file->filepath);
      if ($size->width < $format->min_width) {
        drupal_set_message(t('The image <em>%name</em> is only %current pixels wide, which is less than the minimum of %minimum pixels allowed in the %group ad group.', array(
          '%name' => $file->filename,
          '%current' => $size->width,
          '%minimum' => $format->min_width,
          '%group' => theme_placeholder($term->name),
        )), 'error');
        $error = TRUE;
      }
      else {
        if ($format->max_width && $size->width > $format->max_width) {
          drupal_set_message(t('The image <em>%name</em> is %current pixels wide, which is more than the maximum of %maximum pixels allowed in the %group ad group.', array(
            '%name' => $file->filename,
            '%current' => $size->width,
            '%maximum' => $format->max_width,
            '%group' => theme_placeholder($term->name),
          )), 'error');
          $error = TRUE;
        }
      }
      if ($size->height < $format->min_height) {
        drupal_set_message(t('The image <em>%name</em> is only %current pixels high, which is less than the minimum of %minimum pixels allowed in the %group ad group.', array(
          '%name' => $file->filename,
          '%current' => $size->height,
          '%minimum' => $format->min_height,
          '%group' => theme_placeholder($term->name),
        )), 'error');
        $error = TRUE;
      }
      else {
        if ($format->max_height && $size->height > $format->max_height) {
          drupal_set_message(t('The image <em>%name</em> is %current pixels high, which is more than the maximum of %maximum pixels allowed in the %group ad group.', array(
            '%name' => $file->filename,
            '%current' => $size->height,
            '%maximum' => $format->max_height,
            '%group' => theme_placeholder($term->name),
          )), 'error');
          $error = TRUE;
        }
      }
    }
  }
  else {
    $error = TRUE;
    drupal_set_message('Please report error: $file is not an object, bug #146147.');
  }
  if ($error) {
    return FALSE;
  }
  else {
    return $size;
  }
}

/**
 *
 */
function ad_image_load_image($node) {
  if (is_array($node->files)) {
    foreach ($node->files as $file) {
      if (is_array($file)) {
        if ($file['list'] && file_exists($file['filepath'])) {
          $image = ad_image_validate_size((object) $file, $node->nid);
          if ($image !== FALSE) {
            $image->fid = $file['fid'];
            return $image;
          }
        }
      }
      else {
        if ($file->list && file_exists($file->filepath)) {
          $image = ad_image_validate_size($file, $node->nid);
          if ($image !== FALSE) {
            $image->fid = $file->fid;
            return $image;
          }
        }
      }
    }
  }
  return FALSE;
}

/**
 * Adapi helper function for displaying a node form.
 */
function ad_image_node_form(&$node) {
  $form = array();
  ad_image_adapi('check_install', $node);
  $form['ad_image'] = array(
    '#type' => 'fieldset',
    '#title' => t('Image'),
    '#collapsible' => TRUE,
  );
  if (is_array($node->files)) {
    $files = $node->files;
  }
  else {
    $files = module_invoke('upload', 'load', $node);
  }
  $num = sizeof($files);
  $path = NULL;
  $active = 0;
  if ($num) {
    foreach ($files as $file) {
      if ($file->list && file_exists($file->filepath)) {
        $path .= '<img src="' . file_create_url($file->filepath) . '" alt="' . check_plain($file->filename) . '" /> ';
        $image = ad_image_validate_size($file, $node->nid);
        if ($image === FALSE) {
          $path .= t('(invalid image)') . '<br />';
        }
        else {
          if (!$active++) {
            $path .= t('(active)') . '<br />';
          }
          else {
            $path .= t('(inactive)') . '<br />';
          }
        }
      }
      else {
        if (!file_exists($file->filepath)) {
          drupal_set_message(t('Unable to locate image %image.', array(
            '%image' => "{$file->filepath}",
          )));
          $path .= t('Unable to locate the uploaded image.');
        }
      }
    }
  }
  if ($path == NULL) {
    $path = t('No images have been uploaded.  Please upload an image via the <em>File attachments</em> form section below.<br />');

    // Only set error if node has been previewed or submitted.
    if (isset($_POST['edit'])) {
      form_set_error('upload', t('It is required that you upload an image for your image advertisement.'));
    }
  }
  $path .= t('<br />Only the first uploaded image that has <em>List</em> checked in the <em>File attachments</em> form section below will be displayed as an advertisement.  The image that will be displayed is marked as <em>active</em> above.');
  $form['ad_image']['image'] = array(
    '#type' => 'markup',
    '#value' => $path,
    '#prefix' => '<div class="container-inline">',
    '#suffix' => '</div>',
  );
  $form['ad_image']['url'] = array(
    '#type' => 'textfield',
    '#title' => t('Destination URL'),
    '#required' => FALSE,
    '#default_value' => $node->url,
    '#description' => t('Enter the complete URL if you want people to be redirected when they click on this advertisement.  The URL must begin with http:// or https://.  For example, %url.  If you do not enter a URL, the advertisement will not be clickable.', array(
      '%url' => t('http://www.sample.org/'),
    )),
  );
  $form['ad_image']['tooltip'] = array(
    '#type' => 'textfield',
    '#title' => t('Mouseover'),
    '#required' => FALSE,
    '#default_value' => $node->tooltip,
    '#description' => t('Optionally enter text to appear when a mouse pointer hovers over the ad image.'),
  );
  return $form;
}
function ad_image_node_view(&$node) {
  $node->content['ad'] = array(
    '#value' => ad_image_display_ad($node),
    '#weight' => -1,
  );
  if ($node->url) {
    $link = t('Links to !url.', array(
      '!url' => $node->url,
    ));
    $link = check_markup($link, $node->format, FALSE);
    $node->content['ad-link'] = array(
      '#value' => "<div class=\"links-to\">{$link}</div>",
      '#weight' => 0,
    );
  }
}

Functions

Namesort descending Description
ad_image_active_file Determine the currently active ad.
ad_image_adapi Adapi implementation.
ad_image_display_ad Function used to display the selected ad.
ad_image_format_load
ad_image_global_settings
ad_image_global_settings_submit Save min and max image width and height values for ad groups.
ad_image_help Implementation of hook_help().
ad_image_init Drupal _init hook. Include ad_image_views.inc if the views.module is enabled.
ad_image_load_image
ad_image_node_form Adapi helper function for displaying a node form.
ad_image_node_view
ad_image_validate_size Validate that the size of the uploaded image is within the defined limits.