You are here

ad_channel.module in Advertisement 5.2

Ad Channel

Copyright (c) 2008. Jeremy Andrews <jeremy@tag1consulting.com>.

File

channel/ad_channel.module
View source
<?php

/**
 * @file
 * Ad Channel
 *
 * Copyright (c) 2008.
 *   Jeremy Andrews <jeremy@tag1consulting.com>.
 */

/**
 * Implementation of hook_help().
 */
function ad_channel_help($path) {
  switch ($path) {
    case 'admin/help#ad_channel':
      $output = '<p>' . t('This module provides the ability to create advertisement channels, for which rules can be defined.') . '</p>';
      break;
    case 'admin/content/ad/channel':
    case 'admin/content/ad/channel/list':
      return '<p>' . t('This is a list of existing containers and channels that you can edit.  Containers hold channels, and channels hold advertisements.') . '</p>';
    case 'admin/content/ad/channel/container':
      return '<p>' . t('Containers help you organize your advertisement channels.  A container can hold one or more related advertisement channels.') . '</p>';
    case 'admin/content/ad/channel/channel':
      return '<p>' . t('Advertisements can be assigned to one or more advertisement channels.  Rules can then be applied to these channels.') . '</p>';
  }
  return $output;
}

/**
 * Drupal _perm hook.  Establishes permissions used by this module.
 *
 * @return  An array of permissions used by this module.
 */
function ad_channel_perm() {
  return array(
    'administer channels',
    'configure ad premier status',
  );
}

/**
 * Implementation of hook_menu.
 */
function ad_channel_menu($may_cache) {
  $items = array();
  if ($may_cache) {
    $items[] = array(
      'path' => 'admin/content/ad/channel',
      'title' => t('Channels'),
      'callback' => 'ad_channel_admin_overview',
      'type' => MENU_LOCAL_TASK,
      'weight' => 6,
    );
    $items[] = array(
      'path' => 'admin/content/ad/channel/list',
      'title' => t('List'),
      'callback' => 'ad_channel_admin_overview',
      'type' => MENU_DEFAULT_LOCAL_TASK,
      'weight' => 0,
    );
    $items[] = array(
      'path' => 'admin/content/ad/channel/container',
      'title' => t('Create container'),
      'callback' => 'drupal_get_form',
      'callback arguments' => array(
        'ad_channel_admin_container',
      ),
      'type' => MENU_LOCAL_TASK,
      'weight' => 2,
    );
    $items[] = array(
      'path' => 'admin/content/ad/channel/channel',
      'title' => t('Create channel'),
      'callback' => 'drupal_get_form',
      'callback arguments' => array(
        'ad_channel_admin_channel',
      ),
      'type' => MENU_LOCAL_TASK,
      'weight' => 4,
    );
    $items[] = array(
      'path' => 'admin/content/ad/channel/settings',
      'title' => t('Settings'),
      'callback' => 'drupal_get_form',
      'callback arguments' => array(
        'ad_channel_admin_settings',
      ),
      'type' => MENU_LOCAL_TASK,
      'weight' => 9,
    );
  }
  else {
    if (arg(3) == 'channel' && is_numeric(arg(5))) {
      if (arg(4) == 'container') {
        $conid = arg(5);
        if ($conid == 0) {

          // Can't update the default container, as it doesn't really exist.
          drupal_goto('admin/content/ad/channel');
        }
      }
      else {
        if (arg(4) == 'channel') {
          $chid = arg(5);
          if ($chid == 0) {

            // No such channel.
            drupal_goto('admin/content/ad/channel');
          }
        }
      }
      $items[] = array(
        'path' => "admin/content/ad/channel/container/{$conid}",
        'callback' => 'drupal_get_form',
        'callback arguments' => array(
          'ad_channel_admin_container',
          $conid,
        ),
        'type' => MENU_LOCAL_TASK,
      );
      $items[] = array(
        'path' => "admin/content/ad/channel/container/{$conid}/delete",
        'callback' => 'drupal_get_form',
        'callback arguments' => array(
          'ad_channel_admin_confirm_delete_container',
          $conid,
        ),
        'type' => MENU_CALLBACK,
      );
      $items[] = array(
        'path' => "admin/content/ad/channel/channel/{$chid}",
        'callback' => 'drupal_get_form',
        'callback arguments' => array(
          'ad_channel_admin_channel',
          $chid,
        ),
        'type' => MENU_LOCAL_TASK,
      );
      $items[] = array(
        'path' => "admin/content/ad/channel/channel/{$chid}/delete",
        'callback' => 'drupal_get_form',
        'callback arguments' => array(
          'ad_channel_admin_confirm_delete_channel',
          $chid,
        ),
        'type' => MENU_CALLBACK,
      );
    }
  }
  return $items;
}

