. */ require_once('ad_token.inc'); /** * 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( 'file' => 'ad.pages.inc', 'arguments' => array( 'statistics' => NULL, ), ), 'node_ad' => array( 'file' => 'ad.pages.inc', 'arguments' => array( 'node' => NULL, 'yield_form' => TRUE, ), ), 'ad_admin_ads' => array( 'file' => 'ad.admin.inc', 'arguments' => array( 'form' => NULL, ), ), 'ad_filters' => array( 'file' => 'ad.admin.inc', 'arguments' => array( 'form' => NULL, ), ), 'ad_filter_form' => array( 'file' => 'ad.admin.inc', 'arguments' => array( 'form' => NULL, ), ), ); }; /** * Use this function to display ads from a specified group. * * @param $group * The ad group tid to display ads from. * @param $quantity * Optionally specify the number of unique ads to display. * @param $options * Any number of options from this list: hostid, nids. */ function ad($group = FALSE, $quantity = 1, $options = array()) { global $base_url; $adserve = variable_get('adserve', ''); $adserveinc = variable_get('adserveinc', ''); if (empty($adserve) || empty($adserveinc)) { // This is probably the first time ad() has been called. _ad_check_installation(); $adserve = variable_get('adserve', ''); $adserveinc = variable_get('adserveinc', ''); } if (!file_exists($adserve) || !file_exists($adserveinc)) { drupal_set_message(t('Ads cannot be displayed. The ad module is misconfigured, failed to locate the required serve.php ond/or adserve.inc file.', array('@misconfigured' => url('admin/content/ad/configure'))), 'error'); _ad_check_installation(); return (t('The ad module is misconfigured.', array('@misconfigured' => url('admin/content/ad/configure')))); } // Be sure a display method has been chosen. if (!isset($options['ad_display'])) { $options['ad_display'] = variable_get('ad_display', 'javascript'); } $options['quantity'] = isset($quantity) ? $quantity : 1; if (!isset($options['tids'])) { $options['tids'] = $group; } $options['cache'] = variable_get('ad_cache', 'none'); switch ($options['ad_display']) { case 'raw': require_once(drupal_get_path('module', 'ad') .'/adserve.inc'); require_once(drupal_get_path('module', 'ad') .'/adcache.inc'); $output = adserve_ad($options); break; case 'iframe': case 'jquery': $query['m'] = $options['ad_display']; // Fall through... case 'javascript': default: $query['q'] = $quantity; if (isset($options['hostid'])) { $query['k'] = $options['hostid']; } // Allow external cache files to define additional display variables. if ($options['cache'] != 'none') { $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) { $query[$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) { $query[$key] = $value; } } if (isset($options['nids'])) { // Choose ads from the provided list of node Id's. $nids = $options['nids']; $query['n'] = $nids; $group = "nids-$nids"; } else if (isset($options['tids'])) { // Choose ads from the provided list of taxonomy terms. $tids = $options['tids']; $query['t'] = $tids; $group = "tids-$tids"; } else { // Choose ads from the specified group. $query['t'] = $group; $options['tids'] = $group; } if (isset($options['url'])) { $query['u'] = $options['url']; } else { $query['u'] = $_GET['q']; } $src = htmlentities(url($base_url .'/'. $adserve, array('query' => $query))); if ($options['ad_display'] == 'iframe') { // 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') .'" '; $append .= 'name="'. $group .'" '; if ($height = variable_get('ad_iframe_height', '')) { $append .= 'height="'. $height .'" '; } if ($width = variable_get('ad_iframe_width', '')) { $append .= 'width="'. $width .'" '; } $output = '"; } else if ($options['ad_display'] == 'jquery') { // The theme function uses this to generate a CSS id for jQuery to use. $output = $src; } else { $output = ""; } break; } if (user_access('show advertisements')) { if (isset($options['div']) && $options['div'] !== FALSE) { return theme('ad_display', $group, $output, $options['ad_display']); } else { return theme('ad_display', $group, $output, 'raw'); } } else { return theme('ad_display', 'none', ""); } } /** * 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') { drupal_add_js('misc/jquery.js', 'core'); return "\n
\n \n
\n"; } else if ($method == 'raw') { return $display; } else { return "\n
$display
\n"; } } /** * Update click counter then redirect host to ad's target URL. */ function ad_redirect($aid, $group = NULL) { 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); if ($status == CLICK_VALID) { ad_statistics_increment($aid, 'click', $group, $hostid); } } else { // We're not filtering clicks, so all clicks are valid. ad_statistics_increment($aid, 'click', $group, $hostid); $status = 0; } // Allow source url to be passed in. $url = isset($_GET['u']) ? $_GET['u'] : ''; if (!isset($url) || !valid_url($url)) { $url = referer_uri(); } 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()); // Determine where we're supposed to redirect the user. $adtype = db_result(db_query('SELECT adtype FROM {ads} WHERE aid = %d', $aid)); $node->nid = $node->aid = $aid; $node->hostid = $hostid; $url = module_invoke('ad_'. $adtype, 'adapi', 'redirect', $node); if (isset($url)) { watchdog('ad', 'Clicked %type ad aid %aid hostid %hostid.', array('%type' => $adtype, '%aid' => $aid, '%hostid' => $hostid)); 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 tags. */ function ad_link_attributes() { return array_merge(ad_link_target(TRUE), ad_link_nofollow(TRUE)); } /** * 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: $target = array(); 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)) { $nofollow = array('rel' => 'nofollow'); } else { $nofollow = array(); } return $nofollow; } /** * 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.'); } // mark status from pending to approved if (user_access('administer advertisements') || $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) if (user_access('administer advertisements') || $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) if (user_access('administer advertisements') || $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) if (user_access('administer advertisements') || $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) if (user_access('administer advertisements') || $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) { if (isset($node->adstatus)) { $status_array = ad_status_array($node->nid, $node->adstatus); $output = '
'; $output .= '

'. t($status_array[$node->adstatus]) .'

'; switch ($node->adstatus) { case 'approved': if ($node->autoactivate) { $output .= '

'. t('This advertisement will be automatically activated on %timestamp, in %time.', array('%timestamp' => format_date($node->autoactivate, 'large'), '%time' => format_interval($node->autoactivate - time()))) .'

'; } break; case 'active': $activated = db_result(db_query("SELECT activated FROM {ads} WHERE aid = %d", $node->nid)); if ($activated) { $output .= '

'. t('This advertisement has been active since %date.', array('%date' => format_date($activated, 'large'))) .'

'; } if ($node->autoexpire) { $output .= '

'. t('This advertisement will expire on %timestamp, in %time.', array('%timestamp' => format_date($node->autoexpire, 'large'), '%time' => format_interval($node->autoexpire - time()))) .'

'; } 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 .= '

'. t('This advertisement will expire after %left more impressions.', array('%left' => $node->maxviews - $views)) .'

'; } 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 .= '

'. t('This advertisement will expire after %left more clicks.', array('%left' => $node->maxclicks - $clicks)) .'

'; } break; case 'expired': $expired = db_result(db_query("SELECT expired FROM {ads} WHERE aid = %d", $node->nid)); if ($expired) { $output .= '

'. t('This advertisement expired %date.', array('%date' => format_date($expired, 'large'))) .'

'; } break; } $output .= '
'; return theme('box', t('Status'), $output); } } /** * Implementation of hook_help(). */ function ad_help($path, $arg) { $output = ''; switch ($path) { case 'admin/help#ad': $output = '

'. 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.') .'

'; break; case 'node/add/ad': $output = '

'. t('Advertisements can be randomly displayed to visitors of your website.') .'

'; break; } return $output; } /** * 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. $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); ad_statistics_increment($ad->aid, 'autoactivated'); ad_statistics_increment($ad->aid, 'active'); 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()); } } /** * Implementation of hook_perm(). */ function ad_perm() { return array('administer advertisements', 'create advertisements', 'edit own advertisements', 'edit any advertisement', 'delete own advertisements', 'delete any advertisement', 'show advertisements'); } /** * Implementation of hook_node_info(). */ function ad_node_info() { $items['ad'] = array( 'name' => t('Advertisement'), 'module' => 'ad', 'description' => t('Advertisements can be randomly displayed to visitors of your website.'), ); return $items; } /** * Implementation of hook_access(). */ function ad_access($op, $node, $account) { 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 (user_access('show advertisements', $account) || user_access('administer advertisements', $account)); } } /** * Implementation of hook_form(). */ function ad_form(&$node, &$form_state) { $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', '#value' => isset($node->nid) ? $node->nid : 0, ); $form['title'] = array( '#type' => 'textfield', '#title' => t('Title'), '#required' => TRUE, '#default_value' => isset($node->title) ? $node->title : '', ); $form['body_filter']['body'] = array( '#type' => 'textarea', '#title' => t('Description'), '#default_value' => isset($node->body) ? $node->body : '', '#rows' => 3 ); $form['body_filter']['format'] = filter_form($node->format); // determine the current ad type if (!isset($adtype)) { $adtypes = ad_get_types(); if (sizeof($adtypes) == 1) { $adtype = key($adtypes); } else if (!sizeof($adtypes)) { drupal_set_message(t('At least one ad type module must be enabled before you can create advertisements. For example, try
enabling the ad_text or ad_image module.', array('!url' => url('admin/build/modules'))), 'error'); } } // display ad type switch if (!isset($node->adtype) || isset($node->adtype_select)) { $adtypes = array(0 => '---'); $adtypes += ad_get_types('name'); $form['select'] = array( '#type' => 'fieldset', '#title' => t('Select Ad type'), '#prefix' => '
', '#suffix' => '
', '#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) { 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'] = '
'; $form['adtype_elements']['#suffix'] = '
'; } if (!isset($form['adtype_elements'])) { $form['adtype_elements'] = array( '#value' => '
', '#weight' => 3.1, ); } // fieldset for updating ad status $form['adstatus'] = array( '#type' => 'fieldset', '#title' => t('Status'), '#collapsible' => TRUE, '#weight' => 4, ); $nid = isset($node->nid) ? $node->nid : 0; $adstatus = isset($node->adstatus) ? $node->adstatus : ''; // display all available status options 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( '#type' => 'fieldset', '#title' => t('Scheduling'), '#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, ); if ((isset($node->nid) && ad_permission($node->nid, 'manage status')) || user_access('administer advertisements')) { $form['schedule']['current'] = array( '#type' => 'markup', '#prefix' => '
', '#suffix' => '
', '#value' => t('The current date and time is "%date".', array('%date' => format_date(time(), 'custom', 'F j, Y H:i'))) ); $form['schedule']['autoactivate'] = array( '#type' => 'textfield', '#title' => t('Automatically activate ad'), '#required' => FALSE, '#default_value' => isset($node->autoactivate) && $node->autoactivate > 0 ? format_date((int)$node->autoactivate, 'custom', 'F j, Y H:i') : 0, '#description' => t('You can specify a date and time for this advertisement to be automatically activated. The advertisement needs to be in an approved state before it can be automatically activated. If you prefer to activate the advertisement immediately, leave this field empty.') ); } if (user_access('administer advertisements')) { // admins can expire advertisements $form['schedule']['autoexpire'] = array( '#type' => 'textfield', '#title' => t('Automatically expire ad'), '#required' => FALSE, '#default_value' => isset($node->autoexpire) && $node->autoexpire > 0 ? format_date((int)$node->autoexpire, 'custom', 'F j, Y H:i') : 0, '#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.') ); $form['schedule']['maxviews'] = array( '#type' => 'textfield', '#title' => t('Maximum impressions'), '#required' => FALSE, '#size' => 10, '#maxlength' => 11, '#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')), ); $form['schedule']['maxclicks'] = array( '#type' => 'textfield', '#title' => t('Maximum clicks'), '#required' => FALSE, '#size' => 10, '#maxlength' => 11, '#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 $form['schedule']['autoexpire_display'] = array( '#type' => 'markup', '#prefix' => '
', '#suffix' => '
', '#value' => theme('ad_status_display', $node), ); $form['schedule']['autoexpire'] = array( '#type' => 'hidden', '#value' => isset($node->autoexpire) ? $node->autoexpire : 0, ); } $form['#validate'][] = 'ad_select_adtype'; return $form; } /** * 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; } /** * Implementation of hook_form_alter(). */ function ad_form_alter(&$form, &$form_state, $form_id) { 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 must be assigned to at least one ad group.'); $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']); } } } /** * 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 (isset($node->adtype)) { if ($node->status != 1 && $node->adstatus == 'active') { $node->adstatus = 'expired'; } $activated = $node->adstatus == 'active' ? time() : 0; if (!isset($node->autoactivate)) { $node->autoactivate = 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': if (isset($node->adtype)) { $ad = db_fetch_object(db_query('SELECT * FROM {ads} WHERE aid = %d', $node->nid)); // Ad must be in approved state to be able to autoactivate it. if ($node->adstatus != 'approved' && isset($node->autoactive) && $node->autoactivate) { if ($node->adstatus == 'active') { // This ad is already active, no need to autoactivate it. $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 approved state.'), 'error'); } } // If this node has been upublished, the ad should no longer be active. if ($node->status != 1 && $node->adstatus == 'active') { $node->adstatus = 'expired'; } // 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') { // Ad has been manually expired. $activated = $ad->activated; $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)), isset($node->autoactivate) && strlen($node->autoactivate) > 1 ? strtotime($node->autoactivate) : '', isset($node->autoexpire) && strlen($node->autoexpire) > 1 ? 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': db_query("DELETE FROM {ads} WHERE aid = %d", $node->nid); db_query("DELETE FROM {ad_statistics} WHERE aid = %d", $node->nid); // All that's left of the ad is a single timestamp as to when it was // deleted. ad_statistics_increment($node->nid, 'delete'); break; case 'view': if (isset($node->adtype)) { $node = node_prepare($node, $teaser); $node->content['body'] = array( '#value' => $teaser ? $node->teaser : theme('node_ad', $node, $page), '#weight' => 1, ); } break; } // Allow ad type module to act on nodeapi events. The adapi hook provides // access to additional variables not available in the nodeapi hook. if (isset($node->adtype)) { // Don't use module_invoke, as in pre-PHP5 the changes to $node won't be // passed back. $function = "ad_$node->adtype" .'_adapi'; if (function_exists($function)) { $function($op, $node); } } // Allow ad cache module to act on nodeapi events. $cache = variable_get('ad_cache', 'none'); if ($cache != 'none') { $function = "ad_cache_$cache" .'_adcacheapi'; if (function_exists($function)) { $function($op, $node); } } // Rebuild the cache after all hooks are invoked. switch ($op) { case 'insert': case 'update': case 'delete': if (variable_get('ad_cache_file_rebuild_realtime', 0) && isset($node->adtype)) { ad_rebuild_cache(); } } } function ad_adapi($op, $node = NULL) { switch ($op) { case 'permissions': return array( 'access statistics' => TRUE, 'access click history' => TRUE, 'set status as pending' => FALSE, 'set status as denied' => FALSE, 'set status from pending to approved' => FALSE, 'set status from pending to denied' => FALSE, 'set status from approved to active' => TRUE, 'set status from approved to offline' => TRUE, 'set status from active to offline' => TRUE, 'set status from active to expired' => FALSE, 'set status from offline to active' => TRUE, 'set status from offline to expired' => FALSE, ); break; } } /** * Implementation of hook_menu(). */ function ad_menu() { $items = array(); $items['admin/content/ad'] = array( 'title' => 'Ads', 'page callback' => 'ad_admin_list', 'access arguments' => array('administer advertisements'), 'description' => 'Configure and manage your advertising system.', 'file' => 'ad.admin.inc', ); $items['admin/content/ad/list'] = array( 'title' => 'List', 'page callback' => 'ad_admin_list', 'access arguments' => array('administer advertisements'), 'type' => MENU_DEFAULT_LOCAL_TASK, 'file' => 'ad.admin.inc', ); $items['admin/content/ad/configure'] = array( 'title' => 'Settings', 'page callback' => 'drupal_get_form', 'page arguments' => array('ad_admin_configure_settings'), 'access arguments' => array('administer advertisements'), 'type' => MENU_LOCAL_TASK, 'weight' => 3, 'file' => 'ad.admin.inc', ); $items['node/add/ad/ahah'] = array( 'access arguments' => array('create advertisements'), 'page callback' => 'ad_form_ahah', 'type' => MENU_CALLBACK, ); ad_menu_add_global_settings($items); $items['admin/content/ad/groups'] = array( 'title' => 'Ad groups', 'page callback' => 'ad_admin_groups_list', 'access arguments' => array('administer advertisements'), 'type' => MENU_LOCAL_TASK, 'weight' => 5, 'file' => 'ad.admin.inc', ); $items['admin/content/ad/groups/list'] = array( 'title' => 'List', 'page callback' => 'ad_admin_groups_list', 'access arguments' => array('administer advertisements'), 'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => 0, 'file' => 'ad.admin.inc', ); $items['admin/content/ad/groups/add'] = array( 'title' => 'Create group', 'page callback' => 'drupal_get_form', 'page arguments' => array('ad_admin_group_form'), 'access arguments' => array('administer advertisements'), 'type' => MENU_LOCAL_TASK, 'weight' => 3, 'file' => 'ad.admin.inc', ); $items["admin/content/ad/groups/%ad_group/edit"] = array( 'title' => 'Edit group', 'page callback' => 'drupal_get_form', 'page arguments' => array('ad_admin_group_form', 4), 'access arguments' => array('administer advertisements'), 'weight' => 1, 'file' => 'ad.admin.inc', ); $items["admin/content/ad/groups/%ad_group/delete"] = array( 'title' => 'Delete group', 'page callback' => 'drupal_get_form', 'page arguments' => array('ad_confirm_group_delete', 4), 'access arguments' => array('administer advertisements'), 'weight' => 2, 'file' => 'ad.admin.inc', ); $items['admin/content/ad/configure/global'] = array( 'title' => 'Global settings', 'page callback' => 'drupal_get_form', 'page arguments' => array('ad_admin_configure_settings'), 'access arguments' => array('administer advertisements'), 'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => 0, 'file' => 'ad.admin.inc', ); $items["node/%node/details/%"] = array( 'title' => 'Click details', 'page callback' => 'ad_click_details', 'page arguments' => array(1, 3), 'access arguments' => array(1, 'access click history'), 'access callback' => 'ad_permission', 'type' => MENU_CALLBACK, 'file' => 'ad.pages.inc', ); $items["ad/redirect/%"] = array( 'access arguments' => array('show advertisements'), 'type' => MENU_CALLBACK, 'page callback' => 'ad_redirect', 'page arguments' => (array(2)), ); return $items; } /** * Load settings for all ad modules. Those modules, who don't * have their settings form, will get a standard one. */ function ad_menu_add_global_settings(&$menu_items) { $adtypes = ad_get_types(); foreach ($adtypes as $type => $name) { // Ad type global settings. $settings = 'ad_'. $type .'_global_settings'; $file = 'ad_image.module'; if (!function_exists($settings)) { $settings = 'ad_no_global_settings'; $file = 'ad.admin.inc'; } $menu_items['admin/content/ad/configure/'. $type] = array( 'title' => $name, 'page callback' => 'drupal_get_form', 'page arguments' => array($settings), 'access arguments' => array('administer advertisements'), 'type' => MENU_LOCAL_TASK, 'weight' => 2, 'file' => 'ad.admin.inc', ); } } /** * Drupal menu wildcard Ad group loader */ function ad_group_load($tid) { if (!is_numeric($tid)) { return FALSE; } $group = ad_groups_list(TRUE, $tid); if (!isset($group)) { return FALSE; } return $group; } /** * Implementation of hook_block(). */ function ad_block($op = 'list', $delta = 0, $edit = array()) { switch ($op) { case 'list': $blocks = array(); $groups = ad_groups_list(); foreach ($groups as $tid => $name) { $blocks[$tid]['info'] = t('ad group: @name', array('@name' => $name)); } return $blocks; case 'configure': $form['ad_block_quantity_'. $delta] = array( '#type' => 'select', '#title' => t('Number of ads'), '#default_value' => variable_get('ad_block_quantity_'. $delta, 1), '#options' => drupal_map_assoc(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25)), '#description' => t('Select the maximum number of unique ads that should be displayed together in this block. If you specify a number larger than the maximum number of ads in this ad group, all ads will be displayed once.'), ); return $form; case 'save': variable_set('ad_block_quantity_'. $delta, $edit['ad_block_quantity_'. $delta]); break; case 'view': $groups = ad_groups_list(); $block['content'] = ad($delta, variable_get('ad_block_quantity_'. $delta, 1)); return $block; } } /** * Determine whether the user has a given privilege. * * @param $aid * ID of advertisement. * @param $permission * Permission string which should be checked (such as 'access click history') * @param $account * User object, which are accessing the ad or current user by default. */ function ad_permission($aid, $string, $account = NULL) { global $user; $access = FALSE; // by default, check permission for current user if (!isset($account)) { $account = $user; } // user #1 has all privileges if ($account->uid == 1) { return TRUE; } // if you have administer permissions, you have all permissions if (user_access('administer advertisements', $account)) { return TRUE; } // when used in the Drupal menu, $aid may be the full ad object. if (is_object($aid) && isset($aid->aid)) { $aid = $aid->aid; } else if (is_object($aid) && isset($aid->nid)) { $aid = $aid->nid; } else if (is_object($aid)) { watchdog('ad', 'Invalid aid object passed into ad_permission, no aid->aid set.'); $aid = 0; } // invoke ad_owners module to determine user's access if (module_exists('ad_owners') && function_exists('ad_owners_permission')) { $access = ad_owners_permission($aid, $string, $account); } // no ad_owners module, allow acces to statistics and click history else if (in_array($string, array('access statistics', 'access click history'))) { $access = TRUE; } // with no ad_owners module, all other permissions are denied unless user // has 'administer advertisements' permission return $access; } /** * Returns ad types data. * * @param $op * If set to 'name', will only return array of type names ($type => $name). * If set to 'data', will return all of the type's data * @param $type * If not specified, will return array of all available types, else will * return specific type's name or data. */ function ad_get_types($op = 'name', $type = NULL) { $adtypes = module_invoke_all('adapi', 'type', array()); switch ($op) { case 'name': if (isset($type)) { return $adtypes[$type]['name']; } else { foreach ($adtypes as $type => $data) { $adtypes[$type] = $data['name']; } return $adtypes; } case 'data': if (isset($type)) { return $adtypes[$type]; } else { return $adtypes; } } } /** * Return an array of all groups, or a specific group. * * @param $object * If FALSE, will return only name of group(s). If TRUE, will return full * group object including ->name, ->description, and ->tid. * @param $tid * If set to an integer >0, will only return group info about that specific * group. */ function ad_groups_list($object = FALSE, $tid = NULL) { static $groups = array(); static $names = array(); // Return the full group object(s). if ($object) { if (empty($groups)) { $tids = taxonomy_get_tree(_ad_get_vid()); if (is_array($tids)) { foreach ($tids as $group) { $groups[$group->tid]->name = $group->name; $groups[$group->tid]->description = $group->description; $groups[$group->tid]->tid = $group->tid; $groups[$group->tid]->weight = $group->weight; } } // Hard coded "default" group with tid of 0. $groups[0]->name = t('default'); $groups[0]->description = t('The default ad group is comprised of all ads not assigned to any other ad group.'); $groups[0]->tid = 0; $groups[0]->weight = 0; } // Return a specific group object. if ((int)$tid) { return $groups[$tid]; } // Return an array of all group objects. else { return $groups; } } // Return only the group name(s). else { if (empty($names)) { $tids = taxonomy_get_tree(_ad_get_vid()); if (is_array($tids)) { foreach ($tids as $group) { $names[$group->tid] = $group->name; } } // Hard coded "default" group with tid of 0. $names[0] = t('default'); } // Return a specific group name. if ((int)$tid) { return $names[$tid]; } // Return an array of all group names. else { return $names; } } } /** * Implement ad notify api _hook. */ function ad_adnotifyapi($op, $arg1 = NULL, $arg2 = NULL) { switch ($op) { // Make the following events available for notification. case 'register': return array( '-expired' => t('Email @when before the advertisement will expire.'), 'expired' => t('Email @when after the advertisement is expired.'), '-active' => t('Email @when before the advertisement will be activated (if scheduled).'), 'active' => t('Email @when after the advertisement is activated.'), 'offline' => t('Email @when after the advertisement is taken offline.'), 'click' => t('Email @when after the advertisement is clicked.'), 'approved' => t('Email @when after the advertisement is approved.'), 'denied' => t('Email @when after the advertisement is denied.'), 'update' => t('Email @when after the advertisement is updated.'), ); break; case '-expired': $node = node_load($arg1->aid); if (isset($node->autoexpire) && $node->autoexpire) { if ((time() + $arg1->delay >= $node->autoexpire) && ($arg1->sent + $arg1->delay < $node->autoexpire)) { return array('-expired' => 1); } } break; case '-active': $node = node_load($arg1->aid); if (isset($node->autoactivate) && $node->autoactivate) { if ((time() + $arg1->delay >= $node->autoactivate) && ($arg1->sent + $arg1->delay < $node->autoactivate)) { return array('-active' => 1); } } break; case 'mail_text': switch ($arg1) { case 'expired': return array( 'subject' => t('[%site-name ad] %event notification'), 'body' => t("Hello %owner_name,\n\n This is an automatically generated notification to inform you that your advertisement \"%title\" that was being displayed on the %site-name website has expired.\n\n Your advertisement was viewed %global_impressions times and clicked %global_clicks times since it was activated on %activated_large.\n\n You can view additional statistics about this advertisement or update this notification at the following url:\n %url\n\nRegards,\n The %site-name Team\n\n-\n%site-url"), ); case '-expired': return array( 'subject' => t('[%site-name ad] expiration notification'), 'body' => t("Hello %owner_name,\n\n This is an automatically generated notification to inform you that your advertisement \"%title\" that is being displayed on the %site-name website will expire on %autoexpire_large.\n\n Your advertisement has been viewed %today_impressions times and clicked %today_clicks times today. It was viewed %yesterday_impressions times and clicked %yesterday_clicks times yesterday. It has been viewed %global_impressions times and clicked %global_clicks times since it was activated on %activated_large.\n\n You can view additional statistics about this advertisement or update this notification at the following url:\n %url\n\nRegards,\n The %site-name Team\n\n-\n%site-url"), ); case 'active': return array( 'subject' => t('[%site-name ad] %event notification'), 'body' => t("Hello %owner_name,\n\n This is an automatically generated notification to inform you that your advertisement \"%title\" is now actively being displayed on the %site-name website.\n\n Your advertisement has been viewed %global_impressions times and clicked %global_clicks times since it was activated on %activated_large.\n\n You can view additional statistics about this advertisement or update this notification at the following url:\n %url\n\nRegards,\n The %site-name Team\n\n-\n%site-url"), ); case '-active': return array( 'subject' => t('[%site-name ad] activation notification'), 'body' => t("Hello %owner_name,\n\n This is an automatically generated notification to inform you that your advertisement \"%title\" will be actively displayed on the %site-name website on %autoactivate_large.\n\n You can view statistics about this advertisement or update this notification at the following url:\n %url\n\nRegards,\n The %site-name Team\n\n-\n%site-url"), ); case 'click': return array( 'subject' => t('[%site-name ad] %event notification'), 'body' => t("Hello %owner_name,\n\n This is an automatically generated notification to inform you that your advertisement \"%title\" on the %site-name website has been clicked.\n\n Your advertisement has been viewed %today_impressions times and clicked %today_clicks times today. It was viewed %yesterday_impressions times and clicked %yesterday_clicks times yesterday. It has been viewed %global_impressions times and clicked %global_clicks times since it was activated on %activated_large.\n\n You will receive this %frequency You can view additional statistics about this advertisement or update this notification at the following url:\n %url\n\nRegards,\n The %site-name Team\n\n-\n%site-url"), ); case 'approved': return array( 'subject' => t('[%site-name ad] %event notification'), 'body' => t("Hello %owner_name,\n\n This is an automatically generated notification to inform you that your advertisement \"%title\" on the %site-name website has been approved.\n\n You can view statistics about this advertisement at the following url:\n %url\n\nRegards,\n The %site-name Team\n\n-\n%site-url"), ); case 'denied': return array( 'subject' => t('[%site-name ad] %event notification'), 'body' => t("Hello %owner_name,\n\n This is an automatically generated notification to inform you that your advertisement \"%title\" on the %site-name website has been denied and will not be displayed.\n\n You can view statistics about this advertisement at the following url:\n %url\n\nRegards,\n The %site-name Team\n\n-\n%site-url"), ); } break; } } function _ad_check_installation() { // Verify serve.php exists and is readable. $adserve = variable_get('adserve', ''); $adserveinc = variable_get('adserveinc', ''); if (!file_exists($adserve)) { // The serve.php file should be in the same directory as the ad.module. $adserve = drupal_get_path('module', 'ad') .'/serve.php'; variable_set('adserve', $adserve); } if (!is_readable($adserve)) { variable_set('adserve', ''); drupal_set_message(t('Failed to read the required file %filename. Please make the file readable by the webserver process. No ads can be displayed until this problem is resolved.', array('%filename' => $adserve)), 'error'); } if (!file_exists($adserveinc)) { // The adserve.inc file should be in the same directory as the ad.module. $adserveinc = drupal_get_path('module', 'ad') .'/adserve.inc'; variable_set('adserveinc', $adserveinc); } if (!is_readable($adserveinc)) { variable_set('adserveinc', ''); drupal_set_message(t('Failed to read the required file %filename. Please make the file readable by the webserver process. No ads can be displayed until this problem is resolved.', array('%filename' => $adserveinc)), 'error'); } // Validate vid in vocabulary table. $vid = db_result(db_query("SELECT vid FROM {vocabulary} WHERE module = 'ad'")); if ($vid != variable_get('ad_group_vid', '')) { drupal_set_message(t('Invalid vocabulary defined for advertisements, attempting to auto-fix.'), 'error'); if ($vid) { db_query("DELETE FROM {vocabulary_node_types} WHERE vid = %d OR type = 'ad'", variable_get('ad_group_vid', '')); variable_set('ad_group_vid_restore', variable_get('ad_group_vid', '')); } variable_del('ad_group_vid'); } else { // Validate vid in vocabulary_node_types table. $result = db_query("SELECT vid FROM {vocabulary_node_types} WHERE type = 'ad'"); $found = FALSE; while ($vocab = db_fetch_object($result)) { if ($vocab->vid == variable_get('ad_group_vid', '')) { $found = TRUE; } } if (!$found) { drupal_set_message(t('Missing vocabulary node type for advertisements, attempting to auto-fix.'), 'error'); db_query("DELETE FROM {vocabulary_node_types} WHERE vid = %d OR type = 'ad'", variable_get('ad_group_vid', '')); db_query("DELETE FROM {vocabulary} WHERE vid = %d", variable_get('ad_group_vid', '')); variable_set('ad_group_vid_restore', variable_get('ad_group_vid', '')); variable_del('ad_group_vid'); } } _ad_get_vid(); // Preserve old ad groups, if any. if (($old = variable_get('ad_group_vid_restore', '')) && $vid = variable_get('ad_group_vid', '')) { drupal_set_message(t('Restoring orphaned ad group configuration.')); db_query('UPDATE {term_data} SET vid = %d WHERE vid = %d', $vid, $old); variable_set('ad_group_vid_restore', ''); } $rid = db_result(db_query_range("SELECT rid FROM {permission} WHERE perm LIKE '%%show advertisements%%'", 1)); if (!$rid) { drupal_set_message(t('Be sure to enable "!show" permissions for all roles that you wish to see advertisements.', array('!show' => l(t('show advertisements'), 'admin/user/permissions')))); } // Allow modules to define an action to take each time an ad is served. // When modules define 'adserve_select' or 'adserve_filter', they must set // the 'function' and 'path' parameters. The 'weight' parameter can // optionally be set. // function: the function to call when serving an add // path: the path to the include file where $function is defined // Modules can define actions that happen when advertisements are served. // Currently support actions are: // - init_text (display content before displaying ads) // TODO // - select (alter which ads are selected to be displayed) // TODO // - filter (filter selected ads before they are displayed) // TODO // - exit_text (display content after displaying ads) // TODO $hooks = array('init_text', 'select', 'filter', 'exit_text'); foreach ($hooks as $hook) { $adserve_actions = module_invoke_all('adapi', "adserve_$hook", array()); $actions = array(); foreach ($adserve_actions as $name => $action) { if (is_numeric($action['weight'])) { $weight = $action['weight']; } else { // weight is an optional, defaults to 0 $weight = $action['weight'] = 0; } $actions[$weight .'.'. $name] = $action; $actions[$weight .'.'. $name]['name'] = $name; } // order actions by weight (multiple same-weight actions sorted by alpha) ksort($actions); variable_set("adserve_$hook", serialize($actions)); } module_invoke_all('adapi', 'check_install', array()); } /** * Creates a vocabulary for use by ad groups if not already created. */ function _ad_get_vid() { $vid = variable_get('ad_group_vid', ''); if (empty($vid)) { // No vid stored in the variables table, check if one even exists. $vid = db_result(db_query("SELECT vid FROM {vocabulary} WHERE module = '%s'", 'ad')); if (!$vid) { // No vid, so we create one. $edit = array( 'name' => t('Ad groups'), 'multiple' => 1, 'required' => 0, 'hierarchy' => 0, 'relations' => 0, 'module' => 'ad', 'nodes' => array('ad' => 1) ); taxonomy_save_vocabulary($edit); $vid = $edit['vid']; } // Save the vid for next time. variable_set('ad_group_vid', $vid); } return $vid; } /** * Builds the necessary HTML to display an image-based impressions counter. */ function ad_display_image($aid, $css = TRUE) { global $base_url; $adserve = variable_get('adserve', ''); $cache = variable_get('ad_cache', 'none'); $variables = "?o=image"; $variables .= "&a=$aid"; if ($cache != 'none') { $variables .= '&c='. $cache . module_invoke('ad_cache_'. $cache, 'adcacheapi', 'display_variables', array()); } $output = 'view counter'; if ($css) { return '
'. $output .'
'; } else { return $output; } } /** * Retrieve the group name from the nid. */ function _ad_get_group($nid) { static $groups = array(); if (!isset($groups[$nid])) { $result = db_query('SELECT d.name FROM {term_data} d LEFT JOIN {term_node} n ON d.tid = n.tid WHERE n.nid = %d AND d.vid = %d', $nid, _ad_get_vid()); while ($term = db_fetch_object($result)) { $terms[] = $term->name; } if (!empty($terms)) { $groups[$nid] = implode(', ', $terms); } else { $groups[$nid] = t('default'); } } return $groups[$nid]; }