annotate adserve.inc @ 0:d8a3998dac8e ad

ajout module ad
author pierre
date Fri, 20 Feb 2009 14:04:09 +0000
parents
children 948362c2a207
rev   line source
pierre@0 1 <?php
pierre@0 2 // $Id: adserve.inc,v 1.1.2.31.2.8 2009/02/17 19:22:45 jeremy Exp $
pierre@0 3
pierre@0 4 /**
pierre@0 5 * @file
pierre@0 6 * Configuration.
pierre@0 7 *
pierre@0 8 * Copyright (c) 2005-2009.
pierre@0 9 * Jeremy Andrews <jeremy@tag1consulting.com>.
pierre@0 10 *
pierre@0 11 * By default, adserve configuration happens dynamically as ads are served.
pierre@0 12 * However, it is possible to override dynamic settings with static defaults.
pierre@0 13 * Refer to the documentation/ADSERVE_CONFIGURATION.txt for details on adding
pierre@0 14 * adserve overrides to settings.php.
pierre@0 15 *
pierre@0 16 * Note that the path to Drupal's root directory can not be overriden in
pierre@0 17 * settings.php as adserve needs this path to find settings.php in the first
pierre@0 18 * place. To hard code the path to Drupal's root directory, uncomment the
pierre@0 19 * following define statement, and set the correct path. This is not generally
pierre@0 20 * required. On a Unix server this path will be something like '/path/to/web'.
pierre@0 21 * On a Windows server this path will be something like 'D:\path\to\web'.
pierre@0 22 */
pierre@0 23 //define('DRUPAL_ROOT', '/var/www/html');
pierre@0 24
pierre@0 25 /**
pierre@0 26 * The main adserve logic.
pierre@0 27 */
pierre@0 28 function adserve_ad($options = array()) {
pierre@0 29 static $displayed_count = 0;
pierre@0 30
pierre@0 31 // If no $options are passed in, assume we're using JavaScript.
pierre@0 32 if (!empty($options)) {
pierre@0 33 adserve_variable('variable_load', $options);
pierre@0 34 }
pierre@0 35 else {
pierre@0 36 adserve_variable('variable_load');
pierre@0 37 }
pierre@0 38 adserve_bootstrap(0);
pierre@0 39
pierre@0 40 adserve_debug();
pierre@0 41
pierre@0 42 adserve_variable('error', FALSE);
pierre@0 43 $output = NULL;
pierre@0 44 if (adserve_variable('adcache') != 'none') {
pierre@0 45 /**
pierre@0 46 * Ad caches are defined through external modules. Ad caches are composed
pierre@0 47 * of a module 'ad_cache_TYPE.module' and an include file
pierre@0 48 * 'ad_cache_TYPE.inc' that live in the 'cache/TYPE' subdirectory where
pierre@0 49 * 'TYPE' is replaced with the type of cache. For example, the included
pierre@0 50 * file cache lives in 'cache/file'.
pierre@0 51 *
pierre@0 52 * The ad_cache_TYPE.inc file must have a function named ad_cache_TYPE()
pierre@0 53 * which is used to display ads. It can optionally include a function
pierre@0 54 * titled ad_cache_TYPE_variables used to extract any necessary
pierre@0 55 * variables from the global $_GET array (this can also be used to override
pierre@0 56 * values that would normally be set from $_GET). Any functions used
pierre@0 57 * by this code without bootstrapping Drupal should also be in this file.
pierre@0 58 *
pierre@0 59 * The ad_cache_TYPE.module file should define the drupal _help() hook
pierre@0 60 * so the module can be enabled. It should also define the _adcacheapi()
pierre@0 61 * hook allowing for configuration and processing. Any functions used by
pierre@0 62 * this code after bootstrapping Drupal should also be in this module.
pierre@0 63 *
pierre@0 64 * Refer to cache/file/* for an implementation example.
pierre@0 65 */
pierre@0 66 $function = 'ad_cache_'. adserve_variable('adcache');
pierre@0 67 $output = adserve_invoke_file($function);
pierre@0 68
pierre@0 69 }
pierre@0 70
pierre@0 71 // If there's no output, we assume either there's no cache enabled, or the
pierre@0 72 // cache failed.
pierre@0 73 // TODO: Log failures with the watchdog.
pierre@0 74 if ($output == NULL) {
pierre@0 75 if (adserve_variable('debug')) {
pierre@0 76 echo "No cache enabled.<br />\n";
pierre@0 77 }
pierre@0 78
pierre@0 79 adserve_bootstrap();
pierre@0 80
pierre@0 81 if (adserve_variable('nids')) {
pierre@0 82 $id = adserve_variable('nids');
pierre@0 83 $type = 'nids';
pierre@0 84 adserve_variable('group', "n$id");
pierre@0 85
pierre@0 86 // Retrieve all active advertisements from the provided nid list.
pierre@0 87 $sql = "SELECT aid FROM {ads} WHERE adstatus = 'active' AND aid IN (%s)";
pierre@0 88 $result = db_query($sql, $id);
pierre@0 89
pierre@0 90 if (adserve_variable('debug')) {
pierre@0 91 echo "Searching for ad from nid list: $id.<br />\n";
pierre@0 92 echo "Query: \"$sql;\"<br />\n";
pierre@0 93 }
pierre@0 94 }
pierre@0 95 else if (adserve_variable('tids')) {
pierre@0 96 $id = adserve_variable('tids');
pierre@0 97 $type = 'tids';
pierre@0 98 adserve_variable('group', "t$id");
pierre@0 99
pierre@0 100 // Retrieve all active advertisements from the provided tid list.
pierre@0 101 $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)";
pierre@0 102 $result = db_query($sql, $id);
pierre@0 103
pierre@0 104 if (adserve_variable('debug')) {
pierre@0 105 echo "Searching for ad from tid list: $id.<br />\n";
pierre@0 106 echo "Query: \"$sql;\"<br />\n";
pierre@0 107 }
pierre@0 108 }
pierre@0 109 else {
pierre@0 110 $id = 0;
pierre@0 111 $type = 'default';
pierre@0 112 adserve_variable('group', "$id");
pierre@0 113
pierre@0 114 // Randomly determine which ad to display from those that do not have
pierre@0 115 // any tid assigned to them.
pierre@0 116 $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";
pierre@0 117 $result = db_query($sql);
pierre@0 118
pierre@0 119 if (adserve_variable('debug')) {
pierre@0 120 echo "Searching for ads with no tids.<br />\n";
pierre@0 121 echo "Query: \"$sql;\"<br />\n";
pierre@0 122 }
pierre@0 123 }
pierre@0 124
pierre@0 125 // Build list of all available ads to choose from.
pierre@0 126 $available = array();
pierre@0 127 while ($ad = db_fetch_object($result)) {
pierre@0 128 $available[$ad->aid] = $ad->aid;
pierre@0 129 }
pierre@0 130 if (adserve_variable('debug')) {
pierre@0 131 echo 'Available ads: ';
pierre@0 132 if (sizeof($ads)) {
pierre@0 133 echo implode(', ', $available) ."<br />";
pierre@0 134 }
pierre@0 135 else {
pierre@0 136 echo 'none<br />';
pierre@0 137 }
pierre@0 138 }
pierre@0 139
pierre@0 140 // Randomly select from available advertisements.
pierre@0 141 $selected = adserve_select_ad($available, adserve_variable('quantity'));
pierre@0 142
pierre@0 143 $output = '';
pierre@0 144 $ads = 0;
pierre@0 145 $details = array();
pierre@0 146 $ids = array();
pierre@0 147 // Include appropriate module for displaying selected ad.
pierre@0 148 foreach ($selected as $aid) {
pierre@0 149 $ids[$aid] = $aid;
pierre@0 150 $ads++;
pierre@0 151 $detail = $details[$aid] = node_load($aid);
pierre@0 152 if (!isset($modules[$detail->adtype])) {
pierre@0 153 $modules[$detail->adtype] = db_result(db_query("SELECT filename FROM {system} WHERE name = '%s'", 'ad_'. $detail->adtype));
pierre@0 154 }
pierre@0 155 if (adserve_variable('debug')) {
pierre@0 156 echo 'ad: <pre>';
pierre@0 157 print_r($detail);
pierre@0 158 echo '</pre>';
pierre@0 159 echo "Loading module '". $modules[$detail->adtype] ."'.<br />\n";
pierre@0 160 }
pierre@0 161 include_once $modules[$detail->adtype];
pierre@0 162
pierre@0 163 if ($output) {
pierre@0 164 // Add a div between ads that themers can use to arrange ads when
pierre@0 165 // displaying more than one at a time.
pierre@0 166 $displayed_count++;
pierre@0 167 $output .= "<div class=\"advertisement-space\" id=\"space-$id-$displayed_count\"></div>";
pierre@0 168 }
pierre@0 169 $output .= module_invoke("ad_$detail->adtype", 'display_ad', $detail);
pierre@0 170
pierre@0 171 // Update the ad's impressions counter.
pierre@0 172 if (adserve_variable('ad_display') == 'raw') {
pierre@0 173 $output .= ad_display_image($detail);
pierre@0 174 }
pierre@0 175 else {
pierre@0 176 adserve_increment($detail);
pierre@0 177 }
pierre@0 178 }
pierre@0 179 adserve_variable("$type-ids", $ids);
pierre@0 180 if (empty($ads)) {
pierre@0 181 adserve_variable('error', TRUE);
pierre@0 182 $output = 'No active ads were found in the '. (empty($nids) ? 'tids' : 'nids') ." '$id'.";
pierre@0 183 adserve_increment(NULL, 'count');
pierre@0 184 }
pierre@0 185 if (adserve_variable('debug')) {
pierre@0 186 echo "Ads displayed: $ads<br />";
pierre@0 187 }
pierre@0 188 }
pierre@0 189
pierre@0 190 $hostid = adserve_variable('hostid');
pierre@0 191 $group = adserve_variable('group');
pierre@0 192 $replace = "/$group";
pierre@0 193 if (!empty($hostid)) {
pierre@0 194 $replace .= "/$hostid";
pierre@0 195 }
pierre@0 196 if ($url = htmlentities(adserve_variable('url'))) {
pierre@0 197 $replace .= "?u=$url";
pierre@0 198 }
pierre@0 199
pierre@0 200 $output = preg_replace('&/@HOSTID___&', $replace, $output);
pierre@0 201 if (adserve_variable('error')) {
pierre@0 202 $output = "<!-- $output -->";
pierre@0 203 }
pierre@0 204
pierre@0 205 /**
pierre@0 206 * Modules can add custom code to be displayed before or after ads are
pierre@0 207 * displayed. For example, you many want to add a tagline, "Powered by
pierre@0 208 * Drupal". To do so, define 'adserve_exit_text' within your module's
pierre@0 209 * adapi hook.
pierre@0 210 *
pierre@0 211 * Code sample for adserve_exit_text example:
pierre@0 212 *
pierre@0 213 * sample_adapi($op, $ad) {
pierre@0 214 * case 'adserve_exit_text':
pierre@0 215 * return array(
pierre@0 216 * 'sample' => array(
pierre@0 217 * 'text' => t('Powered by Drupal'),
pierre@0 218 * )
pierre@0 219 * );
pierre@0 220 * }
pierre@0 221 *
pierre@0 222 * As another example use case, you could also use the _init_text and
pierre@0 223 * _exit_text hooks to wrap all advertisements in a custom div.
pierre@0 224 */
pierre@0 225 $init = TRUE;
pierre@0 226 foreach (array('adserve_init_text', 'adserve_exit_text') as $hook) {
pierre@0 227 $result = adserve_invoke_hook($hook);
pierre@0 228 if (is_array($result)) {
pierre@0 229 $append = '';
pierre@0 230 foreach ($result as $text) {
pierre@0 231 if ($text['text']) {
pierre@0 232 $append .= $text['text'];
pierre@0 233 }
pierre@0 234 }
pierre@0 235 if ($init) {
pierre@0 236 $output = $append . $output;
pierre@0 237 }
pierre@0 238 else {
pierre@0 239 $output .= $append;
pierre@0 240 }
pierre@0 241 }
pierre@0 242 $init = FALSE;
pierre@0 243 }
pierre@0 244
pierre@0 245 switch (adserve_variable('ad_display')) {
pierre@0 246 case 'iframe':
pierre@0 247 case 'jquery':
pierre@0 248 if (!adserve_variable('debug')) {
pierre@0 249 // Tell the web browser not to cache this frame so the ad refreshes
pierre@0 250 // each time the page is viewed.
pierre@0 251
pierre@0 252 // Expires in the past:
pierre@0 253 header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
pierre@0 254 // Last load:
pierre@0 255 header('Last-Modified: '. gmdate('D, d M Y H:i:s') .' GMT');
pierre@0 256 // HTTP 1.1:
pierre@0 257 header('Cache-Control: no-store, no-cache, must-revalidate');
pierre@0 258 header('Cache-Control: post-check=0, pre-check=0', FALSE);
pierre@0 259 // HTTP 1.0:
pierre@0 260 header('Pragma: no-cache');
pierre@0 261 }
pierre@0 262 print "$output";
pierre@0 263 exit(0);
pierre@0 264 case 'javascript':
pierre@0 265 default:
pierre@0 266 $output = str_replace(array("\r", "\n", "<", ">", "&"),
pierre@0 267 array('\r', '\n', '\x3c', '\x3e', '\x26'),
pierre@0 268 addslashes($output));
pierre@0 269 if (!adserve_variable('debug')) {
pierre@0 270 // Tell the web browser not to cache this script so the ad refreshes
pierre@0 271 // each time the page is viewed.
pierre@0 272 // Expires in the past:
pierre@0 273 header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
pierre@0 274 // Last load:
pierre@0 275 header('Last-Modified: '. gmdate('D, d M Y H:i:s') .' GMT');
pierre@0 276 // HTTP 1.1:
pierre@0 277 header('Cache-Control: no-store, no-cache, must-revalidate');
pierre@0 278 header('Cache-Control: post-check=0, pre-check=0', FALSE);
pierre@0 279 // HTTP 1.0:
pierre@0 280 header('Pragma: no-cache');
pierre@0 281 // Output is a JavaScript:
pierre@0 282 header('Content-Type: application/x-javascript; charset=utf-8');
pierre@0 283 }
pierre@0 284 print "document.write('$output');";
pierre@0 285 exit(0);
pierre@0 286 case 'raw':
pierre@0 287 chdir(adserve_variable('ad_dir'));
pierre@0 288 return $output;
pierre@0 289 }
pierre@0 290 }
pierre@0 291
pierre@0 292 /**
pierre@0 293 * Retrieve variables from $_GET array or from passed in $value array.
pierre@0 294 */
pierre@0 295 function adserve_variable($variable, $value = NULL) {
pierre@0 296 global $conf;
pierre@0 297 static $variables = NULL, $overridden = NULL, $cache_loaded = array();
pierre@0 298
pierre@0 299 // Update the value, if set.
pierre@0 300 if (isset($value)) {
pierre@0 301 $variables->$variable = $value;
pierre@0 302 }
pierre@0 303
pierre@0 304 if (!isset($variables->loaded) || $variable == 'variable_load') {
pierre@0 305 if ($variable == 'variable_load' && isset($value)) {
pierre@0 306 $values['debug'] = isset($value['debug']) ? $value['debug'] : '';
pierre@0 307 $values['c'] = isset($value['adcache']) ? $value['adcache'] : '';
pierre@0 308 $values['n'] = isset($value['nids']) ? $value['nids'] : '';
pierre@0 309 $values['t'] = isset($value['tids']) ? $value['tids'] : '';
pierre@0 310 $values['k'] = isset($value['hostid']) ? $value['hostid'] : '';
pierre@0 311 $values['q'] = isset($value['quantity']) ? $value['quantity'] : 1;
pierre@0 312 $values['m'] = isset($value['ad_display']) ? $value['ad_display'] : 0;
pierre@0 313 unset($value);
pierre@0 314 }
pierre@0 315 else {
pierre@0 316 $values = $_GET;
pierre@0 317 }
pierre@0 318
pierre@0 319 // Don't use getcwd as path may involve symbolic links
pierre@0 320 $variables->ad_dir = dirname($_SERVER['SCRIPT_FILENAME']);
pierre@0 321 // 'debug' is an integer.
pierre@0 322 $variables->debug = isset($values['debug']) ? (int)$values['debug'] : 0;
pierre@0 323 // Cache types are comprised of only letters.
pierre@0 324 $variables->adcache = isset($values['c']) ? preg_replace('/[^a-zA-Z]/', '', $values['c']) : 'none';
pierre@0 325 // Nids is an integer or a ",".
pierre@0 326 $variables->nids = isset($values['n']) ? preg_replace('/[^0-9,]/', '', $values['n']) : '';
pierre@0 327 // Tids is an integer or a ",".
pierre@0 328 $variables->tids = isset($values['t']) ? preg_replace('/[^0-9,]/', '', $values['t']) : '';
pierre@0 329 // Hostid is an md5() which is comprised of numbers and letters a-f.
pierre@0 330 $variables->hostid = isset($values['k']) ? preg_replace('/[^0-9a-f]/', '', $values['k']) : '';
pierre@0 331 // Click url
pierre@0 332 $variables->url = isset($values['u']) ? $values['u'] : '';
pierre@0 333 // Quantity is an integer.
pierre@0 334 $variables->quantity = isset($values['q']) ? (int)$values['q'] : 0;
pierre@0 335 // Ad ID is an integer.
pierre@0 336 $variables->aid = isset($values['a']) ? (int)$values['a'] : 0;
pierre@0 337 // Method is compriese of only letters.
pierre@0 338 $variables->ad_display = isset($values['m']) ? preg_replace('/[^a-zA-Z]/', '', $values['m']) : 'javascript';
pierre@0 339
pierre@0 340 // Set defaults.
pierre@0 341 $variables->quantity = $variables->quantity ? $variables->quantity : 1;
pierre@0 342
pierre@0 343 if ($variables->debug) {
pierre@0 344 foreach ($variables as $variable => $val) {
pierre@0 345 echo "$variable: '$val'<br />\n";
pierre@0 346 }
pierre@0 347 if ($variables->debug == 1) exit;
pierre@0 348 }
pierre@0 349 $variables->loaded = TRUE;
pierre@0 350
pierre@0 351 // Override the value, if set during initialization.
pierre@0 352 if (isset($value)) {
pierre@0 353 $variables->$variable = $value;
pierre@0 354 }
pierre@0 355 }
pierre@0 356
pierre@0 357 if (!$overridden) {
pierre@0 358 if (isset($conf)) {
pierre@0 359 foreach ($conf as $var => $val) {
pierre@0 360 $variables->$var = $val;
pierre@0 361 if ($variables->debug) {
pierre@0 362 echo "Override $var: '$val'<br />\n";
pierre@0 363 }
pierre@0 364 }
pierre@0 365 $overridden = TRUE;
pierre@0 366 }
pierre@0 367 }
pierre@0 368
pierre@0 369 if (!isset($cache_loaded[$variables->adcache])) {
pierre@0 370 // Retrieve variables defined by cache plugin, if enabled.
pierre@0 371 if ($variables->adcache != 'none') {
pierre@0 372 $include = $variables->ad_dir ."/cache/$variables->adcache/ad_cache_$variables->adcache.inc";
pierre@0 373 if (file_exists($include)) {
pierre@0 374 if ($variables->debug) {
pierre@0 375 echo "Attempting to include cache include file '$include'.<br />\n";
pierre@0 376 }
pierre@0 377 require_once($include);
pierre@0 378 }
pierre@0 379 else if ($variables->debug) {
pierre@0 380 echo "Failed to find cache include file '$include'.<br />\n";
pierre@0 381 }
pierre@0 382 $function = 'ad_cache_'. $variables->adcache .'_variables';
pierre@0 383 if (function_exists($function)) {
pierre@0 384 $external_variables = $function();
pierre@0 385 foreach ($external_variables as $key => $val) {
pierre@0 386 if (!isset($variables->$key)) {
pierre@0 387 $variables->$key = $val;
pierre@0 388 }
pierre@0 389 }
pierre@0 390 }
pierre@0 391 }
pierre@0 392 $cache_loaded[$variables->adcache] = TRUE;
pierre@0 393 }
pierre@0 394
pierre@0 395 if ($variable == 'variable_dump') {
pierre@0 396 echo "Dumping \$variables:<br />\n";
pierre@0 397 echo '<pre>';
pierre@0 398 foreach ($variables as $var => $val) {
pierre@0 399 echo " $var($val)<br />\n";
pierre@0 400 }
pierre@0 401 echo '</pre>';
pierre@0 402 }
pierre@0 403
pierre@0 404 if (isset($variables->$variable)) {
pierre@0 405 return $variables->$variable;
pierre@0 406 }
pierre@0 407 else {
pierre@0 408 return NULL;
pierre@0 409 }
pierre@0 410 }
pierre@0 411
pierre@0 412 /**
pierre@0 413 * Invoke a function in the specified file.
pierre@0 414 */
pierre@0 415 function adserve_invoke_file($function, $arg1 = NULL, $arg2 = NULL) {
pierre@0 416 $output = '';
pierre@0 417 if (function_exists($function)) {
pierre@0 418 $output = $function($arg1, $arg2);
pierre@0 419 }
pierre@0 420 else if (adserve_variable('debug')) {
pierre@0 421 echo "Function '$function' does not exist.<br />\n";
pierre@0 422 }
pierre@0 423 return $output;
pierre@0 424 }
pierre@0 425
pierre@0 426 /**
pierre@0 427 * Invoke adserve hooks, defined in adapi with adserve_HOOK.
pierre@0 428 */
pierre@0 429 function adserve_invoke_hook($hook, $a1 = NULL, $a2 = NULL) {
pierre@0 430 if (adserve_variable('adcache') != 'none') {
pierre@0 431 $cache = adserve_variable('adcache');
pierre@0 432 _debug_echo("Invoking adserve hook '$hook' in $cache cache.");
pierre@0 433 // Get information from cache.
pierre@0 434 return adserve_invoke_file("ad_cache_{$cache}_$hook", $a1, $a2);
pierre@0 435 }
pierre@0 436 else {
pierre@0 437 _debug_echo("Invoking adserve hook '$hook'.");
pierre@0 438 // Get information from Drupal variable table.
pierre@0 439 $actions = variable_get($hook, '');
pierre@0 440 $return = array();
pierre@0 441 if (!empty($actions)) {
pierre@0 442 $actions = unserialize($actions);
pierre@0 443 foreach ($actions as $name => $action) {
pierre@0 444 if ($action['function']) {
pierre@0 445 $function = $action['function'];
pierre@0 446 if (!function_exists($function)) {
pierre@0 447 if ($action['path']) {
pierre@0 448 _debug_echo("Including file '". $action['path'] ."'.");
pierre@0 449 include_once($action['path']);
pierre@0 450 }
pierre@0 451 }
pierre@0 452 if (function_exists($function)) {
pierre@0 453 _debug_echo("Invoking function '$function'.");
pierre@0 454 $return[] = $function($a1, $a2);
pierre@0 455 }
pierre@0 456 else if (adserve_variable('debug')) {
pierre@0 457 echo "Function '$function' does not exist.<br />\n";
pierre@0 458 }
pierre@0 459 }
pierre@0 460 else {
pierre@0 461 $return[] = $action;
pierre@0 462 }
pierre@0 463 }
pierre@0 464 }
pierre@0 465 return $return;
pierre@0 466 }
pierre@0 467 // Retreive hook definition from cache if using, or from variable_get
pierre@0 468 // return hook action.
pierre@0 469 }
pierre@0 470
pierre@0 471 function _debug_echo($text) {
pierre@0 472 if (adserve_variable('debug')) {
pierre@0 473 echo "$text<br />\n";
pierre@0 474 }
pierre@0 475 }
pierre@0 476
pierre@0 477 /**
pierre@0 478 * Remove one or more ids from array.
pierre@0 479 * TODO: Optimize. Perhaps something like array_flip, unset, array_flip.
pierre@0 480 * @param $ids An array of ID's, ie array(5, 8, 9, 11).
pierre@0 481 * @param $remove An ID or an array of ID's to be removed from $ids.
pierre@0 482 */
pierre@0 483 function adserve_select_reindex($ids, $remove) {
pierre@0 484 $new = array();
pierre@0 485 // Walk through array of IDs and decide what to keep.
pierre@0 486 foreach ($ids as $id) {
pierre@0 487 // If $remove is an array, walk through array to decide fate of ID.
pierre@0 488 if (is_array($remove)) {
pierre@0 489 $keep = TRUE;
pierre@0 490 foreach ($remove as $rem) {
pierre@0 491 // Loop until we find one that matches or reach end of array.
pierre@0 492 if ($id == $rem) {
pierre@0 493 $keep = FALSE;
pierre@0 494 break;
pierre@0 495 }
pierre@0 496 }
pierre@0 497 if ($keep) {
pierre@0 498 $new[] = $id;
pierre@0 499 }
pierre@0 500 }
pierre@0 501 else {
pierre@0 502 if ($id != $remove) {
pierre@0 503 $new[] = $id;
pierre@0 504 }
pierre@0 505 }
pierre@0 506 }
pierre@0 507 return $new;
pierre@0 508 }
pierre@0 509
pierre@0 510 /**
pierre@0 511 * Disabled: will be re-implemented with new adserve hooks introduced for
pierre@0 512 * geotargeting.
pierre@0 513 function adserve_invoke_weight($ads, $quantity = 1, $invalid = array()) {
pierre@0 514 $parent = adserve_variable('ad_dir') .'/weight';
pierre@0 515 if (is_dir($parent) && $handle = opendir($parent)) {
pierre@0 516 while ($dir = readdir($handle)) {
pierre@0 517 if (is_dir("$parent/$dir") && !in_array($dir, array('.', '..', 'CVS'))) {
pierre@0 518 $include = "$parent/$dir/ad_weight_$dir.inc";
pierre@0 519 if (file_exists($include)) {
pierre@0 520 require_once($include);
pierre@0 521 $function = "ad_weight_{$dir}_select_ad";
pierre@0 522 if (function_exists($function)) {
pierre@0 523 $return = $function($ads, $quantity, $invalid);
pierre@0 524 // First come, first serve. We found an ad_weight function that
pierre@0 525 // returned something, so we'll take it.
pierre@0 526 if ($return) {
pierre@0 527 return $return;
pierre@0 528 }
pierre@0 529 }
pierre@0 530 }
pierre@0 531 }
pierre@0 532 }
pierre@0 533 }
pierre@0 534 }
pierre@0 535 */
pierre@0 536
pierre@0 537 /**
pierre@0 538 * Simple default function to randomly select an ad. Provides a hook to allow
pierre@0 539 * the definition of external display methods.
pierre@0 540 * @param An array of valid ad IDs, ie array(5, 8, 9, 11).
pierre@0 541 * @param Optional, how many unique ads to select.
pierre@0 542 * @param Optional, an array of invalid IDs.
pierre@0 543 */
pierre@0 544 function adserve_select_ad($ads, $quantity = 1, $invalid = array()) {
pierre@0 545 //adserve_invoke_weight($ads, $quantity, $invalid);
pierre@0 546
pierre@0 547 $ids = array();
pierre@0 548 $id = 0;
pierre@0 549 $total = sizeof($ads);
pierre@0 550 _debug_echo("Selecting $quantity ad(s) from $total total ad(s).");
pierre@0 551 if (is_array($ads)) {
pierre@0 552 $ads = adserve_select_reindex($ads, $invalid);
pierre@0 553 $total = sizeof($ads);
pierre@0 554 for ($i = 0; $i < $quantity; $i++) {
pierre@0 555 _debug_echo('Randomly selecting ad: '. ($i + 1) ." of $quantity.");
pierre@0 556 $id = 0;
pierre@0 557 // Randomly select a unique banner to display. We subtract 1 as arrays
pierre@0 558 // start at 0.
pierre@0 559 $return = adserve_invoke_hook('adserve_select', $ads, $invalid);
pierre@0 560 if (is_array($return) && !empty($return)) {
pierre@0 561 foreach ($return as $id) {
pierre@0 562 // First come first serve.
pierre@0 563 if ((int)$id) break;
pierre@0 564 }
pierre@0 565 }
pierre@0 566 if ($id >= 0 && sizeof($ads)) {
pierre@0 567 if ($id == 0) {
pierre@0 568 _debug_echo("Default ID selection in adserve.inc.");
pierre@0 569 $id = $total > 1 ? $ads[mt_rand(0, $total - 1)] : $ads[0];
pierre@0 570 _debug_echo("Randomly selected ID: $id.");
pierre@0 571 }
pierre@0 572 if ($id > 0) {
pierre@0 573 $ids[] = $id;
pierre@0 574 }
pierre@0 575 }
pierre@0 576 else {
pierre@0 577 // There are no more valid advertisements left to display.
pierre@0 578 break;
pierre@0 579 }
pierre@0 580 $invalid[] = $id;
pierre@0 581 $ads = adserve_select_reindex($ads, $id);
pierre@0 582 $total = sizeof($ads);
pierre@0 583 // We're out of ads to display.
pierre@0 584 if ($total <= 0) {
pierre@0 585 break;
pierre@0 586 }
pierre@0 587 }
pierre@0 588 }
pierre@0 589 return $ids;
pierre@0 590 }
pierre@0 591
pierre@0 592 /**
pierre@0 593 * Include Drupal's bootstrap.inc.
pierre@0 594 */
pierre@0 595 function adserve_include_drupal() {
pierre@0 596 // For optimal performance set DRUPAL_ROOT at the top of this file.
pierre@0 597 if (defined('DRUPAL_ROOT')) {
pierre@0 598 if (is_dir(DRUPAL_ROOT) && file_exists(DRUPAL_ROOT .'/includes/bootstrap.inc')) {
pierre@0 599 chdir(DRUPAL_ROOT);
pierre@0 600 adserve_variable('root_dir', DRUPAL_ROOT);
pierre@0 601 }
pierre@0 602 else {
pierre@0 603 echo 'Invalid DRUPAL_ROOT ('. DRUPAL_ROOT .') defined in adserve.inc';
pierre@0 604 }
pierre@0 605 }
pierre@0 606 else {
pierre@0 607 $path = explode('/', adserve_variable('ad_dir'));
pierre@0 608 while (!empty($path)) {
pierre@0 609 // Search for top level Drupal directory to perform bootstrap.
pierre@0 610 chdir(implode('/', $path));
pierre@0 611 if (file_exists('./includes/bootstrap.inc')) {
pierre@0 612 adserve_variable('root_dir', getcwd());
pierre@0 613 break;
pierre@0 614 }
pierre@0 615 array_pop($path);
pierre@0 616 }
pierre@0 617 }
pierre@0 618 require_once adserve_variable('root_dir') .'/includes/bootstrap.inc';
pierre@0 619 }
pierre@0 620
pierre@0 621 /**
pierre@0 622 * Include the necessary files and call the Drupal bootstrap.
pierre@0 623 */
pierre@0 624 function adserve_bootstrap($bootstrap = NULL) {
pierre@0 625 adserve_include_drupal();
pierre@0 626
pierre@0 627 // If no specific bootstrap is specified, do a full bootstrap.
pierre@0 628 if (!isset($bootstrap)) {
pierre@0 629 $bootstrap = DRUPAL_BOOTSTRAP_FULL;
pierre@0 630 }
pierre@0 631
pierre@0 632 if (adserve_variable('debug')) {
pierre@0 633 echo "Drupal bootstrap '". $bootstrap ."'.<br />\n";
pierre@0 634 }
pierre@0 635
pierre@0 636 drupal_bootstrap($bootstrap);
pierre@0 637 }
pierre@0 638
pierre@0 639 /**
pierre@0 640 * Increment ad counters. Increment in cache if enabled.
pierre@0 641 */
pierre@0 642 function adserve_increment($ad, $action = 'view') {
pierre@0 643 $cache = adserve_variable('adcache');
pierre@0 644 if (adserve_variable('debug')) {
pierre@0 645 echo "adserve_increment action($action) cache($cache)<br />\n";
pierre@0 646 }
pierre@0 647 if (is_object($ad) && isset($ad->aid)) {
pierre@0 648 $aid = $ad->aid;
pierre@0 649 }
pierre@0 650 else {
pierre@0 651 $aid = 0;
pierre@0 652 }
pierre@0 653 if ($cache != 'none') {
pierre@0 654 $rc = adserve_invoke_file("ad_cache_{$cache}_increment", $action, $aid);
pierre@0 655 if ($rc) return;
pierre@0 656 }
pierre@0 657 adserve_bootstrap();
pierre@0 658 // Update impressions statistics.
pierre@0 659 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'));
pierre@0 660 // If column doesn't already exist, we need to add it.
pierre@0 661 if (!db_affected_rows()) {
pierre@0 662 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'));
pierre@0 663 // If another process already added this row our INSERT will fail, if
pierre@0 664 // so we still need to increment it so we don't loose an impression.
pierre@0 665 if (!db_affected_rows()) {
pierre@0 666 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'));
pierre@0 667 }
pierre@0 668 }
pierre@0 669
pierre@0 670 if ($action == 'view') {
pierre@0 671 // See if we need to perform additional queries.
pierre@0 672 if (isset($ad->maxviews) && $ad->maxviews > 0) {
pierre@0 673 $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)));
pierre@0 674 if ($views >= $ad->maxviews) {
pierre@0 675 db_query("UPDATE {ads} SET adstatus = 'expired', autoexpire = 0, autoexpired = %d, expired = %d WHERE aid = %d", time(), time(), $aid);
pierre@0 676 ad_statistics_increment($aid, 'autoexpired');
pierre@0 677 ad_statistics_increment($aid, 'expired');
pierre@0 678 }
pierre@0 679 }
pierre@0 680 }
pierre@0 681 // TODO: Do we need to do this here? Can it happen when a new click is
pierre@0 682 // registered?
pierre@0 683 if (isset($ad->maxclicks) && $ad->maxclicks > 0) {
pierre@0 684 $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)));
pierre@0 685 if ($clicks >= $ad->maxclicks) {
pierre@0 686 db_query("UPDATE {ads} SET adstatus = 'expired', autoexpire = 0, autoexpired = %d, expired = %d WHERE aid = %d", time(), time(), $aid);
pierre@0 687 ad_statistics_increment($aid, 'autoexpired');
pierre@0 688 ad_statistics_increment($aid, 'expired');
pierre@0 689 }
pierre@0 690 }
pierre@0 691 }
pierre@0 692
pierre@0 693 /**
pierre@0 694 * Display additional debug information.
pierre@0 695 */
pierre@0 696 function adserve_debug() {
pierre@0 697 if (adserve_variable('debug')) {
pierre@0 698 echo "Root drupal directory detected as '". adserve_variable('root_dir') ."'.<br />\n<br />\n";
pierre@0 699
pierre@0 700 $ad_dir = adserve_variable('ad_dir');
pierre@0 701 $files = array("$ad_dir/serve.php", "$ad_dir/ad.module");
pierre@0 702 if (adserve_variable('debug') > 2) {
pierre@0 703 $files = array_merge($files, array("$ad_dir/ad.install"));
pierre@0 704 }
pierre@0 705 if (adserve_variable('debug') > 3) {
pierre@0 706 $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"));
pierre@0 707 }
pierre@0 708 foreach ($files as $file) {
pierre@0 709 if (!file_exists($file)) {
pierre@0 710 echo "Error: '$file' does not exist!<br />\n";
pierre@0 711 }
pierre@0 712 else if (!is_readable($file)) {
pierre@0 713 echo "Error: '$file' is not readable!<br />\n";
pierre@0 714 }
pierre@0 715 else {
pierre@0 716 $fd = fopen($file, 'r');
pierre@0 717 while (!feof($fd)) {
pierre@0 718 $line = fgets($fd);
pierre@0 719 if (substr($line, 0, 5) == "<?php") {
pierre@0 720 continue;
pierre@0 721 }
pierre@0 722 else {
pierre@0 723 echo "$file: $line<br />";
pierre@0 724 break;
pierre@0 725 }
pierre@0 726 }
pierre@0 727 }
pierre@0 728 }
pierre@0 729 echo "<br />\n";
pierre@0 730 }
pierre@0 731 }
pierre@0 732