/**
 * Implementation of hook_form_alter().
 * Generate a form for selecting channels to associate with an advertisement.
 */
function ad_channel_form_alter($form_id, &$form) {
  if (isset($form['type']) && $form_id == 'ad_node_form') {
    $fieldset = FALSE;
    $containers = _ad_channel_get_containers();
    foreach ($containers as $container) {
      $channels = _ad_channel_get_container_channels($container->conid);
      if (!empty($channels)) {
        if ($container->conid) {
          $fieldset = TRUE;
        }
        if ($fieldset) {
          $form['channel'][$container->conid] = array(
            '#type' => 'fieldset',
            '#title' => $container->name,
            '#collapsible' => FALSE,
            '#collapsed' => FALSE,
          );
        }
        foreach ($channels as $channel) {
          if (is_object($form['#node'])) {
            $node = $form['#node'];
            $default = isset($node->channel[$channel->chid]);
          }
          else {
            $default = 0;
          }
          $form['channel'][$container->conid]["channel-{$channel->chid}"] = array(
            '#type' => 'checkbox',
            '#title' => $channel->name,
            '#description' => $channel->description,
            '#default_value' => $default,
          );
        }
      }
    }
    if (is_array($form['channel']) && !empty($form['channel'])) {
      if (!empty($form['channel'])) {
        $form['channel'] += array(
          '#type' => 'fieldset',
          '#title' => t('Channels'),
          '#collapsible' => TRUE,
          '#collapsed' => FALSE,
        );
      }
      $form['channel']['#weight'] = -3;
      $form['channel']['#tree'] = TRUE;
    }
    $form['priority'] = array(
      '#type' => 'fieldset',
      '#access' => user_access('configure ad premiere status'),
      '#title' => t('Priority'),
      '#collapsible' => TRUE,
      '#collapsed' => FALSE,
    );
    $form['priority']['premiere'] = array(
      '#type' => 'checkbox',
      '#access' => user_access('configure ad premiere status'),
      '#title' => t('Premiere'),
      '#description' => t('An active premiere advertisement will ovverride all other non-premiere advertisements in the same channel.  As long as one or more premiere advertisements are active in a channel, non-premiere advertisements will not be displayed in that channel.'),
      '#default_value' => $node->premiere,
    );
    $form['priority']['#weight'] = -1;
  }
}

/**
 * Implementation of hook_nodeapi().
 */
function ad_channel_nodeapi($node, $op, $arg = 0) {
  switch ($op) {
    case 'load':
      return _ad_channel_load_node($node);
    case 'insert':
    case 'update':
      return _ad_channel_save_node($node);
    case 'delete':
      return _ad_channel_delete_node($node);
    case 'validate':
      return _ad_channel_validate_nodes($node);
  }
}

/**
 * Implementation of hook_ad_build_cache().
 */
