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 |