Newer
Older
<?php
// $Id$
Alexander Shvets
committed
/**
* @file
* An advertising system for Drupal powered websites.
*
* Copyright (c) 2005-2009.
* Jeremy Andrews <jeremy@tag1consulting.com>.
Alexander Shvets
committed
*/
Alexander Shvets
committed
/**
* Implementation of hook_theme().
*/
function ad_theme() {
return array(
'ad_display' => array(
'file' => 'ad.module',
'arguments' => array(
'group' => NULL,
'display' => NULL,
'method' => 'javascript',
),
),
'ad_status_display' => array(
'file' => 'ad.module',
'arguments' => array(
'node' => NULL,
),
),
'ad_statistics_display' => array(
Alexander Shvets
committed
'file' => 'ad.pages.inc',
'arguments' => array(
'statistics' => NULL,
),
),
'node_ad' => array(
Alexander Shvets
committed
'file' => 'ad.pages.inc',
'arguments' => array(
'node' => NULL,
'yield_form' => TRUE,
),
),
'ad_admin_ads' => array(
Alexander Shvets
committed
'file' => 'ad.admin.inc',
'arguments' => array(
'form' => NULL,
),
),
'ad_filters' => array(
Alexander Shvets
committed
'file' => 'ad.admin.inc',
'arguments' => array(
'form' => NULL,
),
),
'ad_filter_form' => array(
Alexander Shvets
committed
'file' => 'ad.admin.inc',
'arguments' => array(
'form' => NULL,
),
),
);
* Use this function to display ads from a specified group.
*
* @param $group
* @param $quantity
* Optionally specify the number of unique ads to display.
* @param $options
* Any number of options from this list: hostid, nids.
global $base_url;
$adserve = variable_get('adserve', '');
$adserveinc = variable_get('adserveinc', '');
if (empty($adserve) || empty($adserveinc)) {
Alexander Shvets
committed
_ad_check_installation();
drupal_set_message(t('Ads cannot be displayed. The ad module is <a href="@misconfigured">misconfigured</a>, failed to locate the required <em>serve.php</em> ond/or <em>adserve.inc</em> file.', array('@misconfigured' => url('admin/content/ad/configure'))), 'error');
Alexander Shvets
committed
_ad_check_installation();
return (t('The ad module is <a href="@misconfigured">misconfigured</a>.', array('@misconfigured' => url('admin/content/ad/configure'))));
if (!isset($options['ad_display'])) {
$options['ad_display'] = variable_get('ad_display', 'javascript');
$options['tids'] = $group;
}
$options['cache'] = variable_get('ad_cache', 'none');
case 'raw':
require_once(drupal_get_path('module', 'ad') .'/adserve.inc');
require_once(drupal_get_path('module', 'ad') .'/adcache.inc');
$query['m'] = $options['ad_display'];
if (isset($options['hostid'])) {
$query['k'] = $options['hostid'];
// Allow external cache files to define additional display variables.
$query['c'] = $options['cache'];
$cache_variables = module_invoke('ad_cache_'. $options['cache'], 'adcacheapi', 'display_variables', array());
if (is_array($cache_variables)) {
foreach ($cache_variables as $key => $value) {
}
}
}
// Allow ad_type modules to define additional display variables.
$type_variables = module_invoke_all('adapi', 'display_variables', array());
if (is_array($type_variables)) {
foreach ($type_variables as $key => $value) {
if (isset($options['url'])) {
$query['u'] = $options['url'];
}
else {
$query['u'] = $_GET['q'];
if ($alias = drupal_get_path_alias($_GET['q'])) {
$query['l'] = $alias;
}
$src = url($base_url .'/'. $adserve, array('query' => $query));
// TODO: We need to know the IFrame size before it is displayed. This
// limits the flexibility of what can be displayed in these frames.
// For now we'll have a global value, later we'll add per-group
// over-rides.
$append = 'frameborder="'. variable_get('ad_iframe_frameborder', 0) .'" ';
$append .= 'scrolling="'. variable_get('ad_iframe_scroll', 'auto') .'" ';
Alexander Shvets
committed
$append .= 'name="'. $group .'" ';
Alexander Shvets
committed
$append .= 'height="'. $height .'" ';
Alexander Shvets
committed
$append .= 'width="'. $width .'" ';
$output = '<iframe src="'. htmlentities($src) ."\" $append></iframe>";
else if ($options['ad_display'] == 'jquery') {
// The theme function uses this to generate a CSS id for jQuery to use.
$output = $src;
}
$output = "<script type='text/javascript' src='". htmlentities($src) ."'></script>";
return theme('ad_display', $group, $output, $options['ad_display']);
}
else {
return theme('ad_display', 'none', "<!-- Enable 'show advertisements' permission if you wish to display ads here. -->");
}
}
/**
* Function to display the actual advertisement to the screen. Wrap it in a
* theme function to make it possible to customize in your own theme.
*/
function theme_ad_display($group, $display, $method = 'javascript') {
static $id = -1;
// Increment counter for displaying multiple advertisements on the page.
$id++;
// The naming convention for the id attribute doesn't allow commas.
$group = preg_replace('/[,]/', '+', $group);
if ($method == 'jquery') {
return "\n<div class=\"advertisement group-$group\" id=\"group-id-$id\">\n <script type=\"text/javascript\">\n//<![CDATA[\n $(document).ready(function(){ jQuery(\"div#group-id-$id\").load(\"$display\"); });\n //]]>\n </script>\n</div>\n";
else if ($method == 'raw') {
return $display;
}
else {
return "\n<div class=\"advertisement group-$group\" id=\"group-id-$group\">$display</div>\n";
}
}
/**
* Update click counter then redirect host to ad's target URL.
*/
global $user;
$hostid = isset($_GET['hostid']) ? $_GET['hostid'] : '';
$extra = isset($_GET['extra']) ? $_GET['extra'] : '';
if (function_exists('click_filter_status')) {
$status = click_filter_status($aid, $hostid);
}
else {
$status = 0;
}
$url = isset($_GET['u']) ? $_GET['u'] : '';
if (!isset($url) || !valid_url($url)) {
db_query("INSERT INTO {ad_clicks} (aid, uid, status, hostname, user_agent, adgroup, extra, hostid, url, timestamp) VALUES (%d, %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', %d)", $aid, $user->uid, $status, ip_address(), $_SERVER['HTTP_USER_AGENT'], $group, $extra, $hostid, $url, time());
watchdog('ad', 'Clicked %type ad aid %aid hostid %hostid.', array('%type' => $adtype, '%aid' => $aid, '%hostid' => $hostid));
if (function_exists('click_filter_status') && ($status == CLICK_VALID)) {
ad_statistics_increment($aid, 'click', $group, $hostid);
}
else if (!function_exists('click_filter_status')) {
// We're not filtering clicks, so all clicks are valid.
ad_statistics_increment($aid, 'click', $group, $hostid);
}
// Determine where we're supposed to redirect the user.
$adtype = db_result(db_query('SELECT adtype FROM {ads} WHERE aid = %d', $aid));
$url = module_invoke('ad_'. $adtype, 'adapi', 'redirect', $node);
if (isset($url)) {
header('Location: '. $url);
}
else {
watchdog('ad', 'Ad redirection failed for aid %aid hostid %hostid, failed to load destination URL. ', array('%aid' => $aid, '%hostid' => $hostid));
drupal_goto('');
}
}
/**
* Ad API Helper Function:
* Append all necessary attributes to <a> tags.
*/
function ad_link_attributes() {
}
/**
* Ad API Helper Function:
* Provide XHTML-strict-compatible target window onclick-handlers based on
* global configuration.
*/
function ad_link_target() {
switch (variable_get('ad_link_target', '_self')) {
case '_blank':
$target = array('onclick' => 'window.open(this.href); return false;');
break;
case '_parent':
$target = array('onclick' => 'window.parent.location = this.href; return false;');
break;
case '_top':
$target = array('onclick' => 'window.top.location = this.href; return false;');
break;
default:
break;
}
return $target;
}
/**
* Force the cache to be flushed.
*/
function ad_rebuild_cache($verbose = FALSE) {
$cache = variable_get('ad_cache', 'none');
$build = "ad_cache_{$cache}_build";
if (function_exists($build)) {
if ($verbose) {
drupal_set_message('Rebuilding ad cache.');
}
$build();
}
}
/**
* Ad API Helper Function:
* Append rel="nofollow" if globally enabled.
*/
function ad_link_nofollow() {
if (variable_get('ad_link_nofollow', 0)) {
/**
* Increment action counter.
*/
function ad_statistics_increment($aid, $action, $group = NULL, $hostid = NULL) {
// Update action statistics.
db_query("UPDATE {ad_statistics} SET count = count + 1 WHERE date = %d AND aid = %d AND action = '%s' AND adgroup = '%s' AND hostid = '%s'", date('YmdH'), $aid, $action, $group, $hostid);
// If column doesn't already exist, we need to add it.
if (!db_affected_rows()) {
db_query("INSERT INTO {ad_statistics} (aid, adgroup, hostid, date, action, count) VALUES(%d, '%s', '%s', %d, '%s', 1)", $aid, $group, $hostid, date('YmdH'), $action);
// If another process already added this row our INSERT will fail, if so we
// still need to increment it so we don't loose an action.
if (!db_affected_rows()) {
db_query("UPDATE {ad_statistics} SET count = count + 1 WHERE date = %d AND aid = %d AND action = '%s' AND adgroup = '%s' AND hostid = '%s'", date('YmdH'), $aid, $action, $group, $hostid);
$event = array('aid' => $aid, 'action' => $action, 'hostid' => $hostid);
module_invoke_all('adapi', 'statistics_increment', $event);
/**
* Return an array with all status values user has permission to set.
* A user with 'administer advertisements' permission can update any status.
*/
function ad_status_array($aid = 0, $status = NULL) {
$permissions = array();
// mark status as pending
if (user_access('administer advertisements') ||
$status == 'pending' || $status == NULL ||
ad_permission($aid, 'set status as pending')) {
$permissions['pending'] = t('This advertisement is currently waiting for administrative approval.');
$status == 'approved' ||
($status == 'pending' &&
ad_permission($aid, 'set status from pending to approved'))) {
$permissions['approved'] = t('This advertisement has been approved and is currently waiting to be activated.');
}
// mark status as active (from pending, approved, or offline)
$status == 'active' ||
($status == 'approved' &&
ad_permission($aid, 'set status from approved to active')) ||
($status == 'offline' &&
ad_permission($aid, 'set status from offline to active'))) {
$permissions['active'] = t('This advertisement is actively being displayed.');
}
// mark status as offline (from pending, approved, or active)
$status == 'offline' ||
($status == 'approved' &&
ad_permission($aid, 'set status from approved to offline')) ||
($status == 'active' &&
ad_permission($aid, 'set status from active to offline'))) {
$permissions['offline'] = t('This advertisement has been temporarily disabled by its owner and is not currently being displayed.');
}
// mark status as expired (from active or offline)
$status == 'expired' ||
($status == 'active' &&
ad_permission($aid, 'set status from active to expired')) ||
($status == 'offline' &&
ad_permission($aid, 'set status from offline to expired'))) {
$permissions['expired'] = t('This advertisement has expired and is no longer being displayed.');
}
// mark status as denied (from pending or any)
$status == 'denied' ||
($status == 'pending' &&
ad_permission($aid, 'set status from pending to denied')) ||
ad_permission($aid, 'set status as denied')) {
$permissions['denied'] = t('This advertisement was refused by the site administrator and will not be displayed.');
}
return $permissions;
/**
* Display the status of the currently viewed ad.
*/
function theme_ad_status_display($node) {
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
if (isset($node->adstatus)) {
$status_array = ad_status_array($node->nid, $node->adstatus);
$output = '<div class="adstatus">';
$output .= '<p>'. t($status_array[$node->adstatus]) .'</p>';
switch ($node->adstatus) {
case 'approved':
if ($node->autoactivate) {
$output .= '<p>'. t('This advertisement will be automatically activated on %timestamp, in %time.', array('%timestamp' => format_date($node->autoactivate, 'large'), '%time' => format_interval($node->autoactivate - time()))) .'</p>';
}
break;
case 'active':
$activated = db_result(db_query("SELECT activated FROM {ads} WHERE aid = %d", $node->nid));
if ($activated) {
$output .= '<p>'. t('This advertisement has been active since %date.', array('%date' => format_date($activated, 'large'))) .'</p>';
}
if ($node->autoexpire) {
$output .= '<p>'. t('This advertisement will expire on %timestamp, in %time.', array('%timestamp' => format_date($node->autoexpire, 'large'), '%time' => format_interval($node->autoexpire - time()))) .'</p>';
}
if ($node->maxviews) {
$views = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'view' AND date >= %d", $node->nid, date('YmdH', $node->activated)));
$output .= '<p>'. t('This advertisement will expire after %left more impressions.', array('%left' => $node->maxviews - $views)) .'</p>';
}
if ($node->maxclicks) {
$clicks = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'click' AND date >= %d", $node->nid, date('YmdH', $node->activated)));
$output .= '<p>'. t('This advertisement will expire after %left more clicks.', array('%left' => $node->maxclicks - $clicks)) .'</p>';
}
break;
case 'expired':
$expired = db_result(db_query("SELECT expired FROM {ads} WHERE aid = %d", $node->nid));
if ($expired) {
$output .= '<p>'. t('This advertisement expired %date.', array('%date' => format_date($expired, 'large'))) .'</p>';
}
break;
}
$output .= '</div>';
return theme('box', t('Status'), $output);
/**
* Implementation of hook_init.
*/
function ad_init() {
// We do this in the init hook so that it doesn't get skipped when block
// caching is enabled.
$method = variable_get('ad_display', 'javascript');
if ($method == 'jquery') {
drupal_add_js('misc/jquery.js', 'core');
}
}
* Implementation of hook_help().
switch ($path) {
case 'admin/help#ad':
$output = '<p>'. t('The ad module provides a complete advertising system for Drupal powered websites. It does this through an API that allow other modules to handle various types of advertising content. For example, if enabled together with the ad_image module you will be able to display image based advertisements such as banner ads.') .'</p>';
break;
case 'node/add/ad':
$output = '<p>'. t('Advertisements can be randomly displayed to visitors of your website.') .'</p>';
break;
}
return $output;
}
Alexander Shvets
committed
* Implementation of hook_cron().
*/
function ad_cron() {
if (time() - variable_get('ad_cron_timestamp', 0) >= 60) {
// Locate ads that need to be activated or expired.
Alexander Shvets
committed
$result = db_query('SELECT aid, adstatus, adtype, autoactivate, autoactivated, autoexpire, autoexpired FROM {ads} WHERE autoactivate <> 0 OR autoexpire <> 0');
while ($ad = db_fetch_object($result)) {
switch ($ad->adstatus) {
case 'approved': {
// See if this ad is ready to be activated.
if ($ad->autoactivate && $ad->autoactivate <= time()) {
$node = node_load($ad->aid);
// Activate the ad.
db_query("UPDATE {ads} SET adstatus = 'active', autoactivate = 0, autoactivated = %d, activated = %d WHERE aid = %d", time(), time(), $ad->aid);
watchdog('ad', 'Automatically activated ad %title with nid %nid.', array('%title' => $node->title, '%nid' => $node->nid));
// Allow modules to do special processing to automatically
// activated advertisements.
module_invoke('ad_'. $ad->adtype, 'adapi', 'autoactivate', $node);
}
else if (!$ad->autoactivate) {
// Once daily warn that there's an ad stuck in approved state.
if (time() - variable_get("ad_autoactivate_warning_$ad->aid", 0) >= 8600) {
watchdog('ad', 'Warning: ad %title with nid %nid in approved state has no autoactivate date set.', array('%title' => $node->title, '%nid' => $node->nid));
variable_set("ad_autoactivate_warning_$ad->aid", time());
}
}
break;
}
case 'active': {
// See if this ad is ready to be activated.
if ($ad->autoexpire && $ad->autoexpire <= time()) {
$node = node_load($ad->aid);
// Expire the ad.
db_query("UPDATE {ads} SET adstatus = 'expired', autoexpire = 0, autoexpired = %d, expired = %d WHERE aid = %d", time(), time(), $ad->aid);
ad_statistics_increment($ad->aid, 'autoexpired');
ad_statistics_increment($ad->aid, 'expired');
watchdog('ad', 'Automatically expired ad %title with nid %nid.', array('%title' => $node->title, '%nid' => $node->nid));
// Allow modules to do special processing to automatically
// activated advertisements.
module_invoke('ad_'. $ad->adtype, 'adapi', 'autoexpire', $node);
}
else if (!$ad->autoexpire) {
// Ad is already activated, but has autoactivate timestamp set.
db_query("UPDATE {ads} SET autoactivate = 0 WHERE aid = %d", $ad->aid);
}
break;
}
default:
$node = node_load($ad->aid);
db_query('UPDATE {ads} SET autoactivate = 0, autoexpire = 0 WHERE aid = %d', $ad->aid);
watchdog('ad', 'Warning: reset %type timestamp on advertisement %title with nid %nid because it is in %state state.', array('%title' => $node->title, '%nid' => $node->nid, '%type' => $ad->autoactivate ? 'autoactivate' : 'autoexpire', '%state' => $ad->adstatus));
}
}
variable_set('ad_cron_timestamp', time());
}
}
Alexander Shvets
committed
* Implementation of hook_perm().
*/
function ad_perm() {
'create advertisements',
'edit any advertisement',
'delete own advertisements',
'delete any advertisement',
}
/**
Alexander Shvets
committed
* Implementation of hook_node_info().
*/
function ad_node_info() {
Alexander Shvets
committed
$items['ad'] = array(
'module' => 'ad',
'description' => t('Advertisements can be randomly displayed to visitors of your website.'),
Alexander Shvets
committed
);
return $items;
}
/**
Alexander Shvets
committed
* Implementation of hook_access().
switch ($op) {
case 'create':
return (user_access('create advertisements', $account) || user_access('administer advertisements'));
case 'update':
return (user_access('edit any advertisement', $account) || (user_access('edit own advertisements', $account) && is_ad_owner($node->nid)) || user_access('administer advertisements', $account));
case 'delete':
return (user_access('delete any advertisement', $account) || (user_access('delete own advertisements', $account) && is_ad_owner($node->nid)) || user_access('administer advertisements', $account));
case 'view':
// Return false if user doesn't have basic permissions to view
// advertisements. Don't return true to let default Drupal
// domain/node access checks happen.
if (!user_access('show advertisements', $account) &&
!user_access('administer advertisements', $account)) {
return false;
}
}
}
/**
Alexander Shvets
committed
* Implementation of hook_form().
$form = array();
// When form_state is not empty, we should rather use it's values
// to not loose data if validation fails.
if (!empty($form_state['values'])) {
$node = (object)$form_state['values'];
}
$form['aid'] = array(
'#type' => 'value',
if ($type->has_title) {
$form['title'] = array(
'#type' => 'textfield',
'#title' => check_plain($type->title_label),
'#required' => TRUE,
'#default_value' => isset($node->title) ? $node->title : '',
'#weight' => -5,
);
}
$form['body_field'] = node_body_field($node, $type->body_label, $type->min_word_count);
}
else {
// The body array has to exist otherwise the format field gets removed.
$form['body'] = array(
'#type' => 'hidden',
'#value' => '',
// determine the current ad type
if (!isset($adtype)) {
Alexander Shvets
committed
$adtypes = ad_get_types();
drupal_set_message(t('At least one ad type module must be enabled before you can create advertisements. For example, try <a href="!url">enabling</a> the ad_text or ad_image module.', array('!url' => url('admin/build/modules'))), 'error');
if ((!isset($node->adtype) || isset($node->adtype_select)) &&
count($adtypes) >1) {
$adtypes = array(0 => '---');
$adtypes += ad_get_types('name');
$form['select'] = array(
'#type' => 'fieldset',
'#title' => t('Select Ad type'),
'#prefix' => '<div class="container-inline">',
'#suffix' => '</div>',
'#weight' => 3,
);
$form['select']['adtype_select'] = array(
'#type' => 'select',
'#required' => TRUE,
'#options' => $adtypes,
'#default_value' => isset($node->adtype_select) ? $node->adtype_select : '',
);
$form['select']['adtype_submit'] = array(
'#type' => 'submit',
'#value' => t('Select'),
'#validate' => array('ad_select_adtype'),
'#ahah' => array(
'path' => 'node/add/ad/ahah',
'wrapper' => 'adtype-ahah-wrapper',
),
);
}
// display type-specific options
if ((isset($node->adtype) && $node->adtype) || count($adtypes) == 1) {
if (isset($node->adtype_select) && $node->adtype_select && ($node->adtype_select != $node->adtype)) {
$node->adtype = $node->adtype_select;
ad_form_add_adtype_elements($form, $node->adtype, $node);
// add ahah wrapper
$form['adtype_elements']['#prefix'] = '<div id="adtype-ahah-wrapper">';
$form['adtype_elements']['#suffix'] = '</div>';
}
if (!isset($form['adtype_elements'])) {
$form['adtype_elements'] = array(
'#value' => '<div id="adtype-ahah-wrapper"></div>',
'#weight' => 3.1,
);
}
// fieldset for updating ad status
$form['adstatus'] = array(
'#type' => 'fieldset',
'#title' => t('Status'),
$nid = isset($node->nid) ? $node->nid : 0;
$adstatus = isset($node->adstatus) ? $node->adstatus : '';
foreach (ad_status_array($nid, $adstatus) as $status => $description) {
$form['adstatus']["ad$status"] = array(
'#type' => 'radio',
'#title' => t("$status"),
'#return_value' => $status,
'#default_value' => isset($node->adstatus) ? $node->adstatus : 'pending',
'#description' => "$description",
'#parents' => array("adstatus")
// display scheduling options
$form['schedule'] = array(
'#collapsible' => TRUE,
// Collapse if there isn't any scheduling data set.
'#collapsed' => (
isset($node->autoactivate) ||
isset($form_state['values']['autoactivate']) ||
isset($node->autoexpire) ||
isset($form_state['values']['autoexpire']) ||
isset($node->maxviews) ||
isset($form_state['values']['maxviews']) ||
isset($node->maxclicks) ||
isset($form_state['values']['maxclicks']))
? FALSE : TRUE,
$date_api = FALSE;
if (module_exists('date_popup')) {
$date_api = TRUE;
}
if ((isset($node->nid) && ad_permission($node->nid, 'manage status')) ||
user_access('administer advertisements')) {
if (!$date_api) {
$form['schedule']['current'] = array(
'#type' => 'markup',
'#prefix' => '<div>',
'#suffix' => '</div>',
'#value' => t('The current date and time is "%date".', array('%date' => format_date(time(), 'custom', 'F j, Y H:i')))
);
}
'#title' => t('Automatically activate ad'),
'#required' => FALSE,
'#description' => t('You can specify a date and time for this advertisement to be automatically activated. The advertisement needs to be in an <em>approved</em> state before it can be automatically activated. If you prefer to activate the advertisement immediately, leave this field empty.'),
if ($date_api) {
$form['schedule']['autoactivate']['#date_format'] = 'F j, Y H:i';
$form['schedule']['autoactivate']['#default_value'] = isset($node->autoactivate) && $node->autoactivate > 0 ? format_date((int)$node->autoactivate, 'custom', 'Y-m-j H:i') : '';
}
else {
$form['schedule']['autoactivate']['#default_value'] = isset($node->autoactivate) && $node->autoactivate > 0 ? format_date((int)$node->autoactivate, 'custom', 'F j, Y H:i') : 0;
}
if (user_access('administer advertisements')) {
// admins can expire advertisements
$form['schedule']['autoexpire'] = array(
'#title' => t('Automatically expire ad'),
'#required' => FALSE,
'#description' => t('You can specify a date and time for this advertisement to be automatically expired. If you don\'t want the advertisement to expire, leave this field empty.'),
if ($date_api) {
$form['schedule']['autoexpire']['#date_format'] = 'F j, Y H:i';
$form['schedule']['autoexpire']['#default_value'] = isset($node->autoexpire) && $node->autoexpire > 0 ? format_date((int)$node->autoexpire, 'custom', 'Y-m-j H:i') : '';
}
else {
$form['schedule']['autoexpire']['#default_value'] = isset($node->autoexpire) && $node->autoexpire > 0 ? format_date((int)$node->autoexpire, 'custom', 'F j, Y H:i') : 0;
}
'#default_value' => isset($node->maxviews) ? $node->maxviews : 0,
'#description' => t('You can specify the maximum number of times this advertisement should be displayed, after which it will be automatically expired. If you don\'t want this advertisement to expire after a certain number of impressions, leave this field set to %zero.', array('%zero' => '0')),
'#type' => 'textfield',
'#title' => t('Maximum clicks'),
'#required' => FALSE,
'#default_value' => isset($node->maxclicks) ? $node->maxclicks : 0,
'#description' => t('You can specify the maximum number of times this advertisement should be clicked, after which it will be automatically expired. If you don\'t want this advertisement to expire after a certain number of clicks leave this field set to %zero.', array('%zero' => '0')),
}
else {
// display expiration time
'#prefix' => '<div>',
'#suffix' => '</div>',
'#value' => theme('ad_status_display', $node),
);
$form['schedule']['autoexpire'] = array(
return $form;
}
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
/**
* Ad type switch submit handler.
*/
function ad_select_adtype(&$form, &$form_state) {
if (!$form_state['values']['adtype'] && !$form_state['values']['adtype_select']) {
form_set_error('adtype_select', t('Please, select an Ad type.'));
}
if (!isset($form_state['values']['adtype']) || isset($form_state['values']['adtype_select']) && $form_state['values']['adtype'] != $form_state['values']['adtype_select']) {
$form_state['values']['adtype'] = $form_state['values']['adtype_select'];
$form_state['rebuild'] = TRUE;
}
}
/**
* Ad type switch AHAH menu handler.
*/
function ad_form_ahah() {
$form_state = array('storage' => NULL, 'submitted' => FALSE);
$form_build_id = $_POST['form_build_id'];
$form = form_get_cache($form_build_id, $form_state);
ad_form_add_adtype_elements($form, $_POST['adtype_select']);
form_set_cache($form_build_id, $form, $form_state);
$form += array(
'#post' => $_POST,
'#programmed' => FALSE,
);
// Rebuild the form.
$form = form_builder($_POST['form_id'], $form, $form_state);
$output = drupal_render($form['adtype_elements']);
drupal_json(array(
'status' => TRUE,
'data' => $output,
));
}
/**
* Loads Ad type elements into form.
*/
function ad_form_add_adtype_elements(&$form, $adtype, $node = NULL) {
unset($form['adtype_elements']);
$form['adtype_elements'] = module_invoke('ad_'. $adtype, 'adapi', 'form', $node);
$form['adtype'] = array(
'#type' => 'hidden',
'#value' => $adtype,
);
$form['adtype_elements']['#weight'] = 3.1;
}
Alexander Shvets
committed
* Implementation of hook_form_alter().
if ($form_id == 'taxonomy_form_vocabulary') {
// Remove taxonomy form options not applicable for ad groups.
if ($form['vid']['#value'] == _ad_get_vid()) {
$form['help_ad_vocab'] = array(
'#value' => t('This vocabulary was automatically created for use by the ad module. Only applicable options are available.'),
'#weight' => -1
);
$form['nodes']['ad'] = array(
'#type' => 'checkbox',
'#title' => t('ad group'),
'#value' => 1,
'#attributes' => array('disabled' => ''),
'#description' => t('Type %type is required to use this vocabulary.', array('%type' => t('ad group')))
);
$form['tags']['#description'] = t('If enabled, ads are categorized by typing ad group names instead of choosing them from a list.');
$form['multiple']['#description'] = t('If enabled, allows ads to have more than one ad group (always true for free tagging).');
$form['required']['#description'] = t('If enabled, every ad <strong>must</strong> be assigned to at least one ad group.');
Alexander Shvets
committed
$form['hierarchy'] = array(
'#type' => 'value',
'#value' => 0
);
unset($form['relations']);
}
else {
unset($form['nodes']['ad']);
}
}
else if ($form_id == 'taxonomy_form_term') {
if ($form['vid']['#value'] == _ad_get_vid()) {
$form['name']['#title'] = t('Ad group name');
$form['name']['#description'] = t('The name for this ad group. Example: "Linux".');
$form['description']['#description'] = t('A description of the ad group.');
$form['description']['#required'] = TRUE;
$form['weight']['#description'] = t('In listings, the heavier ad groups will sink and the lighter ad groups will be positioned nearer the top.');
unset($form['synonyms']);
}
}
else if ($form_id == 'search_form' && variable_get('ad_no_search', 1) && !user_access('administer advertisements') && !user_access('administer any advertisement')) {
$vid = _ad_get_vid();
$vocabulary = db_result(db_query('SELECT name FROM {vocabulary} WHERE vid = %d', $vid));
unset($form['advanced']['category']['#options'][$vocabulary]);
if (empty($form['advanced']['category']['#options'])) {
unset($form['advanced']['category']);
}
unset($form['advanced']['type']['#options']['ad']);
}
}
/**
* Implementation of hook_db_rewrite_sql().
*/
function ad_db_rewrite_sql($query, $primary_table, $primary_field, $args) {
if (variable_get('ad_no_search', 1) && !user_access('administer advertisements') && !user_access('edit any advertisement') && $query == '' && $primary_table == 'n' && $primary_field = 'nid' && empty($args)) {
Alexander Shvets
committed
* Implementation of hook_nodeapi().
*/
function ad_nodeapi(&$node, $op, $teaser, $page) {
global $user;
switch ($op) {
case 'load':
$ad = db_fetch_array(db_query('SELECT * FROM {ads} WHERE aid = %d', $node->nid));
$merge = array_merge((array)$node, (array)$ad);
$adtype = module_invoke('ad_'. $ad['adtype'], 'adapi', 'load', $merge);
if (is_array($adtype)) {
return array_merge($ad, $adtype);
}
else {
return $ad;
}
break;
case 'insert':
if ($node->status != 1 && $node->adstatus == 'active') {
$node->autoactivate = isset($node->autoactivate) ? trim($node->autoactivate) : 0;
$node->autoexpire = isset($node->autoexpire) ? trim($node->autoexpire) : 0;
if (!isset($node->maxviews)) {
$node->maxviews = 0;
}
if (!isset($node->maxclicks)) {
$node->maxclicks = 0;
}
db_query("INSERT INTO {ads} (aid, uid, adstatus, adtype, redirect, autoactivate, autoexpire, activated, maxviews, maxclicks) VALUES(%d, %d, '%s', '%s', '%s', %d, %d, %d, %d, %d)", $node->nid, $node->uid, $node->adstatus, $node->adtype, url('ad/redirect/'. $node->nid, array('absolute' => TRUE)), $node->autoactivate ? strtotime($node->autoactivate) : '', $node->autoexpire ? strtotime($node->autoexpire) : '', $activated, $node->maxviews, $node->maxclicks);
ad_statistics_increment($node->nid, 'create');
}
break;
case 'update':
$ad = db_fetch_object(db_query('SELECT * FROM {ads} WHERE aid = %d', $node->nid));
$node->autoactivate = isset($node->autoactivate) ? trim($node->autoactivate) : 0;
$node->autoexpire = isset($node->autoexpire) ? trim($node->autoexpire) : 0;
if ($node->adstatus == 'active') {
// This ad is already active, no need to autoactivate it.
drupal_set_message(t('This ad is already active, ignoring autoactivate date.'));
$node->autoactivate = 0;
}
else {
drupal_set_message(t('This ad will not be automatically activated at the scheduled time because it is not in the <em>approved</em> state.'), 'error');
}
// If this node has been upublished, the ad should no longer be active.
if ($node->status != 1 && $node->adstatus == 'active') {
// Check if ad is being manually activated.
if ($ad->adstatus != 'active' && $node->adstatus == 'active') {
$activated = time();
}
// Check if ad is being manually expired.
else if ($ad->adstatus != 'expired' && $node->adstatus == 'expired') {
$expired = time();
}
// Ad has not been manually activated or expired, preserve timestamps.
else {
$activated = $ad->activated;
$expired = $ad->expired;
}
// Ad status has changed, record the event.
if ($ad->adstatus != $node->adstatus) {
ad_statistics_increment($node->nid, $node->adstatus);
}
// Update ads table with new information.
db_query("UPDATE {ads} SET uid = %d, adstatus = '%s', adtype = '%s', redirect = '%s', autoactivate = %d, autoexpire = %d, activated = %d, maxviews = %d, maxclicks = %d, expired = %d WHERE aid = %d", $node->uid, $node->adstatus, $node->adtype, url('ad/redirect/'. $node->nid, array('absolute' => TRUE)), $node->autoactivate ? strtotime($node->autoactivate) : '', $node->autoexpire ? strtotime($node->autoexpire) : '', isset($activated) ? $activated : 0, isset($node->maxviews) ? (int)$node->maxviews : 0, isset($node->maxclicks) ? (int)$node->maxclicks : 0, isset($expired) ? $expired : 0, $node->nid);
ad_statistics_increment($node->nid, 'update');
}
break;
case 'delete':
// All that's left of the ad is a single timestamp as to when it was
db_query("DELETE FROM {ads} WHERE aid = %d", $node->nid);
db_query("DELETE FROM {ad_statistics} WHERE aid = %d", $node->nid);