function ad_channel_ad_build_cache() {
  $cache = array();
  $ads = array();
  $active = db_query("SELECT aid FROM {ads} WHERE adstatus = 'active'");
  while ($ad = db_fetch_object($active)) {

    // cache channel<->node relation
    $result = db_query('SELECT chid FROM {ad_channel_node} WHERE nid = %d', $ad->aid);
    while ($channel = db_fetch_object($result)) {
      $ads[$ad->aid][$channel->chid] = $channel->chid;

      //$ads[$channel->chid][$ad->aid] = $ad->aid;
    }
  }
  $channels = array();
  $result = db_query('SELECT chid, display, urls FROM {ad_channel}');
  while ($channel = db_fetch_object($result)) {
    $channels[$channel->chid] = $channel;
  }
  $result = db_query("SELECT p.aid, p.priority FROM {ads} a LEFT JOIN {ad_priority} p ON a.aid = p.aid WHERE a.adstatus = 'active' AND p.priority = 1");
  while ($priority = db_fetch_object($result)) {
    $premiere[$priority->aid] = $priority->aid;
  }
  $cache['channel']['ads'] = $ads;
  $cache['channel']['channels'] = $channels;
  $cache['channel']['display'] = variable_get('ad_channel_display', 0);
  $cache['premiere'] = $premiere;
  $cache['channel']['hook_filter'] = array(
    'weight' => 0,
    'file' => drupal_get_path('module', 'ad_channel') . '/ad_channel.inc',
    'function' => 'ad_channel_cache_filter',
  );
  return $cache;
}

/***/

/**
 * Settings form.
 */
function ad_channel_admin_settings() {
  $form = array();
  $form['ad_channel_display'] = array(
    '#type' => 'radios',
    '#title' => t('Display advertisements not assigned to any channel'),
    '#options' => array(
      t('Only if no matching advertisements are found in the active channels'),
      t('Always'),
      t('Never'),
    ),
    '#default_value' => variable_get('ad_channel_display', 0),
    '#description' => t('By default, advertisements will first be selected out of the active channels, and if none are found they will be selected out of advertisements not assigned to any channel.  If you select "Always", advertisements will be selected out of the active channels and from advertisements not assigned to any channels.  If you select "Never", advertisements will only be selected out of the active channels, and advertisements not assigned to any channel will not ever be displayed.'),
  );
  return system_settings_form($form);
}

/**
 * Load channels associated with specified node.
 */
function _ad_channel_load_node($node) {
  $result = db_query('SELECT chid FROM {ad_channel_node} WHERE nid = %d', $node->nid);
  $output['channel'] = array();
  while ($chid = db_fetch_object($result)) {
    $output['channel'][$chid->chid] = $chid->chid;
  }

  // currently 0 or 1, with one being a 'premiere' advertisement.
  $output['premiere'] = (int) db_result(db_query('SELECT priority FROM {ad_priority} WHERE aid = %d', $node->nid));
  return $output;
}

/**
 * Save channels associated with added or updated node.
 */
function _ad_channel_save_node($node) {

  // delete old channel information, then add new
  db_query('DELETE FROM {ad_channel_node} WHERE nid = %d', $node->nid);
  $channels = _ad_channel_get_enabled($node);
  foreach ($channels as $chid) {
    db_query('INSERT INTO {ad_channel_node} (chid, nid) VALUES(%d, %d)', $chid, $node->nid);
  }
  if (user_access('configure ad premiere status')) {
    db_query('UPDATE {ad_priority} SET priority = %d WHERE aid = %d', $node->premiere, $node->nid);
    if (!db_affected_rows()) {
      db_query('INSERT INTO {ad_priority} (aid, priority) VALUES(%d, %d)', $node->nid, $node->premiere);
    }
  }
}

/**
 * Delete channel information associated with node.
 */
function _ad_channel_delete_node($node) {
  if ($node->nid) {
    db_query('DELETE FROM {ad_channel_node} WHERE nid = %d', $node->nid);
    db_query('DELETE FROM {ad_priority} WHERE aid = %d', $node->nid);
  }
}

/**
 * Be sure that the enabled channels actually can be enabled.
 */
