Mercurial > defr > drupal > ad
diff adserve.inc @ 1:948362c2a207 ad
update advertisement
author | pierre |
---|---|
date | Thu, 02 Apr 2009 15:28:21 +0000 |
parents | d8a3998dac8e |
children | e5584a19768b |
line wrap: on
line diff
--- a/adserve.inc Fri Feb 20 14:04:09 2009 +0000 +++ b/adserve.inc Thu Apr 02 15:28:21 2009 +0000 @@ -1,5 +1,5 @@ <?php -// $Id: adserve.inc,v 1.1.2.31.2.8 2009/02/17 19:22:45 jeremy Exp $ +// $Id: adserve.inc,v 1.1.2.31.2.8.2.6 2009/03/27 17:26:02 jeremy Exp $ /** * @file @@ -28,265 +28,28 @@ function adserve_ad($options = array()) { static $displayed_count = 0; - // If no $options are passed in, assume we're using JavaScript. + // if no $options are passed in, assume we're using JavaScript if (!empty($options)) { adserve_variable('variable_load', $options); } else { adserve_variable('variable_load'); } + + // include Drupal's settings.php adserve_bootstrap(0); + // if debug enabled, dump current state adserve_debug(); + // start with 'error' set to false adserve_variable('error', FALSE); - $output = NULL; - if (adserve_variable('adcache') != 'none') { - /** - * Ad caches are defined through external modules. Ad caches are composed - * of a module 'ad_cache_TYPE.module' and an include file - * 'ad_cache_TYPE.inc' that live in the 'cache/TYPE' subdirectory where - * 'TYPE' is replaced with the type of cache. For example, the included - * file cache lives in 'cache/file'. - * - * The ad_cache_TYPE.inc file must have a function named ad_cache_TYPE() - * which is used to display ads. It can optionally include a function - * titled ad_cache_TYPE_variables used to extract any necessary - * variables from the global $_GET array (this can also be used to override - * values that would normally be set from $_GET). Any functions used - * by this code without bootstrapping Drupal should also be in this file. - * - * The ad_cache_TYPE.module file should define the drupal _help() hook - * so the module can be enabled. It should also define the _adcacheapi() - * hook allowing for configuration and processing. Any functions used by - * this code after bootstrapping Drupal should also be in this module. - * - * Refer to cache/file/* for an implementation example. - */ - $function = 'ad_cache_'. adserve_variable('adcache'); - $output = adserve_invoke_file($function); - } + // invoke cache function (file already included in adserve_variable) + $ids = adserve_cache('get_ad_ids'); - // If there's no output, we assume either there's no cache enabled, or the - // cache failed. - // TODO: Log failures with the watchdog. - if ($output == NULL) { - if (adserve_variable('debug')) { - echo "No cache enabled.<br />\n"; - } - - adserve_bootstrap(); - - if (adserve_variable('nids')) { - $id = adserve_variable('nids'); - $type = 'nids'; - adserve_variable('group', "n$id"); - - // Retrieve all active advertisements from the provided nid list. - $sql = "SELECT aid FROM {ads} WHERE adstatus = 'active' AND aid IN (%s)"; - $result = db_query($sql, $id); - - if (adserve_variable('debug')) { - echo "Searching for ad from nid list: $id.<br />\n"; - echo "Query: \"$sql;\"<br />\n"; - } - } - else if (adserve_variable('tids')) { - $id = adserve_variable('tids'); - $type = 'tids'; - adserve_variable('group', "t$id"); - - // Retrieve all active advertisements from the provided tid list. - $sql = "SELECT a.aid FROM {ads} a INNER JOIN {term_node} n ON a.aid = n.nid WHERE a.adstatus = 'active' AND n.tid IN (%s)"; - $result = db_query($sql, $id); - - if (adserve_variable('debug')) { - echo "Searching for ad from tid list: $id.<br />\n"; - echo "Query: \"$sql;\"<br />\n"; - } - } - else { - $id = 0; - $type = 'default'; - adserve_variable('group', "$id"); - - // Randomly determine which ad to display from those that do not have - // any tid assigned to them. - $sql = "SELECT a.aid FROM {ads} a LEFT JOIN {term_node} n ON a.aid = n.nid WHERE a.adstatus = 'active' AND n.tid IS NULL"; - $result = db_query($sql); - - if (adserve_variable('debug')) { - echo "Searching for ads with no tids.<br />\n"; - echo "Query: \"$sql;\"<br />\n"; - } - } - - // Build list of all available ads to choose from. - $available = array(); - while ($ad = db_fetch_object($result)) { - $available[$ad->aid] = $ad->aid; - } - if (adserve_variable('debug')) { - echo 'Available ads: '; - if (sizeof($ads)) { - echo implode(', ', $available) ."<br />"; - } - else { - echo 'none<br />'; - } - } - - // Randomly select from available advertisements. - $selected = adserve_select_ad($available, adserve_variable('quantity')); - - $output = ''; - $ads = 0; - $details = array(); - $ids = array(); - // Include appropriate module for displaying selected ad. - foreach ($selected as $aid) { - $ids[$aid] = $aid; - $ads++; - $detail = $details[$aid] = node_load($aid); - if (!isset($modules[$detail->adtype])) { - $modules[$detail->adtype] = db_result(db_query("SELECT filename FROM {system} WHERE name = '%s'", 'ad_'. $detail->adtype)); - } - if (adserve_variable('debug')) { - echo 'ad: <pre>'; - print_r($detail); - echo '</pre>'; - echo "Loading module '". $modules[$detail->adtype] ."'.<br />\n"; - } - include_once $modules[$detail->adtype]; - - if ($output) { - // Add a div between ads that themers can use to arrange ads when - // displaying more than one at a time. - $displayed_count++; - $output .= "<div class=\"advertisement-space\" id=\"space-$id-$displayed_count\"></div>"; - } - $output .= module_invoke("ad_$detail->adtype", 'display_ad', $detail); - - // Update the ad's impressions counter. - if (adserve_variable('ad_display') == 'raw') { - $output .= ad_display_image($detail); - } - else { - adserve_increment($detail); - } - } - adserve_variable("$type-ids", $ids); - if (empty($ads)) { - adserve_variable('error', TRUE); - $output = 'No active ads were found in the '. (empty($nids) ? 'tids' : 'nids') ." '$id'."; - adserve_increment(NULL, 'count'); - } - if (adserve_variable('debug')) { - echo "Ads displayed: $ads<br />"; - } - } - - $hostid = adserve_variable('hostid'); - $group = adserve_variable('group'); - $replace = "/$group"; - if (!empty($hostid)) { - $replace .= "/$hostid"; - } - if ($url = htmlentities(adserve_variable('url'))) { - $replace .= "?u=$url"; - } - - $output = preg_replace('&/@HOSTID___&', $replace, $output); - if (adserve_variable('error')) { - $output = "<!-- $output -->"; - } - - /** - * Modules can add custom code to be displayed before or after ads are - * displayed. For example, you many want to add a tagline, "Powered by - * Drupal". To do so, define 'adserve_exit_text' within your module's - * adapi hook. - * - * Code sample for adserve_exit_text example: - * - * sample_adapi($op, $ad) { - * case 'adserve_exit_text': - * return array( - * 'sample' => array( - * 'text' => t('Powered by Drupal'), - * ) - * ); - * } - * - * As another example use case, you could also use the _init_text and - * _exit_text hooks to wrap all advertisements in a custom div. - */ - $init = TRUE; - foreach (array('adserve_init_text', 'adserve_exit_text') as $hook) { - $result = adserve_invoke_hook($hook); - if (is_array($result)) { - $append = ''; - foreach ($result as $text) { - if ($text['text']) { - $append .= $text['text']; - } - } - if ($init) { - $output = $append . $output; - } - else { - $output .= $append; - } - } - $init = FALSE; - } - - switch (adserve_variable('ad_display')) { - case 'iframe': - case 'jquery': - if (!adserve_variable('debug')) { - // Tell the web browser not to cache this frame so the ad refreshes - // each time the page is viewed. - - // Expires in the past: - header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); - // Last load: - header('Last-Modified: '. gmdate('D, d M Y H:i:s') .' GMT'); - // HTTP 1.1: - header('Cache-Control: no-store, no-cache, must-revalidate'); - header('Cache-Control: post-check=0, pre-check=0', FALSE); - // HTTP 1.0: - header('Pragma: no-cache'); - } - print "$output"; - exit(0); - case 'javascript': - default: - $output = str_replace(array("\r", "\n", "<", ">", "&"), - array('\r', '\n', '\x3c', '\x3e', '\x26'), - addslashes($output)); - if (!adserve_variable('debug')) { - // Tell the web browser not to cache this script so the ad refreshes - // each time the page is viewed. - // Expires in the past: - header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); - // Last load: - header('Last-Modified: '. gmdate('D, d M Y H:i:s') .' GMT'); - // HTTP 1.1: - header('Cache-Control: no-store, no-cache, must-revalidate'); - header('Cache-Control: post-check=0, pre-check=0', FALSE); - // HTTP 1.0: - header('Pragma: no-cache'); - // Output is a JavaScript: - header('Content-Type: application/x-javascript; charset=utf-8'); - } - print "document.write('$output');"; - exit(0); - case 'raw': - chdir(adserve_variable('ad_dir')); - return $output; - } + // display the advertisement(s) + adserve_cache('display', $ids); } /** @@ -296,6 +59,11 @@ global $conf; static $variables = NULL, $overridden = NULL, $cache_loaded = array(); + // Declare variables if not already declared. + if ($variables === NULL) { + $variables = new stdClass(); + } + // Update the value, if set. if (isset($value)) { $variables->$variable = $value; @@ -330,6 +98,9 @@ $variables->hostid = isset($values['k']) ? preg_replace('/[^0-9a-f]/', '', $values['k']) : ''; // Click url $variables->url = isset($values['u']) ? $values['u'] : ''; + if (!$variables->url) { + $variables->url = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ''; + } // Quantity is an integer. $variables->quantity = isset($values['q']) ? (int)$values['q'] : 0; // Ad ID is an integer. @@ -423,170 +194,52 @@ return $output; } -/** - * Invoke adserve hooks, defined in adapi with adserve_HOOK. +/* + * When debugging, strip away distracting header errors. Dump all other errors. */ -function adserve_invoke_hook($hook, $a1 = NULL, $a2 = NULL) { - if (adserve_variable('adcache') != 'none') { - $cache = adserve_variable('adcache'); - _debug_echo("Invoking adserve hook '$hook' in $cache cache."); - // Get information from cache. - return adserve_invoke_file("ad_cache_{$cache}_$hook", $a1, $a2); +function _debug_error_handler($errno, $errstr, $errfile = NULL, $errline = 0, $errcontext = NULL) { + if (!preg_match('/Cannot modify header information/', $errstr) && + !preg_match('/Cannot send session cache limiter/', $errstr)) { + echo "PHP: errno($errno): $errstr "; + if ($errfile && $errline) { + echo "; Line $errline in [$errfile]"; + } + echo "<br />\n"; + if (!empty($errcontext) && adserve_variable('debug') >= 5) { + echo 'Error context:<pre>'; + print_r($errcontext); + echo '</pre>'; + } } - else { - _debug_echo("Invoking adserve hook '$hook'."); - // Get information from Drupal variable table. - $actions = variable_get($hook, ''); - $return = array(); - if (!empty($actions)) { - $actions = unserialize($actions); - foreach ($actions as $name => $action) { - if ($action['function']) { - $function = $action['function']; - if (!function_exists($function)) { - if ($action['path']) { - _debug_echo("Including file '". $action['path'] ."'."); - include_once($action['path']); - } - } - if (function_exists($function)) { - _debug_echo("Invoking function '$function'."); - $return[] = $function($a1, $a2); - } - else if (adserve_variable('debug')) { - echo "Function '$function' does not exist.<br />\n"; - } - } - else { - $return[] = $action; - } - } - } - return $return; - } - // Retreive hook definition from cache if using, or from variable_get - // return hook action. } +/** + * Dump debug message to screen; set custom error handler. + */ function _debug_echo($text) { + static $error_handler = FALSE; + static $time = 0; + if (adserve_variable('debug')) { + if ($time < time()) { + $time = time(); + echo '--> Time mark: '. date('H:i:s', $time) ."<br />\n"; + _debug_memory(); + } + if (!$error_handler) { + set_error_handler('_debug_error_handler'); + $error_handler = TRUE; + } echo "$text<br />\n"; } } -/** - * Remove one or more ids from array. - * TODO: Optimize. Perhaps something like array_flip, unset, array_flip. - * @param $ids An array of ID's, ie array(5, 8, 9, 11). - * @param $remove An ID or an array of ID's to be removed from $ids. - */ -function adserve_select_reindex($ids, $remove) { - $new = array(); - // Walk through array of IDs and decide what to keep. - foreach ($ids as $id) { - // If $remove is an array, walk through array to decide fate of ID. - if (is_array($remove)) { - $keep = TRUE; - foreach ($remove as $rem) { - // Loop until we find one that matches or reach end of array. - if ($id == $rem) { - $keep = FALSE; - break; - } - } - if ($keep) { - $new[] = $id; - } - } - else { - if ($id != $remove) { - $new[] = $id; - } - } +function _debug_memory() { + $memory = ''; + if (adserve_variable('debug') && function_exists('memory_get_usage')) { + $memory = number_format(round(memory_get_usage() / 1024, 3), 3); + echo "Memory usage: $memory K<br />\n"; } - return $new; -} - -/** - * Disabled: will be re-implemented with new adserve hooks introduced for - * geotargeting. -function adserve_invoke_weight($ads, $quantity = 1, $invalid = array()) { - $parent = adserve_variable('ad_dir') .'/weight'; - if (is_dir($parent) && $handle = opendir($parent)) { - while ($dir = readdir($handle)) { - if (is_dir("$parent/$dir") && !in_array($dir, array('.', '..', 'CVS'))) { - $include = "$parent/$dir/ad_weight_$dir.inc"; - if (file_exists($include)) { - require_once($include); - $function = "ad_weight_{$dir}_select_ad"; - if (function_exists($function)) { - $return = $function($ads, $quantity, $invalid); - // First come, first serve. We found an ad_weight function that - // returned something, so we'll take it. - if ($return) { - return $return; - } - } - } - } - } - } -} - */ - -/** - * Simple default function to randomly select an ad. Provides a hook to allow - * the definition of external display methods. - * @param An array of valid ad IDs, ie array(5, 8, 9, 11). - * @param Optional, how many unique ads to select. - * @param Optional, an array of invalid IDs. - */ -function adserve_select_ad($ads, $quantity = 1, $invalid = array()) { - //adserve_invoke_weight($ads, $quantity, $invalid); - - $ids = array(); - $id = 0; - $total = sizeof($ads); - _debug_echo("Selecting $quantity ad(s) from $total total ad(s)."); - if (is_array($ads)) { - $ads = adserve_select_reindex($ads, $invalid); - $total = sizeof($ads); - for ($i = 0; $i < $quantity; $i++) { - _debug_echo('Randomly selecting ad: '. ($i + 1) ." of $quantity."); - $id = 0; - // Randomly select a unique banner to display. We subtract 1 as arrays - // start at 0. - $return = adserve_invoke_hook('adserve_select', $ads, $invalid); - if (is_array($return) && !empty($return)) { - foreach ($return as $id) { - // First come first serve. - if ((int)$id) break; - } - } - if ($id >= 0 && sizeof($ads)) { - if ($id == 0) { - _debug_echo("Default ID selection in adserve.inc."); - $id = $total > 1 ? $ads[mt_rand(0, $total - 1)] : $ads[0]; - _debug_echo("Randomly selected ID: $id."); - } - if ($id > 0) { - $ids[] = $id; - } - } - else { - // There are no more valid advertisements left to display. - break; - } - $invalid[] = $id; - $ads = adserve_select_reindex($ads, $id); - $total = sizeof($ads); - // We're out of ads to display. - if ($total <= 0) { - break; - } - } - } - return $ids; } /** @@ -629,65 +282,10 @@ $bootstrap = DRUPAL_BOOTSTRAP_FULL; } - if (adserve_variable('debug')) { - echo "Drupal bootstrap '". $bootstrap ."'.<br />\n"; - } + echo _debug_echo("Drupal bootstrap '$bootstrap'."); drupal_bootstrap($bootstrap); -} - -/** - * Increment ad counters. Increment in cache if enabled. - */ -function adserve_increment($ad, $action = 'view') { - $cache = adserve_variable('adcache'); - if (adserve_variable('debug')) { - echo "adserve_increment action($action) cache($cache)<br />\n"; - } - if (is_object($ad) && isset($ad->aid)) { - $aid = $ad->aid; - } - else { - $aid = 0; - } - if ($cache != 'none') { - $rc = adserve_invoke_file("ad_cache_{$cache}_increment", $action, $aid); - if ($rc) return; - } - adserve_bootstrap(); - // Update impressions statistics. - db_query("UPDATE {ad_statistics} SET count = count + 1 WHERE aid = %d AND action = '%s' AND date = %d AND adgroup = '%s' AND hostid = '%s'", $aid, $action, date('YmdH'), adserve_variable('group'), adserve_variable('hostid')); - // If column doesn't already exist, we need to add it. - if (!db_affected_rows()) { - db_query("INSERT INTO {ad_statistics} (aid, date, action, adgroup, hostid, count) VALUES(%d, %d, '%s', '%s', '%s', 1)", $aid, date('YmdH'), $action, adserve_variable('hostid'), adserve_variable('hostid')); - // 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 impression. - if (!db_affected_rows()) { - db_query("UPDATE {ad_statistics} SET count = count + 1 WHERE aid = %d AND action = '%s' AND date = %d AND adgroup = '%s' AND hostid = '%s'", $aid, $action, date('YmdH'), adserve_variable('group'), adserve_variable('hostid')); - } - } - - if ($action == 'view') { - // See if we need to perform additional queries. - if (isset($ad->maxviews) && $ad->maxviews > 0) { - $views = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'view' AND date >= %d", $aid, date('YmdH', $ad->activated))); - if ($views >= $ad->maxviews) { - db_query("UPDATE {ads} SET adstatus = 'expired', autoexpire = 0, autoexpired = %d, expired = %d WHERE aid = %d", time(), time(), $aid); - ad_statistics_increment($aid, 'autoexpired'); - ad_statistics_increment($aid, 'expired'); - } - } - } - // TODO: Do we need to do this here? Can it happen when a new click is - // registered? - if (isset($ad->maxclicks) && $ad->maxclicks > 0) { - $clicks = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'click' AND date >= %d", $aid, date('YmdH', $ad->activated))); - if ($clicks >= $ad->maxclicks) { - db_query("UPDATE {ads} SET adstatus = 'expired', autoexpire = 0, autoexpired = %d, expired = %d WHERE aid = %d", time(), time(), $aid); - ad_statistics_increment($aid, 'autoexpired'); - ad_statistics_increment($aid, 'expired'); - } - } + echo _debug_echo("Drupal bootstrap complete."); } /** @@ -698,12 +296,12 @@ echo "Root drupal directory detected as '". adserve_variable('root_dir') ."'.<br />\n<br />\n"; $ad_dir = adserve_variable('ad_dir'); - $files = array("$ad_dir/serve.php", "$ad_dir/ad.module"); - if (adserve_variable('debug') > 2) { + $files = array("$ad_dir/serve.php", "$ad_dir/adserve.inc", "$ad_dir/adcache.inc", "$ad_dir/ad.module"); + if (adserve_variable('debug') >= 2) { $files = array_merge($files, array("$ad_dir/ad.install")); } - if (adserve_variable('debug') > 3) { - $files = array_merge($files, array("$ad_dir/image/ad_image.module", "$ad_dir/image/ad_image.install", "$ad_dir/text/ad_text.module", "$ad_dir/text/ad_text.install", "$ad_dir/embed/ad_embed.module", "$ad_dir/report/ad_report.module", "$ad_dir/notify/ad_notify.module", "$ad_dir/notify/ad_notify.install")); + if (adserve_variable('debug') >= 3) { + $files = array_merge($files, array("$ad_dir/image/ad_image.module", "$ad_dir/image/ad_image.install", "$ad_dir/text/ad_text.module", "$ad_dir/text/ad_text.install", "$ad_dir/embed/ad_embed.module", "$ad_dir/report/ad_report.module", "$ad_dir/notify/ad_notify.module", "$ad_dir/notify/ad_notify.install", "$ad_dir/cache/file/ad_cache_file.inc", "$ad_dir/cache/file/ad_cache_file.module", "$ad_dir/permission/ad_permission.module", "$ad_dir/weight/probability/ad_weight_probability.module", "$ad_dir/weight/probability/ad_weight_probability.inc")); } foreach ($files as $file) { if (!file_exists($file)) {