| pierre@0 | 1 <?php | 
| sly@8 | 2 // $Id: ad.module,v 1.2.2.29.2.83.2.16.2.26 2009/08/05 00:13:36 jeremy Exp $ | 
| pierre@0 | 3 | 
| pierre@0 | 4 /** | 
| pierre@0 | 5  * @file | 
| pierre@0 | 6  * An advertising system for Drupal powered websites. | 
| pierre@0 | 7  * | 
| pierre@0 | 8  * Copyright (c) 2005-2009. | 
| pierre@0 | 9  *   Jeremy Andrews <jeremy@tag1consulting.com>. | 
| pierre@0 | 10  */ | 
| pierre@0 | 11 | 
| pierre@1 | 12 require_once('ad_token.inc'); | 
| pierre@0 | 13 | 
| pierre@0 | 14 /** | 
| pierre@0 | 15  * Implementation of hook_theme(). | 
| pierre@0 | 16  */ | 
| pierre@0 | 17 function ad_theme() { | 
| pierre@0 | 18   return array( | 
| pierre@0 | 19     'ad_display' => array( | 
| pierre@0 | 20       'file' => 'ad.module', | 
| pierre@0 | 21       'arguments' => array( | 
| pierre@0 | 22         'group' => NULL, | 
| pierre@0 | 23         'display' => NULL, | 
| pierre@0 | 24         'method' => 'javascript', | 
| pierre@0 | 25       ), | 
| pierre@0 | 26     ), | 
| pierre@0 | 27     'ad_status_display' => array( | 
| pierre@0 | 28       'file' => 'ad.module', | 
| pierre@0 | 29       'arguments' => array( | 
| pierre@0 | 30         'node' => NULL, | 
| pierre@0 | 31       ), | 
| pierre@0 | 32     ), | 
| pierre@0 | 33     'ad_statistics_display' => array( | 
| pierre@0 | 34       'file' => 'ad.pages.inc', | 
| pierre@0 | 35       'arguments' => array( | 
| pierre@0 | 36         'statistics' => NULL, | 
| pierre@0 | 37       ), | 
| pierre@0 | 38     ), | 
| pierre@0 | 39     'node_ad' => array( | 
| pierre@0 | 40       'file' => 'ad.pages.inc', | 
| pierre@0 | 41       'arguments' => array( | 
| pierre@0 | 42         'node' => NULL, | 
| pierre@0 | 43         'yield_form' => TRUE, | 
| pierre@0 | 44       ), | 
| pierre@0 | 45     ), | 
| pierre@0 | 46     'ad_admin_ads' => array( | 
| pierre@0 | 47       'file' => 'ad.admin.inc', | 
| pierre@0 | 48       'arguments' => array( | 
| pierre@0 | 49         'form' => NULL, | 
| pierre@0 | 50       ), | 
| pierre@0 | 51     ), | 
| pierre@0 | 52     'ad_filters' => array( | 
| pierre@0 | 53       'file' => 'ad.admin.inc', | 
| pierre@0 | 54       'arguments' => array( | 
| pierre@0 | 55         'form' => NULL, | 
| pierre@0 | 56       ), | 
| pierre@0 | 57     ), | 
| pierre@0 | 58     'ad_filter_form' => array( | 
| pierre@0 | 59       'file' => 'ad.admin.inc', | 
| pierre@0 | 60       'arguments' => array( | 
| pierre@0 | 61         'form' => NULL, | 
| pierre@0 | 62       ), | 
| pierre@0 | 63     ), | 
| pierre@0 | 64   ); | 
| pierre@0 | 65 }; | 
| pierre@0 | 66 | 
| pierre@0 | 67 /** | 
| pierre@0 | 68  * Use this function to display ads from a specified group. | 
| pierre@0 | 69  * | 
| pierre@0 | 70  * @param $group | 
| pierre@0 | 71  *  The ad group tid to display ads from. | 
| pierre@0 | 72  * @param $quantity | 
| pierre@0 | 73  *  Optionally specify the number of unique ads to display. | 
| pierre@0 | 74  * @param $options | 
| pierre@0 | 75  *  Any number of options from this list:  hostid, nids. | 
| pierre@0 | 76  */ | 
| pierre@0 | 77 function ad($group = FALSE, $quantity = 1, $options = array()) { | 
| pierre@0 | 78   global $base_url; | 
| pierre@0 | 79 | 
| pierre@0 | 80   $adserve = variable_get('adserve', ''); | 
| pierre@0 | 81   $adserveinc = variable_get('adserveinc', ''); | 
| pierre@0 | 82   if (empty($adserve) || empty($adserveinc)) { | 
| pierre@0 | 83     // This is probably the first time ad() has been called. | 
| pierre@0 | 84     _ad_check_installation(); | 
| pierre@0 | 85     $adserve = variable_get('adserve', ''); | 
| pierre@0 | 86     $adserveinc = variable_get('adserveinc', ''); | 
| pierre@0 | 87   } | 
| pierre@0 | 88   if (!file_exists($adserve) || !file_exists($adserveinc)) { | 
| pierre@0 | 89     drupal_set_message(t('Ads cannot be displayed.  The ad module is <a href="@misconfigured">misconfigured</a>, failed to locate the required <em>serve.php</em> ond/or <em>adserve.inc</em> file.', array('@misconfigured' => url('admin/content/ad/configure'))), 'error'); | 
| pierre@0 | 90     _ad_check_installation(); | 
| pierre@0 | 91     return (t('The ad module is <a href="@misconfigured">misconfigured</a>.', array('@misconfigured' => url('admin/content/ad/configure')))); | 
| pierre@0 | 92   } | 
| pierre@0 | 93 | 
| pierre@0 | 94   // Be sure a display method has been chosen. | 
| pierre@0 | 95   if (!isset($options['ad_display'])) { | 
| pierre@0 | 96     $options['ad_display'] = variable_get('ad_display', 'javascript'); | 
| pierre@0 | 97   } | 
| pierre@0 | 98   $options['quantity'] = isset($quantity) ? $quantity : 1; | 
| pierre@0 | 99   if (!isset($options['tids'])) { | 
| pierre@0 | 100     $options['tids'] = $group; | 
| pierre@0 | 101   } | 
| pierre@0 | 102   $options['cache'] = variable_get('ad_cache', 'none'); | 
| pierre@0 | 103 | 
| pierre@0 | 104   switch ($options['ad_display']) { | 
| pierre@0 | 105     case 'raw': | 
| pierre@0 | 106       require_once(drupal_get_path('module', 'ad') .'/adserve.inc'); | 
| pierre@1 | 107       require_once(drupal_get_path('module', 'ad') .'/adcache.inc'); | 
| pierre@0 | 108       $output = adserve_ad($options); | 
| pierre@0 | 109       break; | 
| pierre@0 | 110     case 'iframe': | 
| pierre@0 | 111     case 'jquery': | 
| pierre@0 | 112       $query['m'] = $options['ad_display']; | 
| pierre@0 | 113       // Fall through... | 
| pierre@0 | 114     case 'javascript': | 
| pierre@0 | 115     default: | 
| pierre@0 | 116       $query['q'] = $quantity; | 
| pierre@0 | 117       if (isset($options['hostid'])) { | 
| pierre@0 | 118         $query['k'] = $options['hostid']; | 
| pierre@0 | 119       } | 
| pierre@0 | 120       // Allow external cache files to define additional display variables. | 
| pierre@0 | 121       if ($options['cache'] != 'none') { | 
| pierre@0 | 122         $query['c'] =  $options['cache']; | 
| pierre@0 | 123         $cache_variables = module_invoke('ad_cache_'. $options['cache'], 'adcacheapi', 'display_variables', array()); | 
| pierre@0 | 124         if (is_array($cache_variables)) { | 
| pierre@0 | 125           foreach ($cache_variables as $key => $value) { | 
| pierre@0 | 126             $query[$key] = $value; | 
| pierre@0 | 127           } | 
| pierre@0 | 128         } | 
| pierre@0 | 129       } | 
| pierre@0 | 130       // Allow ad_type modules to define additional display variables. | 
| pierre@0 | 131       $type_variables = module_invoke_all('adapi', 'display_variables', array()); | 
| pierre@0 | 132       if (is_array($type_variables)) { | 
| pierre@0 | 133         foreach ($type_variables as $key => $value) { | 
| pierre@0 | 134           $query[$key] = $value; | 
| pierre@0 | 135         } | 
| pierre@0 | 136       } | 
| pierre@0 | 137       if (isset($options['nids'])) { | 
| pierre@0 | 138         // Choose ads from the provided list of node Id's. | 
| pierre@0 | 139         $nids = $options['nids']; | 
| pierre@0 | 140         $query['n'] = $nids; | 
| pierre@0 | 141         $group = "nids-$nids"; | 
| pierre@0 | 142       } | 
| pierre@0 | 143       else if (isset($options['tids'])) { | 
| pierre@0 | 144         // Choose ads from the provided list of taxonomy terms. | 
| pierre@0 | 145         $tids = $options['tids']; | 
| pierre@0 | 146         $query['t'] = $tids; | 
| pierre@0 | 147         $group = "tids-$tids"; | 
| pierre@0 | 148       } | 
| pierre@0 | 149       else { | 
| pierre@0 | 150         // Choose ads from the specified group. | 
| pierre@0 | 151         $query['t'] = $group; | 
| pierre@0 | 152         $options['tids'] = $group; | 
| pierre@0 | 153       } | 
| pierre@1 | 154       if (isset($options['url'])) { | 
| pierre@1 | 155         $query['u'] = $options['url']; | 
| pierre@1 | 156       } | 
| pierre@1 | 157       else { | 
| pierre@1 | 158         $query['u'] = $_GET['q']; | 
| pierre@1 | 159       } | 
| piotre@7 | 160       $src = url($base_url .'/'. $adserve, array('query' => $query)); | 
| pierre@0 | 161       if ($options['ad_display'] == 'iframe') { | 
| pierre@0 | 162         // TODO: We need to know the IFrame size before it is displayed.  This | 
| pierre@0 | 163         // limits the flexibility of what can be displayed in these frames. | 
| pierre@0 | 164         // For now we'll have a global value, later we'll add per-group | 
| pierre@0 | 165         // over-rides. | 
| pierre@0 | 166         $append = 'frameborder="'. variable_get('ad_iframe_frameborder', 0) .'" '; | 
| pierre@0 | 167         $append .= 'scrolling="'. variable_get('ad_iframe_scroll', 'auto') .'" '; | 
| pierre@0 | 168         $append .= 'name="'. $group .'" '; | 
| pierre@0 | 169         if ($height = variable_get('ad_iframe_height', '')) { | 
| pierre@0 | 170           $append .= 'height="'. $height .'" '; | 
| pierre@0 | 171         } | 
| pierre@0 | 172         if ($width = variable_get('ad_iframe_width', '')) { | 
| pierre@0 | 173           $append .= 'width="'. $width .'" '; | 
| pierre@0 | 174         } | 
| piotre@7 | 175         $output = '<iframe src="'. htmlentities($src) ."\" $append></iframe>"; | 
| pierre@0 | 176       } | 
| pierre@0 | 177       else if ($options['ad_display'] == 'jquery') { | 
| pierre@0 | 178         // The theme function uses this to generate a CSS id for jQuery to use. | 
| pierre@0 | 179         $output = $src; | 
| pierre@0 | 180       } | 
| pierre@0 | 181       else { | 
| piotre@7 | 182         $output = "<script type='text/javascript' src='". htmlentities($src) ."'></script>"; | 
| pierre@0 | 183       } | 
| pierre@0 | 184       break; | 
| pierre@0 | 185   } | 
| pierre@0 | 186 | 
| pierre@0 | 187   if (user_access('show advertisements')) { | 
| sly@8 | 188     return theme('ad_display', $group, $output, $options['ad_display']); | 
| pierre@0 | 189   } | 
| pierre@0 | 190   else { | 
| pierre@0 | 191     return theme('ad_display', 'none', "<!-- Enable 'show advertisements' permission if you wish to display ads here. -->"); | 
| pierre@0 | 192   } | 
| pierre@0 | 193 } | 
| pierre@0 | 194 | 
| pierre@0 | 195 /** | 
| pierre@0 | 196  * Function to display the actual advertisement to the screen.  Wrap it in a | 
| pierre@0 | 197  * theme function to make it possible to customize in your own theme. | 
| pierre@0 | 198  */ | 
| pierre@0 | 199 function theme_ad_display($group, $display, $method = 'javascript') { | 
| pierre@1 | 200   static $id = -1; | 
| pierre@1 | 201 | 
| pierre@1 | 202   // Increment counter for displaying multiple advertisements on the page. | 
| pierre@1 | 203   $id++; | 
| pierre@0 | 204 | 
| pierre@0 | 205   // The naming convention for the id attribute doesn't allow commas. | 
| pierre@0 | 206   $group = preg_replace('/[,]/', '+', $group); | 
| pierre@0 | 207 | 
| pierre@0 | 208   if ($method == 'jquery') { | 
| pierre@1 | 209     return "\n<div class=\"advertisement group-$group\" id=\"group-id-$id\">\n <script type=\"text/javascript\">\n//<![CDATA[\n  $(document).ready(function(){ jQuery(\"div#group-id-$id\").load(\"$display\"); });\n //]]>\n </script>\n</div>\n"; | 
| pierre@1 | 210   } | 
| pierre@1 | 211   else if ($method == 'raw') { | 
| pierre@1 | 212     return $display; | 
| pierre@0 | 213   } | 
| pierre@0 | 214   else { | 
| pierre@0 | 215     return "\n<div class=\"advertisement group-$group\" id=\"group-id-$group\">$display</div>\n"; | 
| pierre@0 | 216   } | 
| pierre@0 | 217 } | 
| pierre@0 | 218 | 
| pierre@0 | 219 /** | 
| pierre@0 | 220  * Update click counter then redirect host to ad's target URL. | 
| pierre@0 | 221  */ | 
| pierre@1 | 222 function ad_redirect($aid, $group = NULL) { | 
| pierre@0 | 223   global $user; | 
| pierre@1 | 224   $hostid = isset($_GET['hostid']) ? $_GET['hostid'] : ''; | 
| pierre@1 | 225   $extra = isset($_GET['extra']) ? $_GET['extra'] : ''; | 
| pierre@0 | 226   if (function_exists('click_filter_status')) { | 
| pierre@0 | 227     $status = click_filter_status($aid, $hostid); | 
| pierre@0 | 228     if ($status == CLICK_VALID) { | 
| pierre@0 | 229       ad_statistics_increment($aid, 'click', $group, $hostid); | 
| pierre@0 | 230     } | 
| pierre@0 | 231   } | 
| pierre@0 | 232   else { | 
| pierre@0 | 233     // We're not filtering clicks, so all clicks are valid. | 
| pierre@0 | 234     ad_statistics_increment($aid, 'click', $group, $hostid); | 
| pierre@0 | 235     $status = 0; | 
| pierre@0 | 236   } | 
| pierre@0 | 237   // Allow source url to be passed in. | 
| pierre@0 | 238   $url = isset($_GET['u']) ? $_GET['u'] : ''; | 
| pierre@0 | 239   if (!isset($url) || !valid_url($url)) { | 
| pierre@0 | 240     $url = referer_uri(); | 
| pierre@0 | 241   } | 
| pierre@1 | 242   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()); | 
| pierre@0 | 243 | 
| pierre@0 | 244   // Determine where we're supposed to redirect the user. | 
| pierre@0 | 245   $adtype = db_result(db_query('SELECT adtype FROM {ads} WHERE aid = %d', $aid)); | 
| pierre@0 | 246 | 
| pierre@0 | 247   $node->nid = $node->aid = $aid; | 
| pierre@0 | 248   $node->hostid = $hostid; | 
| pierre@0 | 249   $url = module_invoke('ad_'. $adtype, 'adapi', 'redirect', $node); | 
| pierre@0 | 250   if (isset($url)) { | 
| pierre@0 | 251     watchdog('ad', 'Clicked %type ad aid %aid hostid %hostid.', array('%type' => $adtype, '%aid' => $aid, '%hostid' => $hostid)); | 
| pierre@0 | 252     header('Location: '. $url); | 
| pierre@0 | 253   } | 
| pierre@0 | 254   else { | 
| pierre@0 | 255     watchdog('ad', 'Ad redirection failed for aid %aid hostid %hostid, failed to load destination URL. ', array('%aid' => $aid, '%hostid' => $hostid)); | 
| pierre@0 | 256     drupal_goto(''); | 
| pierre@0 | 257   } | 
| pierre@0 | 258 } | 
| pierre@0 | 259 | 
| pierre@0 | 260 /** | 
| pierre@0 | 261  * Ad API Helper Function: | 
| pierre@0 | 262  * Append all necessary attributes to <a> tags. | 
| pierre@0 | 263  */ | 
| pierre@0 | 264 function ad_link_attributes() { | 
| pierre@0 | 265   return array_merge(ad_link_target(TRUE), ad_link_nofollow(TRUE)); | 
| pierre@0 | 266 } | 
| pierre@0 | 267 | 
| pierre@0 | 268 /** | 
| pierre@0 | 269  * Ad API Helper Function: | 
| pierre@0 | 270  * Provide XHTML-strict-compatible target window onclick-handlers based on | 
| pierre@0 | 271  * global configuration. | 
| pierre@0 | 272  */ | 
| pierre@0 | 273 function ad_link_target() { | 
| pierre@0 | 274   switch (variable_get('ad_link_target', '_self')) { | 
| pierre@0 | 275     case '_blank': | 
| pierre@0 | 276       $target = array('onclick' => 'window.open(this.href); return false;'); | 
| pierre@0 | 277       break; | 
| pierre@0 | 278     case '_parent': | 
| pierre@0 | 279       $target = array('onclick' => 'window.parent.location = this.href; return false;'); | 
| pierre@0 | 280       break; | 
| pierre@0 | 281     case '_top': | 
| pierre@0 | 282       $target = array('onclick' => 'window.top.location = this.href; return false;'); | 
| pierre@0 | 283       break; | 
| pierre@0 | 284     default: | 
| pierre@0 | 285       $target = array(); | 
| pierre@0 | 286       break; | 
| pierre@0 | 287   } | 
| pierre@0 | 288   return $target; | 
| pierre@0 | 289 } | 
| pierre@0 | 290 | 
| pierre@0 | 291 /** | 
| pierre@1 | 292  * Force the cache to be flushed. | 
| pierre@1 | 293  */ | 
| pierre@1 | 294 function ad_rebuild_cache($verbose = FALSE) { | 
| pierre@1 | 295   $cache = variable_get('ad_cache', 'none'); | 
| pierre@1 | 296   $build = "ad_cache_{$cache}_build"; | 
| pierre@1 | 297   if (function_exists($build)) { | 
| pierre@1 | 298     if ($verbose) { | 
| pierre@1 | 299       drupal_set_message('Rebuilding ad cache.'); | 
| pierre@1 | 300     } | 
| pierre@1 | 301     $build(); | 
| pierre@1 | 302   } | 
| pierre@1 | 303 } | 
| pierre@1 | 304 | 
| pierre@1 | 305 /** | 
| pierre@0 | 306  * Ad API Helper Function: | 
| pierre@0 | 307  * Append rel="nofollow" if globally enabled. | 
| pierre@0 | 308  */ | 
| pierre@0 | 309 function ad_link_nofollow() { | 
| pierre@0 | 310   if (variable_get('ad_link_nofollow', 0)) { | 
| pierre@0 | 311     $nofollow = array('rel' => 'nofollow'); | 
| pierre@0 | 312   } | 
| pierre@0 | 313   else { | 
| pierre@0 | 314     $nofollow = array(); | 
| pierre@0 | 315   } | 
| pierre@0 | 316   return $nofollow; | 
| pierre@0 | 317 } | 
| pierre@0 | 318 | 
| pierre@0 | 319 /** | 
| pierre@0 | 320  * Increment action counter. | 
| pierre@0 | 321  */ | 
| pierre@0 | 322 function ad_statistics_increment($aid, $action, $group = NULL, $hostid = NULL) { | 
| pierre@0 | 323   // Update action statistics. | 
| pierre@0 | 324   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); | 
| pierre@0 | 325   // If column doesn't already exist, we need to add it. | 
| pierre@0 | 326   if (!db_affected_rows()) { | 
| pierre@0 | 327     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); | 
| pierre@0 | 328     // If another process already added this row our INSERT will fail, if so we | 
| pierre@0 | 329     // still need to increment it so we don't loose an action. | 
| pierre@0 | 330     if (!db_affected_rows()) { | 
| pierre@0 | 331       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); | 
| pierre@0 | 332     } | 
| pierre@0 | 333   } | 
| pierre@0 | 334 | 
| pierre@0 | 335   $event = array('aid' => $aid, 'action' => $action, 'hostid' => $hostid); | 
| pierre@0 | 336   module_invoke_all('adapi', 'statistics_increment', $event); | 
| pierre@0 | 337 } | 
| pierre@0 | 338 | 
| pierre@1 | 339 /** | 
| pierre@1 | 340  * Return an array with all status values user has permission to set. | 
| pierre@1 | 341  * A user with 'administer advertisements' permission can update any status. | 
| pierre@1 | 342  */ | 
| pierre@1 | 343 function ad_status_array($aid = 0, $status = NULL) { | 
| pierre@1 | 344   $permissions = array(); | 
| pierre@1 | 345   // mark status as pending | 
| pierre@1 | 346   if (user_access('administer advertisements') || | 
| pierre@1 | 347       $status == 'pending' || $status == NULL || | 
| pierre@1 | 348       ad_permission($aid, 'set status as pending')) { | 
| pierre@1 | 349     $permissions['pending'] = t('This advertisement is currently waiting for administrative approval.'); | 
| pierre@0 | 350   } | 
| pierre@1 | 351   // mark status from pending to approved | 
| pierre@1 | 352   if (user_access('administer advertisements') || | 
| pierre@1 | 353       $status == 'approved' || | 
| pierre@1 | 354       ($status == 'pending' && | 
| pierre@1 | 355        ad_permission($aid, 'set status from pending to approved'))) { | 
| pierre@1 | 356     $permissions['approved'] = t('This advertisement has been approved and is currently waiting to be activated.'); | 
| pierre@0 | 357   } | 
| pierre@1 | 358   // mark status as active (from pending, approved, or offline) | 
| pierre@1 | 359   if (user_access('administer advertisements') || | 
| pierre@1 | 360       $status == 'active' || | 
| pierre@1 | 361       ($status == 'approved' && | 
| pierre@1 | 362        ad_permission($aid, 'set status from approved to active')) || | 
| pierre@1 | 363       ($status == 'offline' && | 
| pierre@1 | 364        ad_permission($aid, 'set status from offline to active'))) { | 
| pierre@1 | 365     $permissions['active'] = t('This advertisement is actively being displayed.'); | 
| pierre@1 | 366   } | 
| pierre@1 | 367   // mark status as offline (from pending, approved, or active) | 
| pierre@1 | 368   if (user_access('administer advertisements') || | 
| pierre@1 | 369       $status == 'offline' || | 
| pierre@1 | 370       ($status == 'approved' && | 
| pierre@1 | 371        ad_permission($aid, 'set status from approved to offline')) || | 
| pierre@1 | 372       ($status == 'active' && | 
| pierre@1 | 373        ad_permission($aid, 'set status from active to offline'))) { | 
| pierre@1 | 374     $permissions['offline'] = t('This advertisement has been temporarily disabled by its owner and is not currently being displayed.'); | 
| pierre@1 | 375   } | 
| pierre@1 | 376   // mark status as expired (from active or offline) | 
| pierre@1 | 377   if (user_access('administer advertisements') || | 
| pierre@1 | 378       $status == 'expired' || | 
| pierre@1 | 379       ($status == 'active' && | 
| pierre@1 | 380        ad_permission($aid, 'set status from active to expired')) || | 
| pierre@1 | 381       ($status == 'offline' && | 
| pierre@1 | 382        ad_permission($aid, 'set status from offline to expired'))) { | 
| pierre@1 | 383     $permissions['expired'] = t('This advertisement has expired and is no longer being displayed.'); | 
| pierre@1 | 384   } | 
| pierre@1 | 385   // mark status as denied (from pending or any) | 
| pierre@1 | 386   if (user_access('administer advertisements') || | 
| pierre@1 | 387       $status == 'denied' || | 
| pierre@1 | 388       ($status == 'pending' && | 
| pierre@1 | 389        ad_permission($aid, 'set status from pending to denied')) || | 
| pierre@1 | 390       ad_permission($aid, 'set status as denied')) { | 
| pierre@1 | 391     $permissions['denied'] = t('This advertisement was refused by the site administrator and will not be displayed.'); | 
| pierre@1 | 392   } | 
| pierre@1 | 393   return $permissions; | 
| pierre@0 | 394 } | 
| pierre@0 | 395 | 
| pierre@0 | 396 /** | 
| pierre@0 | 397  * Display the status of the currently viewed ad. | 
| pierre@0 | 398  */ | 
| pierre@0 | 399 function theme_ad_status_display($node) { | 
| pierre@1 | 400   if (isset($node->adstatus)) { | 
| pierre@1 | 401     $status_array = ad_status_array($node->nid, $node->adstatus); | 
| pierre@1 | 402     $output  = '<div class="adstatus">'; | 
| pierre@1 | 403     $output .= '<p>'. t($status_array[$node->adstatus]) .'</p>'; | 
| pierre@1 | 404     switch ($node->adstatus) { | 
| pierre@1 | 405       case 'approved': | 
| pierre@1 | 406         if ($node->autoactivate) { | 
| pierre@1 | 407           $output .= '<p>'. t('This advertisement will be automatically activated on %timestamp, in %time.', array('%timestamp' => format_date($node->autoactivate, 'large'), '%time' => format_interval($node->autoactivate - time()))) .'</p>'; | 
| pierre@1 | 408         } | 
| pierre@1 | 409         break; | 
| pierre@1 | 410       case 'active': | 
| pierre@1 | 411         $activated = db_result(db_query("SELECT activated FROM {ads} WHERE aid = %d", $node->nid)); | 
| pierre@1 | 412         if ($activated) { | 
| pierre@1 | 413           $output .= '<p>'. t('This advertisement has been active since %date.', array('%date' => format_date($activated, 'large'))) .'</p>'; | 
| pierre@1 | 414         } | 
| pierre@1 | 415         if ($node->autoexpire) { | 
| pierre@1 | 416           $output .= '<p>'. t('This advertisement will expire on %timestamp, in %time.', array('%timestamp' => format_date($node->autoexpire, 'large'), '%time' => format_interval($node->autoexpire - time()))) .'</p>'; | 
| pierre@1 | 417         } | 
| pierre@1 | 418         if ($node->maxviews) { | 
| pierre@1 | 419           $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))); | 
| pierre@1 | 420           $output .= '<p>'. t('This advertisement will expire after %left more impressions.', array('%left' => $node->maxviews - $views)) .'</p>'; | 
| pierre@1 | 421         } | 
| pierre@1 | 422         if ($node->maxclicks) { | 
| pierre@1 | 423           $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))); | 
| pierre@1 | 424           $output .= '<p>'. t('This advertisement will expire after %left more clicks.', array('%left' => $node->maxclicks - $clicks)) .'</p>'; | 
| pierre@1 | 425         } | 
| pierre@1 | 426         break; | 
| pierre@1 | 427       case 'expired': | 
| pierre@1 | 428         $expired = db_result(db_query("SELECT expired FROM {ads} WHERE aid = %d", $node->nid)); | 
| pierre@1 | 429         if ($expired) { | 
| pierre@1 | 430           $output .= '<p>'. t('This advertisement expired %date.', array('%date' => format_date($expired, 'large'))) .'</p>'; | 
| pierre@1 | 431         } | 
| pierre@1 | 432         break; | 
| pierre@1 | 433     } | 
| pierre@1 | 434     $output .= '</div>'; | 
| pierre@1 | 435     return theme('box', t('Status'), $output); | 
| pierre@0 | 436   } | 
| pierre@0 | 437 } | 
| pierre@0 | 438 | 
| pierre@0 | 439 /** | 
| piotre@7 | 440  * Implementation of hook_init. | 
| piotre@7 | 441  */ | 
| piotre@7 | 442 function ad_init() { | 
| piotre@7 | 443   // We do this in the init hook so that it doesn't get skipped when block | 
| piotre@7 | 444   // caching is enabled. | 
| piotre@7 | 445   $method = variable_get('ad_display', 'javascript'); | 
| piotre@7 | 446   if ($method == 'jquery') { | 
| piotre@7 | 447     drupal_add_js('misc/jquery.js', 'core'); | 
| piotre@7 | 448   } | 
| piotre@7 | 449 } | 
| piotre@7 | 450 | 
| piotre@7 | 451 /** | 
| pierre@0 | 452  * Implementation of hook_help(). | 
| pierre@0 | 453  */ | 
| pierre@0 | 454 function ad_help($path, $arg) { | 
| pierre@0 | 455   $output = ''; | 
| pierre@0 | 456   switch ($path) { | 
| pierre@0 | 457     case 'admin/help#ad': | 
| pierre@0 | 458       $output = '<p>'. t('The ad module provides a complete advertising system for Drupal powered websites.  It does this through an API that allow other modules to handle various types of advertising content.  For example, if enabled together with the ad_image module you will be able to display image based advertisements such as banner ads.') .'</p>'; | 
| pierre@0 | 459       break; | 
| pierre@0 | 460     case 'node/add/ad': | 
| pierre@0 | 461       $output = '<p>'. t('Advertisements can be randomly displayed to visitors of your website.') .'</p>'; | 
| pierre@0 | 462       break; | 
| pierre@0 | 463   } | 
| pierre@0 | 464   return $output; | 
| pierre@0 | 465 } | 
| pierre@0 | 466 | 
| pierre@0 | 467 /** | 
| pierre@0 | 468  * Implementation of hook_cron(). | 
| pierre@0 | 469  */ | 
| pierre@0 | 470 function ad_cron() { | 
| pierre@0 | 471   if (time() - variable_get('ad_cron_timestamp', 0) >= 60) { | 
| pierre@0 | 472     // Locate ads that need to be activated or expired. | 
| pierre@0 | 473     $result = db_query('SELECT aid, adstatus, adtype, autoactivate, autoactivated, autoexpire, autoexpired FROM {ads} WHERE autoactivate <> 0 OR autoexpire <> 0'); | 
| pierre@0 | 474     while ($ad = db_fetch_object($result)) { | 
| pierre@0 | 475       switch ($ad->adstatus) { | 
| pierre@0 | 476         case 'approved': { | 
| pierre@0 | 477           // See if this ad is ready to be activated. | 
| pierre@0 | 478           if ($ad->autoactivate && $ad->autoactivate <= time()) { | 
| pierre@0 | 479             $node = node_load($ad->aid); | 
| pierre@0 | 480 | 
| pierre@0 | 481             // Activate the ad. | 
| pierre@0 | 482             db_query("UPDATE {ads} SET adstatus = 'active', autoactivate = 0, autoactivated = %d, activated = %d WHERE aid = %d", time(), time(), $ad->aid); | 
| pierre@0 | 483             ad_statistics_increment($ad->aid, 'autoactivated'); | 
| pierre@0 | 484             ad_statistics_increment($ad->aid, 'active'); | 
| pierre@0 | 485 | 
| pierre@0 | 486             watchdog('ad', 'Automatically activated ad %title with nid %nid.', array('%title' => $node->title, '%nid' => $node->nid)); | 
| pierre@0 | 487 | 
| pierre@0 | 488             // Allow modules to do special processing to automatically | 
| pierre@0 | 489             // activated advertisements. | 
| pierre@0 | 490             module_invoke('ad_'. $ad->adtype, 'adapi', 'autoactivate', $node); | 
| pierre@0 | 491           } | 
| pierre@0 | 492           else if (!$ad->autoactivate) { | 
| pierre@0 | 493             // Once daily warn that there's an ad stuck in approved state. | 
| pierre@0 | 494             if (time() - variable_get("ad_autoactivate_warning_$ad->aid", 0) >= 8600) { | 
| pierre@0 | 495               watchdog('ad', 'Warning: ad %title with nid %nid in approved state has no autoactivate date set.', array('%title' => $node->title, '%nid' => $node->nid)); | 
| pierre@0 | 496               variable_set("ad_autoactivate_warning_$ad->aid", time()); | 
| pierre@0 | 497             } | 
| pierre@0 | 498           } | 
| pierre@0 | 499           break; | 
| pierre@0 | 500         } | 
| pierre@0 | 501         case 'active': { | 
| pierre@0 | 502           // See if this ad is ready to be activated. | 
| pierre@0 | 503           if ($ad->autoexpire && $ad->autoexpire <= time()) { | 
| pierre@0 | 504             $node = node_load($ad->aid); | 
| pierre@0 | 505 | 
| pierre@0 | 506             // Expire the ad. | 
| pierre@0 | 507             db_query("UPDATE {ads} SET adstatus = 'expired', autoexpire = 0, autoexpired = %d, expired = %d WHERE aid = %d", time(), time(), $ad->aid); | 
| pierre@0 | 508             ad_statistics_increment($ad->aid, 'autoexpired'); | 
| pierre@0 | 509             ad_statistics_increment($ad->aid, 'expired'); | 
| pierre@0 | 510 | 
| pierre@0 | 511             watchdog('ad', 'Automatically expired ad %title with nid %nid.', array('%title' => $node->title, '%nid' => $node->nid)); | 
| pierre@0 | 512 | 
| pierre@0 | 513             // Allow modules to do special processing to automatically | 
| pierre@0 | 514             // activated advertisements. | 
| pierre@0 | 515             module_invoke('ad_'. $ad->adtype, 'adapi', 'autoexpire', $node); | 
| pierre@0 | 516           } | 
| pierre@0 | 517           else if (!$ad->autoexpire) { | 
| pierre@0 | 518             // Ad is already activated, but has autoactivate timestamp set. | 
| pierre@0 | 519             db_query("UPDATE {ads} SET autoactivate = 0 WHERE aid = %d", $ad->aid); | 
| pierre@0 | 520           } | 
| pierre@0 | 521           break; | 
| pierre@0 | 522         } | 
| pierre@0 | 523         default: | 
| pierre@0 | 524           $node = node_load($ad->aid); | 
| pierre@0 | 525           db_query('UPDATE {ads} SET autoactivate = 0, autoexpire = 0 WHERE aid = %d', $ad->aid); | 
| pierre@0 | 526           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)); | 
| pierre@0 | 527       } | 
| pierre@0 | 528     } | 
| pierre@0 | 529     variable_set('ad_cron_timestamp', time()); | 
| pierre@0 | 530   } | 
| pierre@0 | 531 } | 
| pierre@0 | 532 | 
| pierre@0 | 533 /** | 
| pierre@0 | 534  * Implementation of hook_perm(). | 
| pierre@0 | 535  */ | 
| pierre@0 | 536 function ad_perm() { | 
| pierre@0 | 537   return array('administer advertisements', | 
| pierre@0 | 538                 'create advertisements', | 
| pierre@0 | 539                 'edit own advertisements', | 
| pierre@1 | 540                 'edit any advertisement', | 
| pierre@1 | 541                 'delete own advertisements', | 
| pierre@1 | 542                 'delete any advertisement', | 
| pierre@0 | 543                 'show advertisements'); | 
| pierre@0 | 544 } | 
| pierre@0 | 545 | 
| pierre@0 | 546 /** | 
| pierre@0 | 547  * Implementation of hook_node_info(). | 
| pierre@0 | 548  */ | 
| pierre@0 | 549 function ad_node_info() { | 
| pierre@0 | 550   $items['ad'] = array( | 
| pierre@0 | 551     'name' => t('Advertisement'), | 
| pierre@0 | 552     'module' => 'ad', | 
| pierre@0 | 553     'description' => t('Advertisements can be randomly displayed to visitors of your website.'), | 
| pierre@0 | 554   ); | 
| pierre@0 | 555   return $items; | 
| pierre@0 | 556 } | 
| pierre@0 | 557 | 
| pierre@0 | 558 /** | 
| pierre@0 | 559  * Implementation of hook_access(). | 
| pierre@0 | 560  */ | 
| pierre@0 | 561 function ad_access($op, $node, $account) { | 
| pierre@1 | 562   switch ($op) { | 
| pierre@1 | 563     case 'create': | 
| pierre@1 | 564       return (user_access('create advertisements', $account) || user_access('administer advertisements')); | 
| pierre@1 | 565     case 'update': | 
| pierre@1 | 566       return (user_access('edit any advertisement', $account) || (user_access('edit own advertisements', $account) && is_ad_owner($node->nid)) || user_access('administer advertisements', $account)); | 
| pierre@1 | 567     case 'delete': | 
| pierre@1 | 568       return (user_access('delete any advertisement', $account) || (user_access('delete own advertisements', $account) && is_ad_owner($node->nid)) || user_access('administer advertisements', $account)); | 
| pierre@1 | 569     case 'view': | 
| pierre@1 | 570       return (user_access('show advertisements', $account) || user_access('administer advertisements', $account)); | 
| pierre@0 | 571   } | 
| pierre@0 | 572 } | 
| pierre@0 | 573 | 
| pierre@0 | 574 /** | 
| pierre@0 | 575  * Implementation of hook_form(). | 
| pierre@0 | 576  */ | 
| pierre@1 | 577 function ad_form(&$node, &$form_state) { | 
| pierre@0 | 578   $form = array(); | 
| pierre@0 | 579 | 
| pierre@1 | 580   // When form_state is not empty, we should rather use it's values | 
| pierre@1 | 581   // to not loose data if validation fails. | 
| pierre@1 | 582   if (!empty($form_state['values'])) { | 
| pierre@1 | 583     $node = (object)$form_state['values']; | 
| pierre@0 | 584   } | 
| pierre@0 | 585 | 
| pierre@0 | 586   $form['aid'] = array( | 
| pierre@0 | 587     '#type' => 'value', | 
| pierre@0 | 588     '#value' => isset($node->nid) ? $node->nid : 0, | 
| pierre@0 | 589   ); | 
| pierre@0 | 590 | 
| pierre@0 | 591   $form['title'] = array( | 
| pierre@0 | 592     '#type' => 'textfield', | 
| pierre@0 | 593     '#title' => t('Title'), | 
| pierre@0 | 594     '#required' => TRUE, | 
| pierre@0 | 595     '#default_value' => isset($node->title) ? $node->title : '', | 
| pierre@0 | 596   ); | 
| sly@8 | 597   if ($type->has_body) { | 
| sly@8 | 598     $form['body_filter']['body'] = array( | 
| sly@8 | 599       '#type' => 'textarea', | 
| sly@8 | 600       '#title' => t('Description'), | 
| sly@8 | 601       '#default_value' => isset($node->body) ? $node->body : '', | 
| sly@8 | 602       '#rows' => 3 | 
| sly@8 | 603     ); | 
| sly@8 | 604   } | 
| pierre@0 | 605   $form['body_filter']['format'] = filter_form($node->format); | 
| pierre@0 | 606 | 
| pierre@0 | 607   // determine the current ad type | 
| pierre@0 | 608   if (!isset($adtype)) { | 
| pierre@0 | 609     $adtypes = ad_get_types(); | 
| sly@8 | 610     if (count($adtypes) == 1) { | 
| pierre@0 | 611       $adtype = key($adtypes); | 
| pierre@0 | 612     } | 
| sly@8 | 613     else if (!count($adtypes)) { | 
| pierre@0 | 614       drupal_set_message(t('At least one ad type module must be enabled before you can create advertisements.  For example, try <a href="!url">enabling</a> the ad_text or ad_image module.', array('!url' => url('admin/build/modules'))), 'error'); | 
| pierre@0 | 615     } | 
| pierre@0 | 616   } | 
| pierre@0 | 617 | 
| pierre@1 | 618   // display ad type switch | 
| sly@8 | 619   if ((!isset($node->adtype) || isset($node->adtype_select)) && | 
| sly@8 | 620        count($adtypes) >1) { | 
| pierre@1 | 621     $adtypes = array(0 => '---'); | 
| pierre@1 | 622     $adtypes += ad_get_types('name'); | 
| pierre@1 | 623     $form['select'] = array( | 
| pierre@1 | 624       '#type' => 'fieldset', | 
| pierre@1 | 625       '#title' => t('Select Ad type'), | 
| pierre@1 | 626       '#prefix' => '<div class="container-inline">', | 
| pierre@1 | 627       '#suffix' => '</div>', | 
| pierre@1 | 628       '#weight' => 3, | 
| pierre@1 | 629     ); | 
| pierre@1 | 630     $form['select']['adtype_select'] = array( | 
| pierre@1 | 631       '#type' => 'select', | 
| pierre@1 | 632       '#required' => TRUE, | 
| pierre@1 | 633       '#options' => $adtypes, | 
| pierre@1 | 634       '#default_value' => isset($node->adtype_select) ? $node->adtype_select : '', | 
| pierre@1 | 635     ); | 
| pierre@1 | 636     $form['select']['adtype_submit'] = array( | 
| pierre@1 | 637       '#type' => 'submit', | 
| pierre@1 | 638       '#value' => t('Select'), | 
| pierre@1 | 639       '#validate' => array('ad_select_adtype'), | 
| pierre@1 | 640       '#ahah' => array( | 
| pierre@1 | 641         'path' => 'node/add/ad/ahah', | 
| pierre@1 | 642         'wrapper' => 'adtype-ahah-wrapper', | 
| pierre@1 | 643       ), | 
| pierre@1 | 644     ); | 
| pierre@1 | 645   } | 
| pierre@0 | 646   // display type-specific options | 
| sly@8 | 647   if ((isset($node->adtype) && $node->adtype) || count($adtypes) == 1) { | 
| pierre@1 | 648     if (isset($node->adtype_select) && $node->adtype_select && ($node->adtype_select != $node->adtype)) { | 
| pierre@1 | 649       $node->adtype = $node->adtype_select; | 
| pierre@0 | 650     } | 
| sly@8 | 651     if (count($adtypes) == 1) { | 
| sly@8 | 652       $node->adtype = $adtype; | 
| sly@8 | 653     } | 
| pierre@1 | 654     ad_form_add_adtype_elements($form, $node->adtype, $node); | 
| pierre@1 | 655     // add ahah wrapper | 
| pierre@1 | 656     $form['adtype_elements']['#prefix'] = '<div id="adtype-ahah-wrapper">'; | 
| pierre@1 | 657     $form['adtype_elements']['#suffix'] = '</div>'; | 
| pierre@1 | 658   } | 
| pierre@1 | 659   if (!isset($form['adtype_elements'])) { | 
| pierre@1 | 660     $form['adtype_elements'] = array( | 
| pierre@1 | 661       '#value' => '<div id="adtype-ahah-wrapper"></div>', | 
| pierre@1 | 662       '#weight' => 3.1, | 
| pierre@0 | 663     ); | 
| pierre@0 | 664   } | 
| pierre@0 | 665 | 
| pierre@1 | 666   // fieldset for updating ad status | 
| pierre@1 | 667   $form['adstatus'] = array( | 
| pierre@1 | 668     '#type' => 'fieldset', | 
| pierre@1 | 669     '#title' => t('Status'), | 
| pierre@1 | 670     '#collapsible' => TRUE, | 
| pierre@1 | 671     '#weight' => 4, | 
| pierre@1 | 672   ); | 
| pierre@1 | 673   $nid = isset($node->nid) ? $node->nid : 0; | 
| pierre@1 | 674   $adstatus = isset($node->adstatus) ? $node->adstatus : ''; | 
| pierre@1 | 675   // display all available status options | 
| pierre@1 | 676   foreach (ad_status_array($nid, $adstatus) as $status => $description) { | 
| pierre@1 | 677     $form['adstatus']["ad$status"] = array( | 
| pierre@1 | 678       '#type' => 'radio', | 
| pierre@1 | 679       '#title' => t("$status"), | 
| pierre@1 | 680       '#return_value' => $status, | 
| pierre@1 | 681       '#default_value' => isset($node->adstatus) ? $node->adstatus : 'pending', | 
| pierre@1 | 682       '#description' => "$description", | 
| pierre@1 | 683       '#parents' => array("adstatus") | 
| pierre@0 | 684     ); | 
| pierre@0 | 685   } | 
| pierre@0 | 686 | 
| pierre@0 | 687   // display scheduling options | 
| pierre@0 | 688   $form['schedule'] = array( | 
| pierre@0 | 689     '#type' => 'fieldset', | 
| pierre@0 | 690     '#title' => t('Scheduling'), | 
| pierre@0 | 691     '#collapsible' => TRUE, | 
| pierre@0 | 692     // Collapse if there isn't any scheduling data set. | 
| pierre@0 | 693     '#collapsed' => ( | 
| pierre@0 | 694       isset($node->autoactivate) || | 
| pierre@0 | 695       isset($form_state['values']['autoactivate']) || | 
| pierre@0 | 696       isset($node->autoexpire) || | 
| pierre@0 | 697       isset($form_state['values']['autoexpire']) || | 
| pierre@0 | 698       isset($node->maxviews) || | 
| pierre@0 | 699       isset($form_state['values']['maxviews']) || | 
| pierre@0 | 700       isset($node->maxclicks) || | 
| pierre@0 | 701       isset($form_state['values']['maxclicks'])) | 
| pierre@0 | 702       ? FALSE : TRUE, | 
| pierre@0 | 703   ); | 
| pierre@0 | 704 | 
| pierre@1 | 705   if ((isset($node->nid) && ad_permission($node->nid, 'manage status')) || | 
| pierre@1 | 706       user_access('administer advertisements')) { | 
| pierre@0 | 707     $form['schedule']['current'] = array( | 
| pierre@0 | 708       '#type' => 'markup', | 
| pierre@0 | 709       '#prefix' => '<div>', | 
| pierre@0 | 710       '#suffix' => '</div>', | 
| pierre@0 | 711       '#value' => t('The current date and time is "%date".', array('%date' => format_date(time(), 'custom', 'F j, Y H:i'))) | 
| pierre@0 | 712     ); | 
| pierre@0 | 713     $form['schedule']['autoactivate'] = array( | 
| pierre@0 | 714       '#type' => 'textfield', | 
| pierre@0 | 715       '#title' => t('Automatically activate ad'), | 
| pierre@0 | 716       '#required' => FALSE, | 
| pierre@0 | 717       '#default_value' => isset($node->autoactivate) && $node->autoactivate > 0 ? format_date((int)$node->autoactivate, 'custom', 'F j, Y H:i') : 0, | 
| pierre@0 | 718       '#description' => t('You can specify a date and time for this advertisement to be automatically activated.  The advertisement needs to be in an <em>approved</em> state before it can be automatically activated.  If you prefer to activate the advertisement immediately, leave this field empty.') | 
| pierre@0 | 719     ); | 
| pierre@0 | 720   } | 
| pierre@0 | 721 | 
| pierre@0 | 722   if (user_access('administer advertisements')) { | 
| pierre@0 | 723     // admins can expire advertisements | 
| pierre@0 | 724     $form['schedule']['autoexpire'] = array( | 
| pierre@0 | 725       '#type' => 'textfield', | 
| pierre@0 | 726       '#title' => t('Automatically expire ad'), | 
| pierre@0 | 727       '#required' => FALSE, | 
| pierre@0 | 728       '#default_value' => isset($node->autoexpire) && $node->autoexpire > 0 ? format_date((int)$node->autoexpire, 'custom', 'F j, Y H:i') : 0, | 
| pierre@0 | 729       '#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.') | 
| pierre@0 | 730     ); | 
| pierre@0 | 731     $form['schedule']['maxviews'] = array( | 
| pierre@0 | 732       '#type' => 'textfield', | 
| pierre@0 | 733       '#title' => t('Maximum impressions'), | 
| pierre@0 | 734       '#required' => FALSE, | 
| pierre@0 | 735       '#size' => 10, | 
| pierre@0 | 736       '#maxlength' => 11, | 
| pierre@0 | 737       '#default_value' => isset($node->maxviews) ? $node->maxviews : 0, | 
| pierre@0 | 738       '#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')), | 
| pierre@0 | 739     ); | 
| pierre@0 | 740     $form['schedule']['maxclicks'] = array( | 
| pierre@0 | 741       '#type' => 'textfield', | 
| pierre@0 | 742       '#title' => t('Maximum clicks'), | 
| pierre@0 | 743       '#required' => FALSE, | 
| pierre@0 | 744       '#size' => 10, | 
| pierre@0 | 745       '#maxlength' => 11, | 
| pierre@0 | 746       '#default_value' => isset($node->maxclicks) ? $node->maxclicks : 0, | 
| pierre@0 | 747       '#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')), | 
| pierre@0 | 748     ); | 
| pierre@0 | 749   } | 
| pierre@0 | 750   else { | 
| pierre@0 | 751     // display expiration time | 
| pierre@0 | 752     $form['schedule']['autoexpire_display'] = array( | 
| pierre@0 | 753       '#type' => 'markup', | 
| pierre@0 | 754       '#prefix' => '<div>', | 
| pierre@0 | 755       '#suffix' => '</div>', | 
| pierre@0 | 756       '#value' => theme('ad_status_display', $node), | 
| pierre@0 | 757     ); | 
| pierre@0 | 758     $form['schedule']['autoexpire'] = array( | 
| pierre@0 | 759       '#type' => 'hidden', | 
| pierre@0 | 760       '#value' => isset($node->autoexpire) ? $node->autoexpire : 0, | 
| pierre@0 | 761     ); | 
| pierre@0 | 762   } | 
| pierre@0 | 763 | 
| pierre@1 | 764   $form['#validate'][] = 'ad_select_adtype'; | 
| pierre@0 | 765   return $form; | 
| pierre@0 | 766 } | 
| pierre@0 | 767 | 
| pierre@0 | 768 /** | 
| pierre@1 | 769  * Ad type switch submit handler. | 
| pierre@1 | 770  */ | 
| pierre@1 | 771 function ad_select_adtype(&$form, &$form_state) { | 
| pierre@1 | 772   if (!$form_state['values']['adtype'] && !$form_state['values']['adtype_select']) { | 
| pierre@1 | 773     form_set_error('adtype_select', t('Please, select an Ad type.')); | 
| pierre@1 | 774   } | 
| pierre@1 | 775   if (!isset($form_state['values']['adtype']) || isset($form_state['values']['adtype_select']) && $form_state['values']['adtype'] != $form_state['values']['adtype_select']) { | 
| pierre@1 | 776     $form_state['values']['adtype'] = $form_state['values']['adtype_select']; | 
| pierre@1 | 777     $form_state['rebuild'] = TRUE; | 
| pierre@1 | 778   } | 
| pierre@1 | 779 } | 
| pierre@1 | 780 | 
| pierre@1 | 781 /** | 
| pierre@1 | 782  * Ad type switch AHAH menu handler. | 
| pierre@1 | 783  */ | 
| pierre@1 | 784 function ad_form_ahah() { | 
| pierre@1 | 785   $form_state = array('storage' => NULL, 'submitted' => FALSE); | 
| pierre@1 | 786   $form_build_id = $_POST['form_build_id']; | 
| pierre@1 | 787   $form = form_get_cache($form_build_id, $form_state); | 
| pierre@1 | 788   ad_form_add_adtype_elements($form, $_POST['adtype_select']); | 
| pierre@1 | 789   form_set_cache($form_build_id, $form, $form_state); | 
| pierre@1 | 790   $form += array( | 
| pierre@1 | 791     '#post' => $_POST, | 
| pierre@1 | 792     '#programmed' => FALSE, | 
| pierre@1 | 793   ); | 
| pierre@1 | 794   // Rebuild the form. | 
| pierre@1 | 795   $form = form_builder($_POST['form_id'], $form, $form_state); | 
| pierre@1 | 796   $output = drupal_render($form['adtype_elements']); | 
| pierre@1 | 797   drupal_json(array( | 
| pierre@1 | 798     'status'   => TRUE, | 
| pierre@1 | 799     'data'     => $output, | 
| pierre@1 | 800   )); | 
| pierre@1 | 801 } | 
| pierre@1 | 802 | 
| pierre@1 | 803 /** | 
| pierre@1 | 804  * Loads Ad type elements into form. | 
| pierre@1 | 805  */ | 
| pierre@1 | 806 function ad_form_add_adtype_elements(&$form, $adtype, $node = NULL) { | 
| pierre@1 | 807   unset($form['adtype_elements']); | 
| pierre@1 | 808   $form['adtype_elements'] = module_invoke('ad_'. $adtype, 'adapi', 'form', $node); | 
| pierre@1 | 809   $form['adtype'] = array( | 
| pierre@1 | 810     '#type' => 'hidden', | 
| pierre@1 | 811     '#value' => $adtype, | 
| pierre@1 | 812   ); | 
| pierre@1 | 813   $form['adtype_elements']['#weight'] = 3.1; | 
| pierre@1 | 814 } | 
| pierre@1 | 815 | 
| pierre@1 | 816 /** | 
| pierre@0 | 817  * Implementation of hook_form_alter(). | 
| pierre@0 | 818  */ | 
| pierre@0 | 819 function ad_form_alter(&$form, &$form_state, $form_id) { | 
| pierre@0 | 820   if ($form_id == 'taxonomy_form_vocabulary') { | 
| pierre@0 | 821     // Remove taxonomy form options not applicable for ad groups. | 
| pierre@0 | 822     if ($form['vid']['#value'] == _ad_get_vid()) { | 
| pierre@0 | 823       $form['help_ad_vocab'] = array( | 
| pierre@0 | 824         '#value' => t('This vocabulary was automatically created for use by the ad module.  Only applicable options are available.'), | 
| pierre@0 | 825         '#weight' => -1 | 
| pierre@0 | 826       ); | 
| pierre@0 | 827       $form['nodes']['ad'] = array( | 
| pierre@0 | 828         '#type' => 'checkbox', | 
| pierre@0 | 829         '#title' => t('ad group'), | 
| pierre@0 | 830         '#value' => 1, | 
| pierre@0 | 831         '#attributes' => array('disabled' => ''), | 
| pierre@0 | 832         '#description' => t('Type %type is required to use this vocabulary.', array('%type' => t('ad group'))) | 
| pierre@0 | 833       ); | 
| pierre@0 | 834       $form['tags']['#description'] = t('If enabled, ads are categorized by typing ad group names instead of choosing them from a list.'); | 
| pierre@0 | 835       $form['multiple']['#description'] = t('If enabled, allows ads to have more than one ad group (always true for free tagging).'); | 
| pierre@0 | 836       $form['required']['#description'] = t('If enabled, every ad <strong>must</strong> be assigned to at least one ad group.'); | 
| pierre@0 | 837       $form['hierarchy'] = array( | 
| pierre@0 | 838         '#type' => 'value', | 
| pierre@0 | 839         '#value' => 0 | 
| pierre@0 | 840       ); | 
| pierre@0 | 841       unset($form['relations']); | 
| pierre@0 | 842     } | 
| pierre@0 | 843     else { | 
| pierre@0 | 844       unset($form['nodes']['ad']); | 
| pierre@0 | 845     } | 
| pierre@0 | 846   } | 
| pierre@0 | 847   else if ($form_id == 'taxonomy_form_term') { | 
| pierre@0 | 848     if ($form['vid']['#value'] == _ad_get_vid()) { | 
| pierre@0 | 849       $form['name']['#title'] = t('Ad group name'); | 
| pierre@0 | 850       $form['name']['#description'] = t('The name for this ad group.  Example: "Linux".'); | 
| pierre@0 | 851       $form['description']['#description'] = t('A description of the ad group.'); | 
| pierre@0 | 852       $form['description']['#required'] = TRUE; | 
| pierre@0 | 853       $form['weight']['#description'] = t('In listings, the heavier ad groups will sink and the lighter ad groups will be positioned nearer the top.'); | 
| pierre@0 | 854       unset($form['synonyms']); | 
| pierre@0 | 855     } | 
| pierre@0 | 856   } | 
| sly@3 | 857   else if ($form_id == 'search_form' && variable_get('ad_no_search', 1) && !user_access('administer advertisements') && !user_access('administer any advertisement')) { | 
| sly@3 | 858     $vid = _ad_get_vid(); | 
| sly@3 | 859     $vocabulary = db_result(db_query('SELECT name FROM {vocabulary} WHERE vid = %d', $vid)); | 
| sly@3 | 860     unset($form['advanced']['category']['#options'][$vocabulary]); | 
| sly@3 | 861     if (empty($form['advanced']['category']['#options'])) { | 
| sly@3 | 862       unset($form['advanced']['category']); | 
| sly@3 | 863     } | 
| sly@3 | 864     unset($form['advanced']['type']['#options']['ad']); | 
| sly@3 | 865   } | 
| sly@3 | 866 } | 
| sly@3 | 867 | 
| sly@3 | 868 /** | 
| sly@3 | 869  * Implementation of hook_db_rewrite_sql(). | 
| sly@3 | 870  */ | 
| sly@3 | 871 function ad_db_rewrite_sql($query, $primary_table, $primary_field, $args) { | 
| sly@3 | 872   if (variable_get('ad_no_search', 1) && !user_access('administer advertisements') && !user_access('edit any advertisement') && $query == '' && $primary_table == 'n' && $primary_field = 'nid' && empty($args)) { | 
| sly@3 | 873     return array('where' => " n.type != 'ad'"); | 
| sly@3 | 874   } | 
| pierre@0 | 875 } | 
| pierre@0 | 876 | 
| pierre@0 | 877 /** | 
| pierre@0 | 878  * Implementation of hook_nodeapi(). | 
| pierre@0 | 879  */ | 
| pierre@0 | 880 function ad_nodeapi(&$node, $op, $teaser, $page) { | 
| pierre@0 | 881   global $user; | 
| pierre@0 | 882 | 
| pierre@0 | 883   switch ($op) { | 
| pierre@0 | 884 | 
| pierre@0 | 885     case 'load': | 
| pierre@0 | 886       $ad = db_fetch_array(db_query('SELECT * FROM {ads} WHERE aid = %d', $node->nid)); | 
| pierre@0 | 887       $merge = array_merge((array)$node, (array)$ad); | 
| pierre@0 | 888       $adtype = module_invoke('ad_'. $ad['adtype'], 'adapi', 'load', $merge); | 
| pierre@0 | 889       if (is_array($adtype)) { | 
| pierre@0 | 890         return array_merge($ad, $adtype); | 
| pierre@0 | 891       } | 
| pierre@0 | 892       else { | 
| pierre@0 | 893         return $ad; | 
| pierre@0 | 894       } | 
| pierre@0 | 895       break; | 
| pierre@0 | 896 | 
| pierre@0 | 897     case 'insert': | 
| pierre@0 | 898       if (isset($node->adtype)) { | 
| pierre@0 | 899         if ($node->status != 1 && $node->adstatus == 'active') { | 
| pierre@1 | 900           $node->adstatus = 'expired'; | 
| pierre@0 | 901         } | 
| pierre@0 | 902         $activated = $node->adstatus == 'active' ? time() : 0; | 
| pierre@1 | 903         if (!isset($node->autoactivate)) { | 
| pierre@0 | 904           $node->autoactivate = 0; | 
| pierre@0 | 905         } | 
| pierre@0 | 906         if (!isset($node->maxviews)) { | 
| pierre@0 | 907           $node->maxviews = 0; | 
| pierre@0 | 908         } | 
| pierre@0 | 909         if (!isset($node->maxclicks)) { | 
| pierre@0 | 910           $node->maxclicks = 0; | 
| pierre@0 | 911         } | 
| pierre@0 | 912         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); | 
| pierre@0 | 913         ad_statistics_increment($node->nid, 'create'); | 
| pierre@0 | 914       } | 
| pierre@0 | 915       break; | 
| pierre@0 | 916 | 
| pierre@0 | 917     case 'update': | 
| pierre@0 | 918       if (isset($node->adtype)) { | 
| pierre@0 | 919         $ad = db_fetch_object(db_query('SELECT * FROM {ads} WHERE aid = %d', $node->nid)); | 
| pierre@0 | 920         // Ad must be in approved state to be able to autoactivate it. | 
| pierre@1 | 921         if ($node->adstatus != 'approved' && isset($node->autoactive) && $node->autoactivate) { | 
| pierre@0 | 922           if ($node->adstatus == 'active') { | 
| pierre@0 | 923             // This ad is already active, no need to autoactivate it. | 
| pierre@0 | 924             $node->autoactivate = 0; | 
| pierre@0 | 925           } | 
| pierre@0 | 926           else { | 
| pierre@0 | 927             drupal_set_message(t('This ad will not be automatically activated at the scheduled time because it is not in the <em>approved</em> state.'), 'error'); | 
| pierre@0 | 928           } | 
| pierre@0 | 929         } | 
| pierre@0 | 930         // If this node has been upublished, the ad should no longer be active. | 
| pierre@0 | 931         if ($node->status != 1 && $node->adstatus == 'active') { | 
| pierre@1 | 932           $node->adstatus = 'expired'; | 
| pierre@0 | 933         } | 
| pierre@0 | 934         // Check if ad is being manually activated. | 
| pierre@0 | 935         if ($ad->adstatus != 'active' && $node->adstatus == 'active') { | 
| pierre@0 | 936           $activated = time(); | 
| pierre@0 | 937         } | 
| pierre@0 | 938         // Check if ad is being manually expired. | 
| pierre@0 | 939         else if ($ad->adstatus != 'expired' && $node->adstatus == 'expired') { | 
| pierre@0 | 940           // Ad has been manually expired. | 
| pierre@1 | 941           $activated = $ad->activated; | 
| pierre@0 | 942           $expired = time(); | 
| pierre@0 | 943         } | 
| pierre@0 | 944         // Ad has not been manually activated or expired, preserve timestamps. | 
| pierre@0 | 945         else { | 
| pierre@0 | 946           $activated = $ad->activated; | 
| pierre@0 | 947           $expired = $ad->expired; | 
| pierre@0 | 948         } | 
| pierre@0 | 949         // Ad status has changed, record the event. | 
| pierre@0 | 950         if ($ad->adstatus != $node->adstatus) { | 
| pierre@0 | 951           ad_statistics_increment($node->nid, $node->adstatus); | 
| pierre@0 | 952         } | 
| pierre@0 | 953         // Update ads table with new information. | 
| pierre@1 | 954         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); | 
| pierre@0 | 955         ad_statistics_increment($node->nid, 'update'); | 
| pierre@0 | 956       } | 
| pierre@0 | 957       break; | 
| pierre@0 | 958 | 
| pierre@0 | 959     case 'delete': | 
| pierre@0 | 960       db_query("DELETE FROM {ads} WHERE aid = %d", $node->nid); | 
| pierre@0 | 961       db_query("DELETE FROM {ad_statistics} WHERE aid = %d", $node->nid); | 
| pierre@0 | 962       // All that's left of the ad is a single timestamp as to when it was | 
| pierre@0 | 963       // deleted. | 
| pierre@0 | 964       ad_statistics_increment($node->nid, 'delete'); | 
| pierre@0 | 965       break; | 
| pierre@0 | 966 | 
| pierre@0 | 967     case 'view': | 
| pierre@0 | 968       if (isset($node->adtype)) { | 
| sly@3 | 969         if (variable_get('ad_meta_noindex', 1)) { | 
| sly@3 | 970           ad_noindex_meta(); | 
| sly@3 | 971         } | 
| pierre@0 | 972         $node = node_prepare($node, $teaser); | 
| pierre@0 | 973         $node->content['body'] = array( | 
| pierre@0 | 974           '#value' => $teaser ? $node->teaser : theme('node_ad', $node, $page), | 
| pierre@0 | 975           '#weight' => 1, | 
| pierre@0 | 976         ); | 
| pierre@0 | 977       } | 
| pierre@0 | 978       break; | 
| pierre@0 | 979   } | 
| pierre@0 | 980   // Allow ad type module to act on nodeapi events.  The adapi hook provides | 
| pierre@0 | 981   // access to additional variables not available in the nodeapi hook. | 
| pierre@0 | 982   if (isset($node->adtype)) { | 
| pierre@0 | 983     // Don't use module_invoke, as in pre-PHP5 the changes to $node won't be | 
| pierre@0 | 984     // passed back. | 
| pierre@0 | 985     $function = "ad_$node->adtype" .'_adapi'; | 
| pierre@0 | 986     if (function_exists($function)) { | 
| pierre@0 | 987       $function($op, $node); | 
| pierre@0 | 988     } | 
| pierre@0 | 989   } | 
| pierre@0 | 990   // Allow ad cache module to act on nodeapi events. | 
| pierre@0 | 991   $cache = variable_get('ad_cache', 'none'); | 
| pierre@0 | 992   if ($cache != 'none') { | 
| pierre@0 | 993     $function = "ad_cache_$cache" .'_adcacheapi'; | 
| pierre@0 | 994     if (function_exists($function)) { | 
| pierre@0 | 995       $function($op, $node); | 
| pierre@0 | 996     } | 
| pierre@0 | 997   } | 
| pierre@1 | 998 | 
| pierre@1 | 999   // Rebuild the cache after all hooks are invoked. | 
| pierre@1 | 1000   switch ($op) { | 
| pierre@1 | 1001     case 'insert': | 
| pierre@1 | 1002     case 'update': | 
| pierre@1 | 1003     case 'delete': | 
| pierre@1 | 1004       if (variable_get('ad_cache_file_rebuild_realtime', 0) && | 
| pierre@1 | 1005           isset($node->adtype)) { | 
| pierre@1 | 1006         ad_rebuild_cache(); | 
| pierre@1 | 1007       } | 
| pierre@1 | 1008   } | 
| pierre@0 | 1009 } | 
| pierre@0 | 1010 | 
| sly@3 | 1011 /** | 
| sly@3 | 1012  * Add the noindex meta tag. | 
| sly@3 | 1013  */ | 
| sly@3 | 1014 function ad_noindex_meta() { | 
| sly@3 | 1015   static $added = FALSE; | 
| sly@3 | 1016   if (!$added) { | 
| sly@3 | 1017     drupal_set_html_head('<meta name="robots" content="noindex" />'); | 
| sly@3 | 1018     $added = TRUE; | 
| sly@3 | 1019   } | 
| sly@3 | 1020 } | 
| sly@3 | 1021 | 
| pierre@0 | 1022 function ad_adapi($op, $node = NULL) { | 
| pierre@0 | 1023   switch ($op) { | 
| pierre@0 | 1024     case 'permissions': | 
| pierre@1 | 1025       return array( | 
| pierre@1 | 1026         'access statistics' => TRUE, | 
| pierre@1 | 1027         'access click history' => TRUE, | 
| pierre@1 | 1028         'set status as pending' => FALSE, | 
| pierre@1 | 1029         'set status as denied' => FALSE, | 
| pierre@1 | 1030         'set status from pending to approved' => FALSE, | 
| pierre@1 | 1031         'set status from pending to denied' => FALSE, | 
| pierre@1 | 1032         'set status from approved to active' => TRUE, | 
| pierre@1 | 1033         'set status from approved to offline' => TRUE, | 
| pierre@1 | 1034         'set status from active to offline' => TRUE, | 
| pierre@1 | 1035         'set status from active to expired' => FALSE, | 
| pierre@1 | 1036         'set status from offline to active' => TRUE, | 
| pierre@1 | 1037         'set status from offline to expired' => FALSE, | 
| pierre@1 | 1038       ); | 
| pierre@0 | 1039       break; | 
| pierre@0 | 1040   } | 
| pierre@0 | 1041 } | 
| pierre@0 | 1042 | 
| pierre@0 | 1043 /** | 
| pierre@0 | 1044  * Implementation of hook_menu(). | 
| pierre@0 | 1045  */ | 
| pierre@0 | 1046 function ad_menu() { | 
| pierre@0 | 1047   $items = array(); | 
| pierre@0 | 1048 | 
| pierre@0 | 1049   $items['admin/content/ad'] = array( | 
| pierre@0 | 1050     'title' => 'Ads', | 
| pierre@0 | 1051     'page callback' => 'ad_admin_list', | 
| pierre@0 | 1052     'access arguments' => array('administer advertisements'), | 
| pierre@0 | 1053     'description' => 'Configure and manage your advertising system.', | 
| pierre@0 | 1054     'file' => 'ad.admin.inc', | 
| pierre@0 | 1055   ); | 
| pierre@0 | 1056   $items['admin/content/ad/list'] = array( | 
| pierre@0 | 1057     'title' => 'List', | 
| pierre@0 | 1058     'page callback' => 'ad_admin_list', | 
| pierre@0 | 1059     'access arguments' => array('administer advertisements'), | 
| pierre@0 | 1060     'type' => MENU_DEFAULT_LOCAL_TASK, | 
| pierre@0 | 1061     'file' => 'ad.admin.inc', | 
| pierre@0 | 1062   ); | 
| pierre@0 | 1063   $items['admin/content/ad/configure'] = array( | 
| pierre@0 | 1064     'title' => 'Settings', | 
| pierre@0 | 1065     'page callback' => 'drupal_get_form', | 
| pierre@0 | 1066     'page arguments' => array('ad_admin_configure_settings'), | 
| pierre@0 | 1067     'access arguments' => array('administer advertisements'), | 
| pierre@0 | 1068     'type' => MENU_LOCAL_TASK, | 
| pierre@0 | 1069     'weight' => 3, | 
| pierre@0 | 1070     'file' => 'ad.admin.inc', | 
| pierre@0 | 1071   ); | 
| pierre@1 | 1072   $items['node/add/ad/ahah'] = array( | 
| pierre@1 | 1073     'access arguments' => array('create advertisements'), | 
| pierre@1 | 1074     'page callback' => 'ad_form_ahah', | 
| pierre@1 | 1075     'type' => MENU_CALLBACK, | 
| pierre@1 | 1076   ); | 
| pierre@0 | 1077 | 
| pierre@0 | 1078   ad_menu_add_global_settings($items); | 
| pierre@0 | 1079 | 
| pierre@0 | 1080   $items['admin/content/ad/groups'] = array( | 
| pierre@0 | 1081     'title' => 'Ad groups', | 
| pierre@0 | 1082     'page callback' => 'ad_admin_groups_list', | 
| pierre@0 | 1083     'access arguments' => array('administer advertisements'), | 
| pierre@0 | 1084     'type' => MENU_LOCAL_TASK, | 
| pierre@0 | 1085     'weight' => 5, | 
| pierre@0 | 1086     'file' => 'ad.admin.inc', | 
| pierre@0 | 1087   ); | 
| pierre@0 | 1088   $items['admin/content/ad/groups/list'] = array( | 
| pierre@0 | 1089     'title' => 'List', | 
| pierre@0 | 1090     'page callback' => 'ad_admin_groups_list', | 
| pierre@0 | 1091     'access arguments' => array('administer advertisements'), | 
| pierre@0 | 1092     'type' => MENU_DEFAULT_LOCAL_TASK, | 
| pierre@0 | 1093     'weight' => 0, | 
| pierre@0 | 1094     'file' => 'ad.admin.inc', | 
| pierre@0 | 1095   ); | 
| pierre@0 | 1096   $items['admin/content/ad/groups/add'] = array( | 
| pierre@0 | 1097     'title' => 'Create group', | 
| pierre@0 | 1098     'page callback' => 'drupal_get_form', | 
| pierre@0 | 1099     'page arguments' => array('ad_admin_group_form'), | 
| pierre@0 | 1100     'access arguments' => array('administer advertisements'), | 
| pierre@0 | 1101     'type' => MENU_LOCAL_TASK, | 
| pierre@0 | 1102     'weight' => 3, | 
| pierre@0 | 1103     'file' => 'ad.admin.inc', | 
| pierre@0 | 1104   ); | 
| pierre@0 | 1105   $items["admin/content/ad/groups/%ad_group/edit"] = array( | 
| pierre@0 | 1106     'title' => 'Edit group', | 
| pierre@0 | 1107     'page callback' => 'drupal_get_form', | 
| pierre@0 | 1108     'page arguments' => array('ad_admin_group_form', 4), | 
| pierre@0 | 1109     'access arguments' => array('administer advertisements'), | 
| pierre@0 | 1110     'weight' => 1, | 
| pierre@0 | 1111     'file' => 'ad.admin.inc', | 
| pierre@0 | 1112   ); | 
| pierre@0 | 1113   $items["admin/content/ad/groups/%ad_group/delete"] = array( | 
| pierre@0 | 1114     'title' => 'Delete group', | 
| pierre@0 | 1115     'page callback' => 'drupal_get_form', | 
| pierre@0 | 1116     'page arguments' => array('ad_confirm_group_delete', 4), | 
| pierre@0 | 1117     'access arguments' => array('administer advertisements'), | 
| pierre@0 | 1118     'weight' => 2, | 
| pierre@0 | 1119     'file' => 'ad.admin.inc', | 
| pierre@0 | 1120   ); | 
| pierre@0 | 1121   $items['admin/content/ad/configure/global'] = array( | 
| pierre@0 | 1122     'title' => 'Global settings', | 
| pierre@0 | 1123     'page callback' => 'drupal_get_form', | 
| pierre@0 | 1124     'page arguments' => array('ad_admin_configure_settings'), | 
| pierre@0 | 1125     'access arguments' => array('administer advertisements'), | 
| pierre@0 | 1126     'type' => MENU_DEFAULT_LOCAL_TASK, | 
| pierre@0 | 1127     'weight' => 0, | 
| pierre@0 | 1128     'file' => 'ad.admin.inc', | 
| pierre@0 | 1129   ); | 
| pierre@0 | 1130   $items["node/%node/details/%"] = array( | 
| pierre@0 | 1131     'title' => 'Click details', | 
| pierre@0 | 1132     'page callback' => 'ad_click_details', | 
| pierre@0 | 1133     'page arguments' => array(1, 3), | 
| pierre@0 | 1134     'access arguments' => array(1, 'access click history'), | 
| pierre@1 | 1135     'access callback' => 'ad_permission', | 
| pierre@0 | 1136     'type' => MENU_CALLBACK, | 
| pierre@0 | 1137     'file' => 'ad.pages.inc', | 
| pierre@0 | 1138   ); | 
| pierre@1 | 1139   $items["ad/redirect/%"] = array( | 
| pierre@0 | 1140     'access arguments' => array('show advertisements'), | 
| pierre@0 | 1141     'type' => MENU_CALLBACK, | 
| pierre@0 | 1142     'page callback' => 'ad_redirect', | 
| pierre@1 | 1143     'page arguments' => (array(2)), | 
| pierre@0 | 1144   ); | 
| pierre@0 | 1145 | 
| pierre@0 | 1146   return $items; | 
| pierre@0 | 1147 } | 
| pierre@0 | 1148 | 
| pierre@0 | 1149 /** | 
| pierre@0 | 1150  * Load settings for all ad modules. Those modules, who don't | 
| pierre@0 | 1151  * have their settings form, will get a standard one. | 
| pierre@0 | 1152  */ | 
| pierre@0 | 1153 function ad_menu_add_global_settings(&$menu_items) { | 
| pierre@0 | 1154   $adtypes = ad_get_types(); | 
| pierre@0 | 1155   foreach ($adtypes as $type => $name) { | 
| pierre@0 | 1156     // Ad type global settings. | 
| pierre@0 | 1157     $settings = 'ad_'. $type .'_global_settings'; | 
| pierre@1 | 1158     $file = 'ad_image.module'; | 
| pierre@0 | 1159     if (!function_exists($settings)) { | 
| pierre@0 | 1160       $settings = 'ad_no_global_settings'; | 
| pierre@1 | 1161       $file = 'ad.admin.inc'; | 
| pierre@0 | 1162     } | 
| pierre@0 | 1163     $menu_items['admin/content/ad/configure/'. $type] = array( | 
| pierre@0 | 1164       'title' => $name, | 
| pierre@0 | 1165       'page callback' => 'drupal_get_form', | 
| pierre@0 | 1166       'page arguments' => array($settings), | 
| pierre@0 | 1167       'access arguments' => array('administer advertisements'), | 
| pierre@0 | 1168       'type' => MENU_LOCAL_TASK, | 
| pierre@0 | 1169       'weight' => 2, | 
| pierre@0 | 1170       'file' => 'ad.admin.inc', | 
| pierre@0 | 1171     ); | 
| pierre@0 | 1172   } | 
| pierre@0 | 1173 } | 
| pierre@0 | 1174 | 
| pierre@0 | 1175 /** | 
| pierre@0 | 1176  * Drupal menu wildcard Ad group loader | 
| pierre@0 | 1177  */ | 
| pierre@0 | 1178 function ad_group_load($tid) { | 
| pierre@0 | 1179   if (!is_numeric($tid)) { | 
| pierre@0 | 1180     return FALSE; | 
| pierre@0 | 1181   } | 
| pierre@0 | 1182   $group = ad_groups_list(TRUE, $tid); | 
| pierre@0 | 1183   if (!isset($group)) { | 
| pierre@0 | 1184     return FALSE; | 
| pierre@0 | 1185   } | 
| pierre@0 | 1186   return $group; | 
| pierre@0 | 1187 } | 
| pierre@0 | 1188 | 
| pierre@0 | 1189 /** | 
| pierre@0 | 1190  * Implementation of hook_block(). | 
| pierre@0 | 1191  */ | 
| pierre@0 | 1192 function ad_block($op = 'list', $delta = 0, $edit = array()) { | 
| pierre@0 | 1193   switch ($op) { | 
| pierre@0 | 1194     case 'list': | 
| pierre@0 | 1195       $blocks = array(); | 
| pierre@0 | 1196       $groups = ad_groups_list(); | 
| pierre@0 | 1197       foreach ($groups as $tid => $name) { | 
| pierre@0 | 1198         $blocks[$tid]['info'] = t('ad group: @name', array('@name' => $name)); | 
| pierre@0 | 1199       } | 
| pierre@0 | 1200       return $blocks; | 
| pierre@0 | 1201     case 'configure': | 
| pierre@0 | 1202       $form['ad_block_quantity_'. $delta] = array( | 
| pierre@0 | 1203         '#type' => 'select', | 
| pierre@0 | 1204         '#title' => t('Number of ads'), | 
| pierre@0 | 1205         '#default_value' => variable_get('ad_block_quantity_'. $delta, 1), | 
| pierre@0 | 1206         '#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)), | 
| pierre@0 | 1207         '#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.'), | 
| pierre@0 | 1208       ); | 
| pierre@0 | 1209       return $form; | 
| pierre@0 | 1210     case 'save': | 
| pierre@0 | 1211       variable_set('ad_block_quantity_'. $delta, $edit['ad_block_quantity_'. $delta]); | 
| pierre@0 | 1212       break; | 
| pierre@0 | 1213     case 'view': | 
| pierre@0 | 1214       $block['content'] = ad($delta, variable_get('ad_block_quantity_'. $delta, 1)); | 
| pierre@0 | 1215       return $block; | 
| pierre@0 | 1216   } | 
| pierre@0 | 1217 } | 
| pierre@0 | 1218 | 
| pierre@0 | 1219 /** | 
| pierre@0 | 1220  * Determine whether the user has a given privilege. | 
| pierre@0 | 1221  * | 
| pierre@1 | 1222  * @param $aid | 
| pierre@1 | 1223  *   ID of advertisement. | 
| pierre@0 | 1224  * @param $permission | 
| pierre@1 | 1225  *   Permission string which should be checked (such as 'access click history') | 
| pierre@0 | 1226  * @param $account | 
| pierre@0 | 1227  *   User object, which are accessing the ad or current user by default. | 
| pierre@0 | 1228  */ | 
| pierre@1 | 1229 function ad_permission($aid, $string, $account = NULL) { | 
| pierre@0 | 1230   global $user; | 
| pierre@1 | 1231   $access = FALSE; | 
| pierre@0 | 1232 | 
| pierre@1 | 1233   // by default, check permission for current user | 
| pierre@0 | 1234   if (!isset($account)) { | 
| pierre@0 | 1235     $account = $user; | 
| pierre@0 | 1236   } | 
| pierre@0 | 1237 | 
| pierre@1 | 1238   // user #1 has all privileges | 
| pierre@0 | 1239   if ($account->uid == 1) { | 
| pierre@0 | 1240     return TRUE; | 
| pierre@0 | 1241   } | 
| pierre@0 | 1242 | 
| pierre@1 | 1243   // if you have administer permissions, you have all permissions | 
| pierre@0 | 1244   if (user_access('administer advertisements', $account)) { | 
| pierre@0 | 1245     return TRUE; | 
| pierre@0 | 1246   } | 
| pierre@0 | 1247 | 
| pierre@1 | 1248   // when used in the Drupal menu, $aid may be the full ad object. | 
| pierre@1 | 1249   if (is_object($aid) && isset($aid->aid)) { | 
| pierre@1 | 1250     $aid = $aid->aid; | 
| pierre@1 | 1251   } | 
| sly@3 | 1252   else if (is_object($aid) && isset($aid->nid)) { | 
| sly@3 | 1253     $aid = $aid->nid; | 
| sly@3 | 1254   } | 
| pierre@1 | 1255   else if (is_object($aid)) { | 
| pierre@1 | 1256     watchdog('ad', 'Invalid aid object passed into ad_permission, no aid->aid set.'); | 
| pierre@1 | 1257     $aid = 0; | 
| pierre@0 | 1258   } | 
| pierre@0 | 1259 | 
| pierre@1 | 1260   // invoke ad_owners module to determine user's access | 
| pierre@1 | 1261   if (module_exists('ad_owners') && | 
| pierre@1 | 1262       function_exists('ad_owners_permission')) { | 
| pierre@1 | 1263     $access = ad_owners_permission($aid, $string, $account); | 
| pierre@1 | 1264   } | 
| pierre@1 | 1265   // no ad_owners module, allow acces to statistics and click history | 
| pierre@1 | 1266   else if (in_array($string, array('access statistics', 'access click history'))) { | 
| pierre@1 | 1267     $access = TRUE; | 
| pierre@1 | 1268   } | 
| pierre@1 | 1269   // with no ad_owners module, all other permissions are denied unless user | 
| pierre@1 | 1270   // has 'administer advertisements' permission | 
| pierre@1 | 1271   return $access; | 
| pierre@0 | 1272 } | 
| pierre@0 | 1273 | 
| pierre@0 | 1274 /** | 
| pierre@0 | 1275  * Returns ad types data. | 
| pierre@0 | 1276  * | 
| pierre@0 | 1277  * @param $op | 
| pierre@0 | 1278  *  If set to 'name', will only return array of type names ($type => $name). | 
| pierre@0 | 1279  *  If set to 'data', will return all of the type's data | 
| pierre@0 | 1280  * @param $type | 
| pierre@0 | 1281  *  If not specified, will return array of all available types, else will | 
| pierre@0 | 1282  *  return specific type's name or data. | 
| pierre@0 | 1283  */ | 
| pierre@0 | 1284 function ad_get_types($op = 'name', $type = NULL) { | 
| pierre@0 | 1285   $adtypes = module_invoke_all('adapi', 'type', array()); | 
| pierre@0 | 1286   switch ($op) { | 
| pierre@0 | 1287     case 'name': | 
| pierre@0 | 1288       if (isset($type)) { | 
| pierre@0 | 1289         return $adtypes[$type]['name']; | 
| pierre@0 | 1290       } | 
| pierre@0 | 1291       else { | 
| pierre@0 | 1292         foreach ($adtypes as $type => $data) { | 
| pierre@0 | 1293           $adtypes[$type] = $data['name']; | 
| pierre@0 | 1294         } | 
| pierre@0 | 1295         return $adtypes; | 
| pierre@0 | 1296       } | 
| pierre@0 | 1297     case 'data': | 
| pierre@0 | 1298       if (isset($type)) { | 
| pierre@0 | 1299         return $adtypes[$type]; | 
| pierre@0 | 1300       } | 
| pierre@0 | 1301       else { | 
| pierre@0 | 1302         return $adtypes; | 
| pierre@0 | 1303       } | 
| pierre@0 | 1304   } | 
| pierre@0 | 1305 } | 
| pierre@0 | 1306 | 
| pierre@0 | 1307 /** | 
| pierre@0 | 1308  * Return an array of all groups, or a specific group. | 
| pierre@0 | 1309  * | 
| pierre@0 | 1310  * @param $object | 
| pierre@0 | 1311  *  If FALSE, will return only name of group(s).  If TRUE, will return full | 
| pierre@0 | 1312  *  group object including ->name, ->description, and ->tid. | 
| pierre@0 | 1313  * @param $tid | 
| pierre@0 | 1314  *  If set to an integer >0, will only return group info about that specific | 
| pierre@0 | 1315  *  group. | 
| pierre@0 | 1316  */ | 
| pierre@0 | 1317 function ad_groups_list($object = FALSE, $tid = NULL) { | 
| pierre@0 | 1318   static $groups = array(); | 
| pierre@0 | 1319   static $names = array(); | 
| pierre@0 | 1320 | 
| pierre@0 | 1321   // Return the full group object(s). | 
| pierre@0 | 1322   if ($object) { | 
| pierre@0 | 1323     if (empty($groups)) { | 
| pierre@0 | 1324       $tids = taxonomy_get_tree(_ad_get_vid()); | 
| pierre@0 | 1325       if (is_array($tids)) { | 
| pierre@0 | 1326         foreach ($tids as $group) { | 
| pierre@0 | 1327           $groups[$group->tid]->name = $group->name; | 
| pierre@0 | 1328           $groups[$group->tid]->description = $group->description; | 
| pierre@0 | 1329           $groups[$group->tid]->tid = $group->tid; | 
| pierre@0 | 1330           $groups[$group->tid]->weight = $group->weight; | 
| pierre@0 | 1331         } | 
| pierre@0 | 1332       } | 
| pierre@0 | 1333       // Hard coded "default" group with tid of 0. | 
| pierre@0 | 1334       $groups[0]->name = t('default'); | 
| pierre@0 | 1335       $groups[0]->description = t('The default ad group is comprised of all ads not assigned to any other ad group.'); | 
| pierre@0 | 1336       $groups[0]->tid = 0; | 
| pierre@0 | 1337       $groups[0]->weight = 0; | 
| pierre@0 | 1338     } | 
| pierre@0 | 1339     // Return a specific group object. | 
| pierre@0 | 1340     if ((int)$tid) { | 
| pierre@0 | 1341       return $groups[$tid]; | 
| pierre@0 | 1342     } | 
| pierre@0 | 1343     // Return an array of all group objects. | 
| pierre@0 | 1344     else { | 
| pierre@0 | 1345       return $groups; | 
| pierre@0 | 1346     } | 
| pierre@0 | 1347   } | 
| pierre@0 | 1348   // Return only the group name(s). | 
| pierre@0 | 1349   else { | 
| pierre@0 | 1350     if (empty($names)) { | 
| pierre@0 | 1351       $tids = taxonomy_get_tree(_ad_get_vid()); | 
| pierre@0 | 1352       if (is_array($tids)) { | 
| pierre@0 | 1353         foreach ($tids as $group) { | 
| pierre@0 | 1354           $names[$group->tid] = $group->name; | 
| pierre@0 | 1355         } | 
| pierre@0 | 1356       } | 
| pierre@0 | 1357       // Hard coded "default" group with tid of 0. | 
| pierre@0 | 1358       $names[0] = t('default'); | 
| pierre@0 | 1359     } | 
| pierre@0 | 1360     // Return a specific group name. | 
| pierre@0 | 1361     if ((int)$tid) { | 
| pierre@0 | 1362       return $names[$tid]; | 
| pierre@0 | 1363     } | 
| pierre@0 | 1364     // Return an array of all group names. | 
| pierre@0 | 1365     else { | 
| pierre@0 | 1366       return $names; | 
| pierre@0 | 1367     } | 
| pierre@0 | 1368   } | 
| pierre@0 | 1369 } | 
| pierre@0 | 1370 | 
| pierre@0 | 1371 /** | 
| pierre@0 | 1372  * Implement ad notify api _hook. | 
| pierre@0 | 1373  */ | 
| pierre@0 | 1374 function ad_adnotifyapi($op, $arg1 = NULL, $arg2 = NULL) { | 
| pierre@0 | 1375   switch ($op) { | 
| pierre@0 | 1376     // Make the following events available for notification. | 
| pierre@0 | 1377     case 'register': | 
| pierre@0 | 1378       return array( | 
| pierre@0 | 1379         '-expired' => t('Email @when before the advertisement will expire.'), | 
| pierre@0 | 1380         'expired' => t('Email @when after the advertisement is expired.'), | 
| pierre@0 | 1381         '-active' => t('Email @when before the advertisement will be activated (if scheduled).'), | 
| pierre@0 | 1382         'active' => t('Email @when after the advertisement is activated.'), | 
| sly@2 | 1383         'offline' => t('Email @when after the advertisement is taken offline.'), | 
| pierre@0 | 1384         'click' => t('Email @when after the advertisement is clicked.'), | 
| pierre@0 | 1385         'approved' => t('Email @when after the advertisement is approved.'), | 
| pierre@0 | 1386         'denied' => t('Email @when after the advertisement is denied.'), | 
| sly@2 | 1387         'update' => t('Email @when after the advertisement is updated.'), | 
| pierre@0 | 1388       ); | 
| pierre@0 | 1389       break; | 
| pierre@0 | 1390     case '-expired': | 
| pierre@0 | 1391       $node = node_load($arg1->aid); | 
| pierre@0 | 1392       if (isset($node->autoexpire) && $node->autoexpire) { | 
| pierre@0 | 1393         if ((time() + $arg1->delay >= $node->autoexpire) && | 
| pierre@0 | 1394             ($arg1->sent + $arg1->delay < $node->autoexpire)) { | 
| pierre@0 | 1395           return array('-expired' => 1); | 
| pierre@0 | 1396         } | 
| pierre@0 | 1397       } | 
| pierre@0 | 1398       break; | 
| pierre@0 | 1399     case '-active': | 
| pierre@0 | 1400       $node = node_load($arg1->aid); | 
| pierre@0 | 1401       if (isset($node->autoactivate) && $node->autoactivate) { | 
| pierre@0 | 1402         if ((time() + $arg1->delay >= $node->autoactivate) && | 
| pierre@0 | 1403             ($arg1->sent + $arg1->delay < $node->autoactivate)) { | 
| pierre@0 | 1404           return array('-active' => 1); | 
| pierre@0 | 1405         } | 
| pierre@0 | 1406       } | 
| pierre@0 | 1407       break; | 
| pierre@0 | 1408     case 'mail_text': | 
| pierre@0 | 1409       switch ($arg1) { | 
| pierre@0 | 1410         case 'expired': | 
| pierre@0 | 1411           return array( | 
| pierre@1 | 1412             'subject' => t('[%site-name ad] %event notification'), | 
| pierre@1 | 1413             '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"), | 
| pierre@0 | 1414           ); | 
| pierre@0 | 1415         case '-expired': | 
| pierre@0 | 1416           return array( | 
| pierre@1 | 1417             'subject' => t('[%site-name ad] expiration notification'), | 
| pierre@1 | 1418             '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"), | 
| pierre@0 | 1419           ); | 
| pierre@0 | 1420         case 'active': | 
| pierre@0 | 1421           return array( | 
| pierre@1 | 1422             'subject' => t('[%site-name ad] %event notification'), | 
| pierre@1 | 1423             '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"), | 
| pierre@0 | 1424           ); | 
| pierre@0 | 1425         case '-active': | 
| pierre@0 | 1426           return array( | 
| pierre@1 | 1427             'subject' => t('[%site-name ad] activation notification'), | 
| pierre@1 | 1428             '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"), | 
| pierre@0 | 1429           ); | 
| pierre@0 | 1430         case 'click': | 
| pierre@0 | 1431           return array( | 
| pierre@1 | 1432             'subject' => t('[%site-name ad] %event notification'), | 
| pierre@1 | 1433             '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"), | 
| pierre@0 | 1434           ); | 
| pierre@0 | 1435         case 'approved': | 
| pierre@0 | 1436           return array( | 
| pierre@1 | 1437             'subject' => t('[%site-name ad] %event notification'), | 
| pierre@1 | 1438             '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"), | 
| pierre@0 | 1439           ); | 
| pierre@0 | 1440         case 'denied': | 
| pierre@0 | 1441           return array( | 
| pierre@1 | 1442             'subject' => t('[%site-name ad] %event notification'), | 
| pierre@1 | 1443             '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"), | 
| pierre@0 | 1444           ); | 
| pierre@0 | 1445       } | 
| pierre@0 | 1446       break; | 
| pierre@0 | 1447   } | 
| pierre@0 | 1448 } | 
| pierre@0 | 1449 | 
| pierre@0 | 1450 function _ad_check_installation() { | 
| pierre@0 | 1451   // Verify serve.php exists and is readable. | 
| pierre@0 | 1452   $adserve = variable_get('adserve', ''); | 
| pierre@0 | 1453   $adserveinc = variable_get('adserveinc', ''); | 
| pierre@0 | 1454   if (!file_exists($adserve)) { | 
| pierre@0 | 1455     // The serve.php file should be in the same directory as the ad.module. | 
| pierre@0 | 1456     $adserve = drupal_get_path('module', 'ad') .'/serve.php'; | 
| pierre@0 | 1457     variable_set('adserve', $adserve); | 
| pierre@0 | 1458   } | 
| pierre@0 | 1459   if (!is_readable($adserve)) { | 
| pierre@0 | 1460     variable_set('adserve', ''); | 
| pierre@0 | 1461     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'); | 
| pierre@0 | 1462   } | 
| pierre@0 | 1463   if (!file_exists($adserveinc)) { | 
| pierre@0 | 1464     // The adserve.inc file should be in the same directory as the ad.module. | 
| pierre@0 | 1465     $adserveinc = drupal_get_path('module', 'ad') .'/adserve.inc'; | 
| pierre@0 | 1466     variable_set('adserveinc', $adserveinc); | 
| pierre@0 | 1467   } | 
| pierre@0 | 1468   if (!is_readable($adserveinc)) { | 
| pierre@0 | 1469     variable_set('adserveinc', ''); | 
| pierre@0 | 1470     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'); | 
| pierre@0 | 1471   } | 
| pierre@0 | 1472 | 
| pierre@0 | 1473   // Validate vid in vocabulary table. | 
| pierre@0 | 1474   $vid = db_result(db_query("SELECT vid FROM {vocabulary} WHERE module = 'ad'")); | 
| pierre@0 | 1475   if ($vid != variable_get('ad_group_vid', '')) { | 
| pierre@0 | 1476     drupal_set_message(t('Invalid vocabulary defined for advertisements, attempting to auto-fix.'), 'error'); | 
| pierre@0 | 1477     if ($vid) { | 
| pierre@0 | 1478       db_query("DELETE FROM {vocabulary_node_types} WHERE vid = %d OR type = 'ad'", variable_get('ad_group_vid', '')); | 
| pierre@0 | 1479       variable_set('ad_group_vid_restore', variable_get('ad_group_vid', '')); | 
| pierre@0 | 1480     } | 
| pierre@0 | 1481     variable_del('ad_group_vid'); | 
| pierre@0 | 1482   } | 
| pierre@0 | 1483   else { | 
| pierre@0 | 1484     // Validate vid in vocabulary_node_types table. | 
| pierre@0 | 1485     $result = db_query("SELECT vid FROM {vocabulary_node_types} WHERE type = 'ad'"); | 
| pierre@0 | 1486     $found = FALSE; | 
| pierre@0 | 1487     while ($vocab = db_fetch_object($result)) { | 
| pierre@0 | 1488       if ($vocab->vid == variable_get('ad_group_vid', '')) { | 
| pierre@0 | 1489         $found = TRUE; | 
| pierre@0 | 1490       } | 
| pierre@0 | 1491     } | 
| pierre@0 | 1492     if (!$found) { | 
| pierre@0 | 1493       drupal_set_message(t('Missing vocabulary node type for advertisements, attempting to auto-fix.'), 'error'); | 
| pierre@0 | 1494       db_query("DELETE FROM {vocabulary_node_types} WHERE vid = %d OR type = 'ad'", variable_get('ad_group_vid', '')); | 
| pierre@0 | 1495       db_query("DELETE FROM {vocabulary} WHERE vid = %d", variable_get('ad_group_vid', '')); | 
| pierre@0 | 1496       variable_set('ad_group_vid_restore', variable_get('ad_group_vid', '')); | 
| pierre@0 | 1497       variable_del('ad_group_vid'); | 
| pierre@0 | 1498     } | 
| pierre@0 | 1499   } | 
| pierre@0 | 1500 | 
| pierre@0 | 1501   _ad_get_vid(); | 
| pierre@0 | 1502   // Preserve old ad groups, if any. | 
| pierre@0 | 1503   if (($old = variable_get('ad_group_vid_restore', '')) && | 
| pierre@0 | 1504        $vid = variable_get('ad_group_vid', '')) { | 
| pierre@0 | 1505     drupal_set_message(t('Restoring orphaned ad group configuration.')); | 
| pierre@0 | 1506     db_query('UPDATE {term_data} SET vid = %d WHERE vid = %d', $vid, $old); | 
| pierre@0 | 1507     variable_set('ad_group_vid_restore', ''); | 
| pierre@0 | 1508   } | 
| pierre@0 | 1509 | 
| pierre@0 | 1510   $rid = db_result(db_query_range("SELECT rid FROM {permission} WHERE perm LIKE '%%show advertisements%%'", 1)); | 
| pierre@0 | 1511   if (!$rid) { | 
| pierre@0 | 1512     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')))); | 
| pierre@0 | 1513   } | 
| pierre@0 | 1514 | 
| pierre@0 | 1515   // Allow modules to define an action to take each time an ad is served. | 
| pierre@0 | 1516   // When modules define 'adserve_select' or 'adserve_filter', they must set | 
| pierre@0 | 1517   // the 'function' and 'path' parameters.  The 'weight' parameter can | 
| pierre@0 | 1518   // optionally be set. | 
| pierre@0 | 1519   //  function: the function to call when serving an add | 
| pierre@0 | 1520   //  path: the path to the include file where $function is defined | 
| pierre@0 | 1521   // Modules can define actions that happen when advertisements are served. | 
| pierre@0 | 1522   // Currently support actions are: | 
| pierre@0 | 1523   //  - init_text   (display content before displaying ads) // TODO | 
| pierre@0 | 1524   //  - select      (alter which ads are selected to be displayed) // TODO | 
| pierre@0 | 1525   //  - filter      (filter selected ads before they are displayed) // TODO | 
| pierre@0 | 1526   //  - exit_text   (display content after displaying ads) // TODO | 
| pierre@0 | 1527   $hooks = array('init_text', 'select', 'filter', 'exit_text'); | 
| pierre@0 | 1528   foreach ($hooks as $hook) { | 
| pierre@0 | 1529     $adserve_actions = module_invoke_all('adapi', "adserve_$hook", array()); | 
| pierre@0 | 1530     $actions = array(); | 
| pierre@0 | 1531     foreach ($adserve_actions as $name => $action) { | 
| pierre@0 | 1532       if (is_numeric($action['weight'])) { | 
| pierre@0 | 1533         $weight = $action['weight']; | 
| pierre@0 | 1534       } | 
| pierre@0 | 1535       else { | 
| pierre@0 | 1536         // weight is an optional, defaults to 0 | 
| pierre@0 | 1537         $weight = $action['weight'] = 0; | 
| pierre@0 | 1538       } | 
| pierre@0 | 1539       $actions[$weight .'.'. $name] = $action; | 
| pierre@0 | 1540       $actions[$weight .'.'. $name]['name'] = $name; | 
| pierre@0 | 1541     } | 
| pierre@0 | 1542     // order actions by weight (multiple same-weight actions sorted by alpha) | 
| pierre@0 | 1543     ksort($actions); | 
| pierre@0 | 1544     variable_set("adserve_$hook", serialize($actions)); | 
| pierre@0 | 1545   } | 
| pierre@0 | 1546 | 
| pierre@0 | 1547   module_invoke_all('adapi', 'check_install', array()); | 
| pierre@0 | 1548 } | 
| pierre@0 | 1549 | 
| pierre@0 | 1550 /** | 
| pierre@0 | 1551  * Creates a vocabulary for use by ad groups if not already created. | 
| pierre@0 | 1552  */ | 
| pierre@0 | 1553 function _ad_get_vid() { | 
| pierre@0 | 1554   $vid = variable_get('ad_group_vid', ''); | 
| pierre@0 | 1555   if (empty($vid)) { | 
| pierre@0 | 1556     // No vid stored in the variables table, check if one even exists. | 
| pierre@0 | 1557     $vid = db_result(db_query("SELECT vid FROM {vocabulary} WHERE module = '%s'", 'ad')); | 
| pierre@0 | 1558     if (!$vid) { | 
| pierre@0 | 1559       // No vid, so we create one. | 
| pierre@0 | 1560       $edit = array( | 
| pierre@0 | 1561         'name' => t('Ad groups'), | 
| pierre@0 | 1562         'multiple' => 1, | 
| pierre@0 | 1563         'required' => 0, | 
| pierre@0 | 1564         'hierarchy' => 0, | 
| pierre@0 | 1565         'relations' => 0, | 
| pierre@0 | 1566         'module' => 'ad', | 
| pierre@0 | 1567         'nodes' => array('ad' => 1) | 
| pierre@0 | 1568       ); | 
| pierre@0 | 1569 | 
| pierre@0 | 1570       taxonomy_save_vocabulary($edit); | 
| pierre@0 | 1571       $vid = $edit['vid']; | 
| pierre@0 | 1572     } | 
| pierre@0 | 1573     // Save the vid for next time. | 
| pierre@0 | 1574     variable_set('ad_group_vid', $vid); | 
| pierre@0 | 1575   } | 
| pierre@0 | 1576   return $vid; | 
| pierre@0 | 1577 } | 
| pierre@0 | 1578 | 
| pierre@0 | 1579 /** | 
| pierre@0 | 1580  * Builds the necessary HTML to display an image-based impressions counter. | 
| pierre@0 | 1581  */ | 
| sly@2 | 1582 function ad_display_image($aid, $css = TRUE) { | 
| pierre@0 | 1583   global $base_url; | 
| pierre@0 | 1584   $adserve = variable_get('adserve', ''); | 
| pierre@0 | 1585   $cache = variable_get('ad_cache', 'none'); | 
| pierre@0 | 1586   $variables = "?o=image"; | 
| sly@2 | 1587   $variables .= "&a=$aid"; | 
| sly@2 | 1588   if ($cache != 'none') { | 
| sly@2 | 1589     $variables .= '&c='. $cache . module_invoke('ad_cache_'. $cache, 'adcacheapi', 'display_variables', array()); | 
| pierre@0 | 1590   } | 
| sly@2 | 1591   $output = '<img src="'. htmlentities(url($base_url .'/'. $adserve . $variables)) .'" height="0" width="0" alt="view counter" />'; | 
| pierre@0 | 1592   if ($css) { | 
| pierre@0 | 1593     return '<div class="ad-image-counter">'. $output .'</div>'; | 
| pierre@0 | 1594   } | 
| pierre@0 | 1595   else { | 
| pierre@0 | 1596     return $output; | 
| pierre@0 | 1597   } | 
| pierre@0 | 1598 } | 
| pierre@0 | 1599 | 
| pierre@0 | 1600 /** | 
| pierre@0 | 1601  * Retrieve the group name from the nid. | 
| pierre@0 | 1602  */ | 
| pierre@0 | 1603 function _ad_get_group($nid) { | 
| pierre@0 | 1604   static $groups = array(); | 
| pierre@0 | 1605 | 
| pierre@0 | 1606   if (!isset($groups[$nid])) { | 
| pierre@0 | 1607     $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()); | 
| pierre@0 | 1608     while ($term = db_fetch_object($result)) { | 
| pierre@0 | 1609       $terms[] = $term->name; | 
| pierre@0 | 1610     } | 
| pierre@0 | 1611     if (!empty($terms)) { | 
| pierre@0 | 1612       $groups[$nid] = implode(', ', $terms); | 
| pierre@0 | 1613     } | 
| pierre@0 | 1614     else { | 
| pierre@0 | 1615       $groups[$nid] = t('default'); | 
| pierre@0 | 1616     } | 
| pierre@0 | 1617   } | 
| pierre@0 | 1618 | 
| pierre@0 | 1619   return $groups[$nid]; | 
| pierre@0 | 1620 } | 
| pierre@0 | 1621 |