function _ad_channel_validate_nodes($node) {
  $channels = _ad_channel_get_enabled($node);
  foreach ($channels as $chid) {
    $channel = _ad_channel_get_channels($chid);
    $taxonomy = is_array($node->taxonomy) ? $node->taxonomy : array();
    $groups = unserialize($channel->groups);
    if (!empty($groups)) {
      $enabled = FALSE;
      foreach ($groups as $group) {
        if ($group) {
          $enabled = TRUE;
          break;
        }
      }
      if ($enabled) {
        $ad_groups = taxonomy_get_tree(_ad_get_vid());
        foreach ($ad_groups as $ad_group) {
          if (is_array($taxonomy[$ad_group->vid]) && isset($taxonomy[$ad_group->vid][$ad_group->tid]) && isset($groups[$ad_group->tid]) && !$groups[$ad_group->tid] && !isset($groups[''])) {
            form_set_error("channel[{$channel->conid}][channel-{$chid}]", t('The %channel channel does not allow advertisements from the %group group.', array(
              '%channel' => $channel->name,
              '%group' => $ad_group->name,
            )));
          }
        }
      }
    }
  }
}

/**
 * Retrive list of enabled channels from node object.
 */
function _ad_channel_get_enabled($node) {
  static $enabled = array();
  if (!isset($enabled[$node->nid])) {
    $enabled[$node->nid] = array();
    if (is_array($node->channel) && !empty($node->channel)) {
      foreach ($node->channel as $conid => $channels) {
        foreach ($channels as $id => $enable) {
          if ($enable) {
            $chid = explode('-', $id);
            $enabled[$node->nid][] = $chid[1];
          }
        }
      }
    }
  }
  return $enabled[$node->nid];
}

/**
 * Display containers and channels.
 */
function ad_channel_admin_overview() {

  // Stay consistent with other advertisement adminsitrative pages, and display
  // a warning if something is not configured properly.
  _ad_check_install();
  drupal_add_css(drupal_get_path('module', 'ad_channel') . '/ad_channel.css');
  $containers = _ad_channel_get_containers();
  if (count($containers)) {
    $header = array(
      t('Name'),
      t('Options'),
    );
    $output = '<div id="ad-channel">';
    foreach ($containers as $conid => $container) {
      $channels = _ad_channel_get_container_channels($conid);
      if ($conid > 0 || count($channels)) {
        if ($conid > 0) {
          $description = '<div class="name">' . l($container->name, "admin/content/ad/channel/container/{$conid}/edit") . "</div>\n";
        }
        else {
          $description = '<div class="name">' . $container->name . "</div>\n";
        }
        if ($container->description) {
          $description .= '<div class="description">' . filter_xss_admin($container->description) . "</div>\n";
        }
        $rows[] = array(
          array(
            'data' => $description,
            'class' => 'container',
            'colspan' => 2,
          ),
        );
      }
      foreach ($channels as $chid => $channel) {
        $description = "<div style=\"margin-left: 30px;\">\n";
        $description .= ' <div class="name">' . $channel->name . "</div>\n";
        if ($channel->description) {
          $description .= ' <div class="description">' . filter_xss_admin($channel->description) . "</div>\n";
        }
        $description .= "</div>\n";
        $rows[] = array(
          array(
            'data' => $description,
            'class' => 'channel',
          ),
          l(t('edit'), "admin/content/ad/channel/channel/{$channel->chid}/edit") . '&nbsp;&nbsp;&nbsp;' . l(t('delete'), "admin/content/ad/channel/channel/{$channel->chid}/delete"),
        );
      }
    }
    $output .= theme('table', $header, $rows);
    $output .= '</div>';
  }
  return $output;
}

/**
 * Load one or more containers, caching the results.
 */
function _ad_channel_get_containers($conid = 0) {
  static $cache;
  if (!isset($cache[$conid])) {
    if ($conid) {
      $cache[$conid] = db_fetch_object(db_query('SELECT * FROM {ad_channel_container} WHERE conid = %d', $conid));
    }
    else {

      // Get all manually defined channels.
      $result = db_query('SELECT conid, name, description, weight FROM {ad_channel_container} ORDER BY weight ASC');
      while ($container = db_fetch_object($result)) {
        $containers[$container->conid] = $container;
      }

      // Define default 'No container'.
      $none->conid = 0;
      $none->name = t('No container');
      $none->weight = 0;
      $containers[0] = $none;
      $cache[$conid] = $containers;
    }
  }
  return $cache[$conid];
}

/**
 * Load one or more channels, caching the results.
 */
function _ad_channel_get_container_channels($conid = 0) {
  static $cache;
  if (!isset($cache[$conid])) {
    $channels = array();
    $result = db_query('SELECT chid, name, description, weight FROM {ad_channel} WHERE conid = %d ORDER BY weight ASC', $conid);
    while ($channel = db_fetch_object($result)) {
      $channels[$channel->chid] = $channel;
    }
    $cache[$conid] = $channels;
  }
  return $cache[$conid];
}

/**
 * Load one or more channels.
 */
function _ad_channel_get_channels($chid = 0) {
  if ($chid) {
    return db_fetch_object(db_query('SELECT * FROM {ad_channel} WHERE chid = %d', $chid));
  }
  else {
    $channels = array();
    $result = db_query('SELECT chid, name, description FROM {ad_channel}');
    while ($channel = db_fetch_object($result)) {
      $channels[$channel->chid] = $channel;
    }
    return $channels;
  }
}

/**
 * Administrative page for creating or editing containers.
 */
function ad_channel_admin_container($conid = 0) {
  $form = array();
  if ($conid) {
    $container = _ad_channel_get_containers($conid);
    if (empty($container)) {
      drupal_goto('admin/content/ad/channel');
    }
    $form['conid'] = array(
      '#type' => 'hidden',
      '#value' => $conid,
    );
  }
  $form['name'] = array(
    '#type' => 'textfield',
    '#title' => t('Container name'),
    '#required' => TRUE,
    '#description' => t('Channel containers can be used to help organize channels, but they are not required.'),
    '#default_value' => $conid ? $container->name : '',
  );
  $form['description'] = array(
    '#type' => 'textarea',
    '#title' => t('Description'),
    '#description' => t('The channel container description can be used to help you define the purpose of your different channels.  The descriptions are only visible to advertisement administrators.'),
    '#default_value' => $conid ? $container->description : '',
  );
  $form['weight'] = array(
    '#type' => 'weight',
    '#title' => t('Weight'),
    '#description' => t('When listing containers, those with the lighter (smaller) weights get listed before containers with heavier (larger) weights.  Containers with equal weights are sorted alphabetically.'),
    '#default_value' => $conid ? $container->weight : 0,
  );
  if ($conid) {
    $form['update'] = array(
      '#type' => 'submit',
      '#value' => t('Update'),
    );
    $form['delete'] = array(
      '#type' => 'submit',
      '#value' => t('Delete'),
    );
  }
  else {
    $form['create'] = array(
      '#type' => 'submit',
      '#value' => t('Create'),
    );
  }
  $form['cancel'] = array(
    '#type' => 'markup',
    '#value' => l(t('Cancel'), 'admin/content/ad/channel'),
  );
  return $form;
}

/**
 * Validate the container.
 */
function ad_channel_admin_container_validate($form_id, $form_values) {
  $conid = 0;
  if ($form_values['op'] == t('Create')) {
    $conid = db_result(db_query("SELECT conid FROM {ad_channel_container} WHERE name = '%s'", $form_values['name']));
  }
  else {
    if ($form_values['op'] == t('Update')) {
      $conid = db_result(db_query("SELECT conid FROM {ad_channel_container} WHERE name = '%s' AND conid != %d", $form_values['name'], $form_values['conid']));
    }
  }
  if ($conid) {
    form_set_error('name', t('A container named %name already exists.', array(
      '%name' => $form_values['name'],
    )));
  }
}

/**
 * Save the container.
 */
function ad_channel_admin_container_submit($form_id, $form_values) {
  switch ($form_values['op']) {
    case t('Create'):
      db_query("INSERT INTO {ad_channel_container} (name, description, weight) VALUES('%s', '%s', %d)", $form_values['name'], $form_values['description'], $form_values['weight']);
      drupal_set_message(t('The %name container has been created.', array(
        '%name' => $form_values['name'],
      )));
      break;
    case t('Update'):
      db_query("UPDATE {ad_channel_container} SET name = '%s', description = '%s', weight = '%s' WHERE conid = %d", $form_values['name'], $form_values['description'], $form_values['weight'], $form_values['conid']);
      drupal_set_message(t('The %name container has been updated.', array(
        '%name' => $form_values['name'],
      )));
      break;
    case t('Delete'):
      drupal_goto('admin/content/ad/channel/container/' . $form_values['conid'] . '/delete');
  }
  drupal_goto('admin/content/ad/channel');
}

/**
 * Confirm whether or not to delete container, and the contained channels.
 */
function ad_channel_admin_confirm_delete_container($conid) {
  $form = array();
  $container = _ad_channel_get_containers($conid);
  $form['conid'] = array(
    '#type' => 'value',
    '#value' => $conid,
  );
  return confirm_form($form, t('Are you sure you want to delete the %name container?', array(
    '%name' => $container->name,
  )), 'admin/content/ad/channel', t('Any channels currently assigned to the %name container will not be deleted, they will be reassigned. <p>This action can not be undone.', array(
    '%name' => $container->name,
  )), t('Delete'), t('Cancel'));
}

/**
 * Delete a container.
 */
function ad_channel_admin_confirm_delete_container_submit($form_id, $form_values) {
  $container = _ad_channel_get_containers($form_values['conid']);
  if ($container->conid) {
    db_query('UPDATE {ad_channel} SET conid = 0 WHERE conid = %d', $container->conid);
    db_query('DELETE FROM {ad_channel_container} WHERE conid = %d', $container->conid);
    drupal_set_message(t('The %name container has been deleted.', array(
      '%name' => $container->name,
    )));
  }
  drupal_goto('admin/content/ad/channel');
}

/**
 * Administrative page for creating or editing channels.
 */
function ad_channel_admin_channel($chid = 0) {
  $form = array();
  if ($chid) {
    $channel = _ad_channel_get_channels($chid);
    if (empty($channel)) {
      drupal_goto('admin/content/ad/channel');
    }
    $form['chid'] = array(
      '#type' => 'hidden',
      '#value' => $chid,
    );
  }
  $form['name'] = array(
    '#type' => 'textfield',
    '#required' => TRUE,
    '#title' => t('Channel name'),
    '#description' => t('Enter a short, descriptive name for your channel.'),
    '#default_value' => $chid ? $channel->name : '',
  );
  $form['description'] = array(
    '#type' => 'textarea',
    '#title' => t('Description'),
    '#description' => t('Enter a full description of your channel.'),
    '#default_value' => $chid ? $channel->description : '',
  );
  $result = db_query('SELECT conid, name FROM {ad_channel_container} ORDER BY weight ASC');
  $containers = array(
    t('<none>'),
  );
  while ($container = db_fetch_object($result)) {
    $containers[$container->conid] = $container->name;
  }
  if (sizeof($containers) == 1) {
    $containers = array(
      t('No containers have been created.'),
    );
  }
  $form['conid'] = array(
    '#type' => 'select',
    '#title' => t('Container'),
    '#options' => $containers,
    '#description' => t('Optionally assign your channel to a container.  Containers can be used to help organize your channels, but they are not required.'),
    '#default_value' => $chid ? $channel->conid : 0,
  );
  $form['weight'] = array(
    '#type' => 'weight',
    '#title' => t('Weight'),
    '#description' => t('When listing channels, those with the lighter (smaller) weights get listed before channels with heavier (larger) weights.  Channels with equal weights are sorted alphabetically.'),
    '#default_value' => $chid ? $channel->weight : 0,
  );

  // URL rules
  $form['URL_rules'] = array(
    '#type' => 'fieldset',
    '#title' => t('URL rules'),
    '#collapsible' => TRUE,
    '#collasped' => FALSE,
  );
  $form['URL_rules']['display'] = array(
    '#type' => 'radios',
    '#title' => t('Display advertisements from this channel on specific URLs'),
    '#options' => array(
      t('Display advertisements on every URL except the listed URLs.'),
      t('Display advertisements only on the listed URLs.'),
    ),
    '#default_value' => $chid ? $channel->display : 0,
  );
  $form['URL_rules']['urls'] = array(
    '#type' => 'textarea',
    '#title' => t('Paths'),
    '#description' => t("Enter one URL per line, including the 'http://' or 'https:/'.  The '*' character is a wildcard.  Example URLs are <em>http://www.example.com/blog</em> for the blog page and <em>http://www.example.com/blog/*</em> for every personal blog."),
    '#default_value' => $chid ? unserialize($channel->urls) : '',
  );

  // Group rules
  $groups = taxonomy_get_tree(_ad_get_vid());
  $collapsed = is_array($groups) && !empty($groups) ? FALSE : TRUE;
  $form['group_rules'] = array(
    '#type' => 'fieldset',
    '#title' => t('Ad group rules'),
    '#collapsible' => TRUE,
    '#collapsed' => $collapsed,
  );
  if (!$collapsed) {
    foreach ($groups as $group) {
      $options[$group->tid] = $group->name;
    }
    $form['group_rules']['groups'] = array(
      '#type' => 'checkboxes',
      '#title' => t('Allow advertisements from specific ad groups'),
      '#options' => $options,
      '#prefix' => '<div>',
      '#suffix' => '</div>',
      '#description' => t('By selecting one or more groups, only advertisements from the selected group(s) will be allowed to be added to this channel.  If no groups are selected, any advertisement can be added to this channel regardless of its group.'),
      '#default_value' => $chid ? unserialize($channel->groups) : '',
    );
  }
  else {
    $form['group_rules']['none'] = array(
      '#type' => 'markup',
      '#value' => t('No ad groups have been created.'),
      '#prefix' => '<div>',
      '#suffix' => '</div>',
    );
  }
  if ($chid) {
    $form['update'] = array(
      '#type' => 'submit',
      '#value' => t('Update'),
    );
    $form['delete'] = array(
      '#type' => 'submit',
      '#value' => t('Delete'),
    );
  }
  else {
    $form['submit'] = array(
      '#type' => 'submit',
      '#value' => t('Create'),
    );
  }
  $form['cancel'] = array(
    '#type' => 'markup',
    '#value' => l(t('Cancel'), 'admin/content/ad/channel'),
  );
  return $form;
}

/**
 * Validate the channel.
 */
function ad_channel_admin_channel_validate($form_id, $form_values) {
  $chid = 0;
  if ($form_values['op'] == t('Create')) {
    $chid = db_result(db_query("SELECT chid FROM {ad_channel} WHERE name = '%s'", $form_values['name']));
  }
  else {
    if ($form_values['op'] == t('Update')) {
      $chid = db_result(db_query("SELECT chid FROM {ad_channel} WHERE name = '%s' AND chid != %d", $form_values['name'], $form_values['chid']));
    }
  }
  if ($chid) {
    form_set_error('name', t('A channel named %name already exists.', array(
      '%name' => $form_values['name'],
    )));
  }
}

/**
 * Save the channel.
 */
function ad_channel_admin_channel_submit($form_id, $form_values) {
  switch ($form_values['op']) {
    case t('Create'):
      db_query("INSERT INTO {ad_channel} (name, description, conid, weight, display, urls, groups) VALUES('%s', '%s', %d, %d, %d, '%s', '%s')", $form_values['name'], $form_values['description'], $form_values['conid'], $form_values['weight'], $form_values['display'], serialize($form_values['urls']), serialize($form_values['groups']));
      drupal_set_message(t('The %name channel has been created.', array(
        '%name' => $form_values['name'],
      )));
      break;
    case t('Update'):
      $groups = array();

      // Don't store information about groups that no longer exist.
      if (is_array($form_values['groups'])) {
        $ad_groups = taxonomy_get_tree(_ad_get_vid());
        foreach ($ad_groups as $ad_group) {
          if (isset($form_values['groups'][$ad_group->tid])) {
            $groups[$ad_group->tid] = $form_values['groups'][$ad_group->tid];
          }
        }
      }
      db_query("UPDATE {ad_channel} SET name = '%s', description = '%s', conid = %d, weight = %d, display = %d, urls = '%s', groups = '%s' WHERE chid = %d", $form_values['name'], $form_values['description'], $form_values['conid'], $form_values['weight'], $form_values['display'], serialize($form_values['urls']), serialize($groups), $form_values['chid']);
      drupal_set_message(t('The %name channel has been updated.', array(
        '%name' => $form_values['name'],
      )));
      break;
    case t('Delete'):
      drupal_goto('admin/content/ad/channel/channel/' . $form_values['chid'] . '/delete');
  }
  drupal_goto('admin/content/ad/channel');
}

/**
 * Confirm whether or not to delete container, and the contained channels.
 */
function ad_channel_admin_confirm_delete_channel($chid) {
  $form = array();
  $channel = _ad_channel_get_channels($chid);
  $form['chid'] = array(
    '#type' => 'value',
    '#value' => $chid,
  );
  return confirm_form($form, t('Are you sure you want to delete the %name channel?', array(
    '%name' => $channel->name,
  )), 'admin/content/ad/channel', t('Any advertisements currently assigned to the %name channel will not be deleted, they will be reassigned. <p>This action can not be undone.', array(
    '%name' => $channel->name,
  )), t('Delete'), t('Cancel'));
}

/**
 * Delete a channel.
 */
function ad_channel_admin_confirm_delete_channel_submit($form_id, $form_values) {
  $channel = _ad_channel_get_channels($form_values['chid']);
  if ($channel->chid) {
    db_query('DELETE FROM {ad_channel} WHERE chid = %d', $channel->chid);
    drupal_set_message(t('The %name channel has been deleted.', array(
      '%name' => $channel->name,
    )));
  }
  drupal_goto('admin/content/ad/channel');
}

Functions

Namesort descending Description
ad_channel_admin_channel Administrative page for creating or editing channels.
ad_channel_admin_channel_submit Save the channel.
ad_channel_admin_channel_validate Validate the channel.
ad_channel_admin_confirm_delete_channel Confirm whether or not to delete container, and the contained channels.
ad_channel_admin_confirm_delete_channel_submit Delete a channel.
ad_channel_admin_confirm_delete_container Confirm whether or not to delete container, and the contained channels.
ad_channel_admin_confirm_delete_container_submit Delete a container.
ad_channel_admin_container Administrative page for creating or editing containers.
ad_channel_admin_container_submit Save the container.
ad_channel_admin_container_validate Validate the container.
ad_channel_admin_overview Display containers and channels.
ad_channel_admin_settings Settings form.
ad_channel_ad_build_cache Implementation of hook_ad_build_cache().
ad_channel_form_alter Implementation of hook_form_alter(). Generate a form for selecting channels to associate with an advertisement.
ad_channel_help Implementation of hook_help().
ad_channel_menu Implementation of hook_menu.
ad_channel_nodeapi Implementation of hook_nodeapi().
ad_channel_perm Drupal _perm hook. Establishes permissions used by this module.
_ad_channel_delete_node Delete channel information associated with node.
_ad_channel_get_channels Load one or more channels.
_ad_channel_get_containers Load one or more containers, caching the results.
_ad_channel_get_container_channels Load one or more channels, caching the results.
_ad_channel_get_enabled Retrive list of enabled channels from node object.
_ad_channel_load_node Load channels associated with specified node.
_ad_channel_save_node Save channels associated with added or updated node.
_ad_channel_validate_nodes Be sure that the enabled channels actually can be enabled.