Parent Directory
|
Revision Log
|
Revision Graph
Implement schema for owners, permissions, notifications, and remote
hosts. Move from Alpha to Beta status, meaning going forward an upgrade
path will be provided for schema changes.
- ad.install
o define ad_permissions table
o define ad_owners table
o define ad_notifications table
o define ad_hosts table
- ad.module
o fix ad statistics to display even if none for current hour
o implement statistics for current week
o register unique hostid for each add owner for displaying ads
remotely
o enforce matching ad status and node status
o only display clicks and statistics for ads, not all ad types
o stub in support for ad owners, ad owner permissions and add owner
notifications
o display group name instead of just group id when listing ads
o add regex in search for adserve.php to not match ie .swp files
- adserve.php
o implement cache types in switch statement
o track hostid when viewing ads for displaying on remote sites
- ad_text.module
o use htmlentities() to encode ad text
| 1 | <?php |
| 2 | // $Id: ad.module $ |
| 3 | |
| 4 | /** |
| 5 | * @file |
| 6 | * An advertising system for Drupal powered websites. |
| 7 | * |
| 8 | * Ad Module 0.3.1 |
| 9 | * Copyright (c) 2005-2006. |
| 10 | * Jeremy Andrews <jeremy@kerneltrap.org>. All rights reserved. |
| 11 | */ |
| 12 | |
| 13 | /** |
| 14 | * Use this function to display an ad from a specified group. |
| 15 | */ |
| 16 | function ad($group = 'default') { |
| 17 | global $base_url; |
| 18 | |
| 19 | /** |
| 20 | * This function will be called to display advertisements. It will start |
| 21 | * simple but will rapidly evolve to handle the following list of TODO's. |
| 22 | * |
| 23 | * TODO: support taxonomy, ie only display ad in specified taxonomies |
| 24 | * TODO: support roles, display certain ads only to certain roles |
| 25 | * TODO: support multiple display methods (local and remote) |
| 26 | * TODO: track who is displaying the ad (local versus remote) |
| 27 | */ |
| 28 | |
| 29 | $adserve = variable_get('adserve', ''); |
| 30 | if (file_exists($adserve)) { |
| 31 | if (user_access('show advertisements')) { |
| 32 | // Count how many dirs above the adserve.php dir to the index.php dir. |
| 33 | $up = (sizeof(explode('/', $adserve)) - 1); |
| 34 | |
| 35 | $cache = variable_get('ad_cache', 'database'); |
| 36 | $src = url("$base_url/$adserve?group=$group&up=$up&cache=$cache"); |
| 37 | } |
| 38 | } |
| 39 | else { |
| 40 | drupal_set_message(t('Ads cannot be displayed. The ad module is %misconfigured, failed to locate the required adserve.php file "<em>%adserve</em>".', array('%misconfigured' => l(t('misconfigured'), 'admin/ad/configure'), '%adserve' => $adserve)), 'error'); |
| 41 | } |
| 42 | |
| 43 | /** |
| 44 | * TODO: Support other display methods than our own JavaScript. For example, |
| 45 | * we may want to serve ads using externally provided JavaScripts, or straight |
| 46 | * urls, etc... |
| 47 | */ |
| 48 | $output = "<script type=\"text/javascript\" src=\"$src\"></script>\n"; |
| 49 | |
| 50 | return theme('ad_display', $group, $output); |
| 51 | } |
| 52 | |
| 53 | /** |
| 54 | * Function to display the actual advertisement to the screen. Wrap it in a |
| 55 | * theme function to make it possible to customize in your own theme. |
| 56 | */ |
| 57 | function theme_ad_display($group, $display) { |
| 58 | $output = "<div class=\"advertisement\" id=\"group-$group\">\n"; |
| 59 | $output .= $display; |
| 60 | $output .= "</div>"; |
| 61 | return $output; |
| 62 | } |
| 63 | |
| 64 | /** |
| 65 | * Update click counter then redirect host to ad's target URL. |
| 66 | */ |
| 67 | function ad_redirect($aid, $optional = NULL) { |
| 68 | global $user; |
| 69 | ad_statistics_increment($aid, 'click'); |
| 70 | db_query("INSERT INTO {ad_clicks} (aid, uid, hostname, url, timestamp) VALUES (%d, %d, '%s', '%s', %d)", $aid, $user->uid, $_SERVER['REMOTE_ADDR'], referer_uri(), time()); |
| 71 | |
| 72 | // Determine where we're supposed to redirect the user. |
| 73 | $adtype = db_result(db_query('SELECT adtype FROM {ads} WHERE aid = %d', $aid)); |
| 74 | $node->aid = $aid; |
| 75 | $node->optional = $optional; |
| 76 | $url = module_invoke('ad_'. $adtype, 'adapi', 'redirect', $node); |
| 77 | if (isset($url)) { |
| 78 | header('Location: '. $url); |
| 79 | } |
| 80 | else { |
| 81 | drupal_goto(''); |
| 82 | } |
| 83 | } |
| 84 | |
| 85 | /** |
| 86 | * Increment action counter. |
| 87 | */ |
| 88 | function ad_statistics_increment($aid, $action) { |
| 89 | // Update action statistics. |
| 90 | db_query("UPDATE {ad_statistics} SET count = count + 1 WHERE aid = %d AND action = '%s' AND date = %d", $aid, $action, date('YmdH')); |
| 91 | // If column doesn't already exist, we need to add it. |
| 92 | if (!db_affected_rows()) { |
| 93 | db_query("INSERT INTO {ad_statistics} (aid, date, action, count) VALUES(%d, %d, '%s', 1)", $aid, date('YmdH'), $action); |
| 94 | // If another process already added this row our INSERT will fail, if so we |
| 95 | // still need to increment it so we don't loose an action. |
| 96 | if (!db_affected_rows()) { |
| 97 | db_query("UPDATE {ad_statistics} SET count = count + 1 WHERE aid = %d AND action = '%s' AND date = %d", $aid, $action, date('YmdH')); |
| 98 | } |
| 99 | } |
| 100 | } |
| 101 | |
| 102 | function ad_status_array($admin = TRUE) { |
| 103 | if ($admin) { |
| 104 | // status options for administrators |
| 105 | return array( |
| 106 | t('pending') => t('This advertisement is currently waiting for adminsitrative approval.'), |
| 107 | t('active') => t('This advertisement is actively being displayed.'), |
| 108 | t('offline') => t('This advertisement has been temporarily disabled by its owner and is not currently being displayed.'), |
| 109 | t('unpublished') => t('This advertisement has been unpublished and is not currently being displayed.'), |
| 110 | t('expired') => t('This advertisement has expired or was otherwise disabled by an administrator.'), |
| 111 | t('denied') => t('This advertisement was refused by the site administrator, it will not be displayed.')); |
| 112 | } |
| 113 | else { |
| 114 | // status options for advertisement owners |
| 115 | return array( |
| 116 | t('active') => t('This advertisement is actively being displayed.'), |
| 117 | t('offline') => t('This advertisement has been temporarily disabled and is not currently being displayed.')); |
| 118 | } |
| 119 | } |
| 120 | |
| 121 | /** |
| 122 | * Calculate statistics for the given advertisements. |
| 123 | * TODO: Introduce caching to make this more efficient. |
| 124 | */ |
| 125 | function ad_statistics($aid) { |
| 126 | // Get global statistics. |
| 127 | $statistics['global']['views'] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'view'", $aid)); |
| 128 | $statistics['global']['clicks'] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'click'", $aid)); |
| 129 | |
| 130 | // No sense in making further queries if the ad has no global statistics. |
| 131 | if (!$statistics['global']['views'] && !$statistics['global']['clicks']) { |
| 132 | return $statistics; |
| 133 | } |
| 134 | |
| 135 | // Get statistics for this year and last year. |
| 136 | $this_year = date('Y000000'); |
| 137 | $last_year = date('Y') - 1 .'000000'; |
| 138 | $statistics['last_year']['views'] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'view' AND date >= %d AND date <= %d", $aid, $last_year, $this_year)); |
| 139 | $statistics['last_year']['clicks'] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'click' AND date >= %d AND date <= %d", $aid, $last_year, $this_year)); |
| 140 | $statistics['this_year']['views'] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'view' AND date >= %d", $aid, $this_year)); |
| 141 | $statistics['this_year']['clicks'] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'click' AND date >= %d", $aid, $this_year)); |
| 142 | |
| 143 | // No sense in making further queries if the ad has no statistics this year. |
| 144 | if (!$statistics['this_year']['views'] && !$statistics['this_year']['clicks']) { |
| 145 | return $statistics; |
| 146 | } |
| 147 | |
| 148 | // Get statistics for this month and last month. |
| 149 | $this_month = date('Ym0000'); |
| 150 | $last_month = date('m') - 1; |
| 151 | if ($last_month == 0) { |
| 152 | $last_month = date('Y') - 1 .'120000'; |
| 153 | } |
| 154 | else { |
| 155 | $last_month = date('Y'). $last_month .'0000'; |
| 156 | } |
| 157 | $statistics['last_month']['views'] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'view' AND date >= %d AND date <= %d", $aid, $last_month, $this_month)); |
| 158 | $statistics['last_month']['clicks'] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'click' AND date >= %d AND date <= %d", $aid, $last_month, $this_month)); |
| 159 | $statistics['this_month']['views'] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'view' AND date >= %d", $aid, $this_month)); |
| 160 | $statistics['this_month']['clicks'] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'click' AND date >= %d", $aid, $this_month)); |
| 161 | |
| 162 | // No sense in making further queries if the ad has no statistics this month. |
| 163 | if (!$statistics['this_month']['views'] && !$statistics['this_month']['clicks']) { |
| 164 | return $statistics; |
| 165 | } |
| 166 | |
| 167 | // Get statistics for this week. |
| 168 | $statistics['this_week']['views'] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'view' AND date > %d AND date <= %d", $aid, date('Ymd00', time() - 60*60*24*7), date('YmdH', time()))); |
| 169 | $statistics['this_week']['clicks'] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'click' AND date > %d AND date <= %d", $aid, date('Ymd00', time() - 60*60*24*7), date('YmdH', time()))); |
| 170 | |
| 171 | // No sense in making further queries if the ad has no statistics this week. |
| 172 | if (!$statistics['this_week']['views'] && !$statistics['this_week']['clicks']) { |
| 173 | return $statistics; |
| 174 | } |
| 175 | |
| 176 | // Get statistics for yesterday and today. |
| 177 | $statistics['yesterday']['views'] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'view' AND date >= %d AND date <= %d", $aid, date('Ymd00', time() - 60*60*24), date('Ymd00', time()))); |
| 178 | $statistics['yesterday']['clicks'] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'click' AND date >= %d AND date <= %d", $aid, date('Ymd00', time() - 60*60*24), date('Ymd00', time()))); |
| 179 | $statistics['today']['views'] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'view' AND date >= %d", $aid, date('Ymd00', time()))); |
| 180 | $statistics['today']['clicks'] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'click' AND date >= %d", $aid, date('Ymd00', time()))); |
| 181 | |
| 182 | // No sense in making further queries if the ad has no statistics today. |
| 183 | if (!$statistics['today']['views'] && !$statistics['today']['clicks']) { |
| 184 | return $statistics; |
| 185 | } |
| 186 | |
| 187 | // Get statistics for this hour and the last hour. |
| 188 | $statistics['this_hour']['views'] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'view' AND date = %d", $aid, date('YmdH', time()))); |
| 189 | $statistics['this_hour']['clicks'] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'click' AND date = %d", $aid, date('YmdH', time()))); |
| 190 | $statistics['last_hour']['views'] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'view' AND date = %d", $aid, date('YmdH', time() - (60*60)))); |
| 191 | $statistics['last_hour']['clicks'] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'click' AND date = %d", $aid, date('YmdH', time() - (60*60)))); |
| 192 | |
| 193 | return $statistics; |
| 194 | } |
| 195 | |
| 196 | function theme_ad_statistics_display($aid) { |
| 197 | $statistics = ad_statistics($aid); |
| 198 | $headers = array('', t('Views'), t('Clicks'), t('Click-thru')); |
| 199 | $rows = array(); |
| 200 | |
| 201 | $data = array('this_hour' => t('This hour'), 'last_hour' => t('Last hour'), 'today' => t('Today'), 'yesterday' => t('Yesterday'), 'this_week' => t('Last seven days'), 'last_week' => t('Last week'), 'this_month' => t('This month'), 'last_month' => t('Last month'), 'this_year' => t('This year'), 'last_year' => t('Last year'), 'global' => t('All time')); |
| 202 | |
| 203 | foreach ($data as $key => $value) { |
| 204 | if ($statistics[$key]['views'] || $statistics[$key]['clicks'] || $key == 'global') { |
| 205 | $rows[] = array( |
| 206 | array('data' => $value), |
| 207 | array('data' => (int)$statistics[$key]['views']), |
| 208 | array('data' => (int)$statistics[$key]['clicks']), |
| 209 | array('data' => $statistics[$key]['views'] ? sprintf('%1.2f', ((int)$statistics[$key]['clicks'] / (int)$statistics[$key]['views']) * 100) .'%' : '0.00%'), |
| 210 | ); |
| 211 | } |
| 212 | } |
| 213 | return theme('box', '', theme('table', $headers, $rows)); |
| 214 | } |
| 215 | |
| 216 | /**************** |
| 217 | * Drupal hooks * |
| 218 | ****************/ |
| 219 | |
| 220 | /** |
| 221 | * Drupal _help hook. Provides help and information text about the ad module. |
| 222 | * |
| 223 | * @path Current display path. |
| 224 | * @return Text appropriate for the current $path. |
| 225 | */ |
| 226 | function ad_help($path) { |
| 227 | switch ($path) { |
| 228 | case 'admin/modules#description': |
| 229 | $output = t('An advertising system for Drupal powered websites.'); |
| 230 | break; |
| 231 | case 'admin/help#ad': |
| 232 | $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>'; |
| 233 | break; |
| 234 | case 'node/add#ad': |
| 235 | $output = t('Advertisements can be randomly displayed to visitors of your website. Statistics for how often each advertisement is viewed and clicked are collected.'); |
| 236 | break; |
| 237 | } |
| 238 | return $output; |
| 239 | } |
| 240 | |
| 241 | /** |
| 242 | * Drupal _perm hook. Establishes permissions used by this module. |
| 243 | * |
| 244 | * @return An array of permissions used by this module. |
| 245 | */ |
| 246 | function ad_perm() { |
| 247 | return ( |
| 248 | array('administer advertisements', |
| 249 | 'create advertisements', |
| 250 | 'edit own advertisements', |
| 251 | 'show advertisements') |
| 252 | ); |
| 253 | } |
| 254 | |
| 255 | /** |
| 256 | */ |
| 257 | function ad_node_info() { |
| 258 | return array('ad' => array('name' => t('advertisement'), 'base' => 'ad')); |
| 259 | } |
| 260 | |
| 261 | /** |
| 262 | */ |
| 263 | function ad_access($op, $node) { |
| 264 | global $user; |
| 265 | |
| 266 | if ($op == 'create') { |
| 267 | return user_access('create advertisements'); |
| 268 | } |
| 269 | |
| 270 | if ($op == 'update' || $op == 'delete') { |
| 271 | return (user_access('administer advertisements') || ($node->uid == $user->uid && user_access('edit own advertisements'))); |
| 272 | } |
| 273 | } |
| 274 | |
| 275 | /** |
| 276 | * Drupal _form hook. |
| 277 | */ |
| 278 | function ad_form(&$node) { |
| 279 | $form = array(); |
| 280 | $edit = $_POST['edit']; |
| 281 | |
| 282 | $type = arg(3); |
| 283 | if (function_exists("ad_$type". '_type')) { |
| 284 | $adtype = $type; |
| 285 | } |
| 286 | else { |
| 287 | $adtype = $node->adtype; |
| 288 | } |
| 289 | |
| 290 | $form['aid'] = array( |
| 291 | '#type' => 'value', |
| 292 | '#value' => $node->nid, |
| 293 | ); |
| 294 | |
| 295 | $form['title'] = array( |
| 296 | '#type' => 'textfield', |
| 297 | '#title' => t('Title'), |
| 298 | '#required' => TRUE, |
| 299 | '#default_value' => $node->title, |
| 300 | ); |
| 301 | $form['body'] = array( |
| 302 | '#type' => 'textarea', |
| 303 | '#title' => t('Description'), |
| 304 | '#required' => TRUE, |
| 305 | '#default_value' => $node->body, |
| 306 | '#rows' => 3 |
| 307 | ); |
| 308 | |
| 309 | // determine the current ad type |
| 310 | if (!isset($adtype)) { |
| 311 | $adtypes = module_invoke_all('adapi', 'type'); |
| 312 | switch (sizeof($adtypes)) { |
| 313 | case 0: |
| 314 | drupal_set_message(t('At least one ad type module must be enabled before you can create advertisements. For example, try %enabling the ad_text or ad_image module.', array('%enabling' => l('enabling', 'admin/modules'))), 'error'); |
| 315 | break; |
| 316 | case 1: |
| 317 | $adtype = $adtypes[0]; |
| 318 | break; |
| 319 | default: |
| 320 | $adtype = arg(3) ? arg(3) : $edit['adtype']; |
| 321 | $form['adtype'] = array( |
| 322 | '#type' => 'radios', |
| 323 | '#title' => t('Style of ad'), |
| 324 | '#options' => drupal_map_assoc($adtypes), |
| 325 | '#default_value' => $adtype ? $adtype : $adtypes[0], |
| 326 | '#required' => TRUE, |
| 327 | '#description' => t('Select the type of ad that you wish to create from the above options.') |
| 328 | ); |
| 329 | break; |
| 330 | } |
| 331 | } |
| 332 | |
| 333 | // display type-specific options |
| 334 | if (isset($adtype)) { |
| 335 | $elements = module_invoke('ad_'. $adtype, 'adapi', 'form', $node); |
| 336 | foreach ($elements as $element => $values) { |
| 337 | $form["$element"] = $values; |
| 338 | } |
| 339 | $form['adtype'] = array( |
| 340 | '#type' => 'hidden', |
| 341 | '#value' => $adtype, |
| 342 | ); |
| 343 | } |
| 344 | |
| 345 | // display group selection menu |
| 346 | $form['group'] = array( |
| 347 | '#type' => 'fieldset', |
| 348 | '#title' => t('Group'), |
| 349 | '#collapsible' => TRUE, |
| 350 | ); |
| 351 | $form['group']['gid'] = array( |
| 352 | '#type' => 'radios', |
| 353 | '#default_value' => $node->gid ? $node->gid : 1, |
| 354 | '#options' => ad_groups_list(), |
| 355 | '#description' => t('Assign your advertisement to a group. When you wish to display advertisements, you will choose a group of advertisements to display in one position on your screen.'), |
| 356 | ); |
| 357 | |
| 358 | if (user_access('administer advertisements')) { |
| 359 | // admins can set any status on advertisements |
| 360 | $form['adstatus'] = array( |
| 361 | '#type' => 'fieldset', |
| 362 | '#title' => t('Status'), |
| 363 | '#collapsible' => TRUE |
| 364 | ); |
| 365 | foreach (ad_status_array() as $status => $description) { |
| 366 | $form['adstatus']["ad$status"] = array( |
| 367 | '#type' => 'radio', |
| 368 | '#title' => t("$status"), |
| 369 | '#return_value' => $status, |
| 370 | '#default_value' => $node->adstatus ? $node->adstatus : t('pending'), |
| 371 | '#description' => "$description", |
| 372 | '#parents' => array("adstatus") |
| 373 | ); |
| 374 | } |
| 375 | } |
| 376 | else { |
| 377 | // display status options |
| 378 | $adstatus = ad_status_array(FALSE); |
| 379 | if (isset($node->adstatus) && isset($adstatus["$node->adstatus"])) { |
| 380 | $form['adstatus'] = array( |
| 381 | '#type' => 'fieldset', |
| 382 | '#title' => t('Status'), |
| 383 | '#collapsible' => TRUE |
| 384 | ); |
| 385 | foreach ($adstatus as $status => $description) { |
| 386 | $form['adstatus']["ad$status"] = array( |
| 387 | '#type' => 'radio', |
| 388 | '#title' => t("$status"), |
| 389 | '#return_value' => $status, |
| 390 | '#default_value' => $node->adstatus, |
| 391 | '#description' => "$description", '#parents' => array("adstatus") |
| 392 | ); |
| 393 | } |
| 394 | } |
| 395 | else { |
| 396 | $adstatus = ad_status_array(); |
| 397 | if (!isset($node->adstatus)) { |
| 398 | $node->adstatus = t('pending'); |
| 399 | } |
| 400 | $form['adstatus_display'] = array( |
| 401 | '#type' => 'markup', |
| 402 | '#value' => '<p><b>'. t('Status') .':</b> '. $node->adstatus .'<br />'. $adstatus["$node->adstatus"] |
| 403 | ); |
| 404 | $form['adstatus'] = array( |
| 405 | '#type' => 'value', |
| 406 | '#value' => $node->adstatus |
| 407 | ); |
| 408 | } |
| 409 | } |
| 410 | |
| 411 | // display statistics |
| 412 | $form['statistics'] = array( |
| 413 | '#type' => 'fieldset', |
| 414 | '#title' => t('Statistics'), |
| 415 | '#collapsible' => TRUE, |
| 416 | ); |
| 417 | |
| 418 | $form['statistics']['data'] = array( |
| 419 | '#type' => 'markup', |
| 420 | '#prefix' => '<div>', |
| 421 | '#suffix' => '</div>', |
| 422 | '#value' => theme_ad_statistics_display($node->nid), |
| 423 | ); |
| 424 | |
| 425 | // display scheduling options |
| 426 | $form['schedule'] = array( |
| 427 | '#type' => 'fieldset', |
| 428 | '#title' => t('Scheduling'), |
| 429 | '#collapsible' => TRUE, |
| 430 | '#collapsed' => TRUE, |
| 431 | ); |
| 432 | $form['schedule']['current'] = array( |
| 433 | '#type' => 'markup', |
| 434 | '#prefix' => '<div>', |
| 435 | '#suffix' => '</div>', |
| 436 | '#value' => t('The current date and time is "%date".', array('%date' => format_date(time(), 'custom', 'F j, Y H:i'))) |
| 437 | ); |
| 438 | $form['schedule']['autoactivate'] = array( |
| 439 | '#type' => 'textfield', |
| 440 | '#title' => t('Automatically activate ad'), |
| 441 | '#required' => FALSE, |
| 442 | '#default_value' => $node->autoactivate ? format_date((int)$node->autoactivate, 'custom', 'F j, Y H:i') : '', |
| 443 | '#description' => t('You can specify a date and time for this advertisement to be automatically activated. The advertisement needs to be in an "offline" state before it can be automatically activated. If you prefer to activate the advertisement immediately, leave this field empty.') |
| 444 | ); |
| 445 | |
| 446 | if (user_access('administer advertisements')) { |
| 447 | // admins can expire advertisements |
| 448 | $form['schedule']['autoexpire'] = array( |
| 449 | '#type' => 'textfield', |
| 450 | '#title' => t('Automatically expire ad'), |
| 451 | '#required' => FALSE, |
| 452 | '#default_value' => $node->autoexpire ? format_date((int)$node->autoexpire, 'custom', 'F j, Y H:i') : '', |
| 453 | '#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.') |
| 454 | ); |
| 455 | } |
| 456 | else { |
| 457 | // display expiration time |
| 458 | if (isset($node->autoexpire)) { |
| 459 | $form['schedule']['autoexpire_display'] = array( |
| 460 | '#type' => 'markup', |
| 461 | '#value' => t('This ad will automatically expire in %date.', array('%date' => format_interval($node->autoexpire - time()))) |
| 462 | ); |
| 463 | $form['schedule']['autoexpire'] = array( |
| 464 | '#type' => 'hidden', |
| 465 | '#value' => $node->autoexpire |
| 466 | ); |
| 467 | } |
| 468 | } |
| 469 | |
| 470 | return $form; |
| 471 | } |
| 472 | |
| 473 | /** |
| 474 | * Drupal _nodeapi hook. |
| 475 | */ |
| 476 | function ad_nodeapi(&$node, $op, $teaser, $page) { |
| 477 | global $user; |
| 478 | |
| 479 | switch ($op) { |
| 480 | |
| 481 | case 'load': |
| 482 | $ad = db_fetch_array(db_query('SELECT * FROM {ads} WHERE aid = %d', $node->nid)); |
| 483 | $adtype = module_invoke('ad_'. $ad['adtype'], 'adapi', 'load', $ad); |
| 484 | if (is_array($adtype)) { |
| 485 | return array_merge($ad, $adtype); |
| 486 | } |
| 487 | else { |
| 488 | return $ad; |
| 489 | } |
| 490 | break; |
| 491 | |
| 492 | case 'insert': |
| 493 | if ($node->adtype) { |
| 494 | if ($node->status != 1 && $node->adstatus == 'active') { |
| 495 | $node->adstatus = t('unpublished'); |
| 496 | ad_statistics_increment($node->nid, 'unpublish'); |
| 497 | } |
| 498 | db_query("INSERT INTO {ads} (aid, uid, gid, adstatus, adtype, redirect, autoactivate, autoexpire) VALUES(%d, %d, %d, '%s', '%s', '%s', %d, %d)", $node->nid, $node->uid, $node->gid, $node->adstatus, $node->adtype, url("ad/redirect/$node->nid"), strtotime($node->autoactivate), strtotime($node->autoexpire)); |
| 499 | ad_host_id_create($node->uid); |
| 500 | ad_statistics_increment($node->nid, 'create'); |
| 501 | } |
| 502 | break; |
| 503 | |
| 504 | case 'update': |
| 505 | if ($node->adtype) { |
| 506 | if ($node->status != 1 && $node->adstatus == 'active') { |
| 507 | $node->adstatus = t('unpublished'); |
| 508 | ad_statistics_increment($node->nid, 'unpublish'); |
| 509 | } |
| 510 | else if ($node->status == 1 && $node->adstatus == 'unpublished') { |
| 511 | $node->adstatus = t('active'); |
| 512 | ad_statistics_increment($node->nid, 'publish'); |
| 513 | } |
| 514 | db_query("UPDATE {ads} SET uid = %d, gid = %d, adstatus = '%s', adtype = '%s', autoactivate = %d, autoexpire = %d WHERE aid = %d", $node->uid, $node->gid, $node->adstatus, $node->adtype, strtotime($node->autoactivate), strtotime($node->autoexpire), $node->nid); |
| 515 | ad_host_id_create($node->uid); |
| 516 | ad_statistics_increment($node->nid, 'update'); |
| 517 | } |
| 518 | break; |
| 519 | |
| 520 | case 'delete': |
| 521 | db_query("DELETE FROM {ads} WHERE aid = %d", $node->nid); |
| 522 | db_query("DELETE FROM {ad_statistics} WHERE aid = %d", $node->nid); |
| 523 | break; |
| 524 | |
| 525 | case 'view': |
| 526 | if ($node->adtype) { |
| 527 | $node = node_prepare($node, $teaser); |
| 528 | if (user_access('administer advertisements')) { |
| 529 | $node->body .= theme_ad_statistics_display($node->nid); |
| 530 | |
| 531 | $header = array( |
| 532 | array('data' => t('Time'), 'field' => 'timestamp', 'sort' => 'desc'), |
| 533 | array('data' => t('Username'), 'field' => 'uid'), |
| 534 | array('data' => t('IP address'), 'field' => 'hostname'), |
| 535 | array('data' => t('URL where clicked'), 'field' => 'url'), |
| 536 | ); |
| 537 | |
| 538 | if ($node->nid) { |
| 539 | $sql = "SELECT timestamp,uid,hostname,url FROM {ad_clicks} WHERE aid = $node->nid"; |
| 540 | $sql .= tablesort_sql($header); |
| 541 | $result = pager_query($sql, 15); |
| 542 | |
| 543 | while ($ad = db_fetch_object($result)) { |
| 544 | $row = array(); |
| 545 | $click_user = user_load(array('uid' => $ad->uid)); |
| 546 | $row[] = format_date($ad->timestamp, 'custom', 'F j, Y H:i'); |
| 547 | $row[] = $ad->uid ? l($click_user->name, "user/$ad->uid") : variable_get('anonymous', 'Anonymous'); |
| 548 | $row[] = $ad->hostname; |
| 549 | $row[] = l($ad->url, $ad->url); |
| 550 | $rows[] = $row; |
| 551 | } |
| 552 | |
| 553 | $output = theme('table', $header, $rows); |
| 554 | $output .= theme('pager', NULL, 50, 0); |
| 555 | $node->body .= theme('box', t('Click history'), $output); |
| 556 | } |
| 557 | } |
| 558 | } |
| 559 | break; |
| 560 | |
| 561 | |
| 562 | case 'validate': |
| 563 | break; |
| 564 | |
| 565 | } |
| 566 | // insert ad type data |
| 567 | if ($node->adtype) { |
| 568 | module_invoke('ad_'. $node->adtype, 'adapi', $op, $node); |
| 569 | } |
| 570 | } |
| 571 | |
| 572 | /** |
| 573 | * Drupal _menu hook. |
| 574 | */ |
| 575 | function ad_menu($may_cache) { |
| 576 | global $user; |
| 577 | $items = array(); |
| 578 | |
| 579 | if ($may_cache) { |
| 580 | // menu items |
| 581 | $items[] = array('path' => 'admin/ad', |
| 582 | 'title' => t('ads'), |
| 583 | 'callback' => 'ad_admin_list', |
| 584 | 'access' => user_access('administer advertisements')); |
| 585 | |
| 586 | // tabs |
| 587 | $items[] = array('path' => 'admin/ad/list', |
| 588 | 'title' => t('list'), |
| 589 | 'callback' => 'ad_admin_list', |
| 590 | 'type' => MENU_DEFAULT_LOCAL_TASK); |
| 591 | $items[] = array('path' => 'admin/ad/configure', |
| 592 | 'title' => t('settings'), |
| 593 | 'callback' => 'ad_admin_configure_settings', |
| 594 | 'type' => MENU_LOCAL_TASK, |
| 595 | 'weight' => 3); |
| 596 | $items[] = array('path' => 'admin/ad/groups', |
| 597 | 'title' => t('groups'), |
| 598 | 'callback' => 'ad_admin_groups_configure', |
| 599 | 'type' => MENU_LOCAL_TASK, |
| 600 | 'weight' => 5); |
| 601 | |
| 602 | // configure sub tabs |
| 603 | $items[] = array('path' => 'admin/ad/configure/global', |
| 604 | 'title' => t('global settings'), |
| 605 | 'callback' => 'ad_admin_configure_settings', |
| 606 | 'type' => MENU_DEFAULT_LOCAL_TASK, |
| 607 | 'weight' => 0); |
| 608 | $items[] = array('path' => 'admin/ad/groups/list', |
| 609 | 'title' => t('list'), |
| 610 | 'callback' => 'ad_admin_groups_configure', |
| 611 | 'type' => MENU_DEFAULT_LOCAL_TASK, |
| 612 | 'weight' => 0); |
| 613 | |
| 614 | |
| 615 | $items[] = array('path' => 'node/add/ad', |
| 616 | 'title' => t('ad'), |
| 617 | 'callback' => 'ad_add', |
| 618 | 'access' => user_access('create advertisements')); |
| 619 | } |
| 620 | else { |
| 621 | // callbacks |
| 622 | |
| 623 | if (arg(0) == 'ad' && arg(1) == 'redirect' && is_numeric(arg(2))) { |
| 624 | $aid = arg(2); |
| 625 | $optional = arg(3); |
| 626 | $items[] = array('path' => "ad/redirect/$aid", |
| 627 | 'access' => user_access('show advertisements'), |
| 628 | 'type' => MENU_CALLBACK, |
| 629 | 'callback' => 'ad_redirect', |
| 630 | 'callback arguments' => array($aid, $optional)); |
| 631 | } |
| 632 | elseif (arg(1) == 'ad' && arg(2) == 'groups' && is_numeric(arg(3))) { |
| 633 | $gid = arg(3); |
| 634 | $items[] = array('path' => "admin/ad/groups/$gid/delete", |
| 635 | 'title' => t('delete'), |
| 636 | 'callback' => 'ad_admin_groups_delete', |
| 637 | 'type' => MENU_CALLBACK, |
| 638 | 'weight' => 1); |
| 639 | } |
| 640 | elseif (arg(0) == 'node' && is_numeric(arg(1)) && |
| 641 | (user_access('administer advertisements') || user_access('edit own advertisements'))) { |
| 642 | $node = node_load(array('nid' => arg(1))); |
| 643 | |
| 644 | $items[] = array('path' => "node/$node->nid/ad", |
| 645 | 'access' => user_access('administer advertisements') || |
| 646 | ($node->uid == $user->uid && user_access('edit own advertisements')), |
| 647 | 'title' => t('ad owners'), |
| 648 | 'callback' => 'ad_owners_overview', |
| 649 | 'callback arguments' => array($node), |
| 650 | 'type' => MENU_LOCAL_TASK, |
| 651 | 'weight' => 5); |
| 652 | |
| 653 | if (is_numeric(arg(3))) { |
| 654 | $uid = arg(3); |
| 655 | $ad_user = user_load(array('uid' => $uid)); |
| 656 | $items[] = array('path' => "node/$node->nid/ad/$uid/permissions", |
| 657 | 'title' => t('%owner\'s permissions', array('%owner' => $ad_user->name)), |
| 658 | 'callback' => 'ad_owner_permissions', |
| 659 | 'callback arguments' => array($node->nid, $uid), |
| 660 | 'type' => MENU_LOCAL_TASK, |
| 661 | 'weight' => 0); |
| 662 | $items[] = array('path' => "node/$node->nid/ad/$uid/notifications", |
| 663 | 'title' => t('%owner\'s notifications', array('%owner' => $ad_user->name)), |
| 664 | 'callback' => 'ad_owner_notifications', |
| 665 | 'callback arguments' => array($node->nid, $uid), |
| 666 | 'type' => MENU_LOCAL_TASK, |
| 667 | 'weight' => 1); |
| 668 | } |
| 669 | } |
| 670 | } |
| 671 | |
| 672 | return $items; |
| 673 | } |
| 674 | |
| 675 | /** |
| 676 | * Drupal _block hook. |
| 677 | */ |
| 678 | function ad_block($op = 'list', $delta = 0, $edit = array()) { |
| 679 | switch ($op) { |
| 680 | case 'list': |
| 681 | $blocks = array(); |
| 682 | $result = db_query('SELECT gid,name FROM {ad_groups}'); |
| 683 | while ($ad = db_fetch_object($result)) { |
| 684 | $blocks[$ad->gid]['info'] = t('ad group: <em>%name</em>', array('%name' => $ad->name)); |
| 685 | } |
| 686 | return $blocks; |
| 687 | case 'view': |
| 688 | $group = db_result(db_query('SELECT name FROM {ad_groups} WHERE gid = %d', $delta)); |
| 689 | $block['content'] = ad($group); |
| 690 | return $block; |
| 691 | } |
| 692 | } |
| 693 | |
| 694 | /****/ |
| 695 | |
| 696 | /** |
| 697 | * Present a list of ad types to choose from. |
| 698 | */ |
| 699 | function ad_add() { |
| 700 | global $user; |
| 701 | |
| 702 | $edit = isset($_POST['edit']) ? $_POST['edit'] : ''; |
| 703 | $adtypes = module_invoke_all('adapi', 'type'); |
| 704 | if (arg(3) && is_array($adtypes) && in_array(arg(3), array_keys($adtypes))) { |
| 705 | $adtype = arg(3); |
| 706 | |
| 707 | $node = array( |
| 708 | 'uid' => $user->uid, |
| 709 | 'name' => $user->name, |
| 710 | 'type' => 'ad', |
| 711 | 'adtype' => $adtype, |
| 712 | ); |
| 713 | |
| 714 | foreach (array('title', 'teaser', 'body') as $field) { |
| 715 | if ($_GET['edit'][$field]) { |
| 716 | $node[$field] = $_GET['edit'][$field]; |
| 717 | } |
| 718 | } |
| 719 | $output = node_form($node); |
| 720 | drupal_set_title(t('Submit %name', array('%name' => $adtype))); |
| 721 | } |
| 722 | else { |
| 723 | $output = t('Choose from the following available advertisement types:'); |
| 724 | $output .= '<dl>'; |
| 725 | if (sizeof($adtypes) == 1) { |
| 726 | drupal_goto('node/add/ad/'. $adtypes[0]); |
| 727 | } |
| 728 | else if (sizeof($adtypes)) { |
| 729 | foreach ($adtypes as $type) { |
| 730 | $output .= '<dt>'. l(t('%type advertisement', array('%type' => $type)), "node/add/ad/$type") .'</dt>'; |
| 731 | $output .= '<dd>'. implode("\n", module_invoke_all('help', 'node/add/ad#'. $type)) .'</dd>'; |
| 732 | } |
| 733 | } |
| 734 | else { |
| 735 | $output .= '<dt>'. t('There are no advertisement types available.') .'</dt>'; |
| 736 | } |
| 737 | $output .= '</dl>'; |
| 738 | } |
| 739 | |
| 740 | return $output; |
| 741 | } |
| 742 | |
| 743 | /** |
| 744 | * |
| 745 | */ |
| 746 | function ad_owners_overview($node) { |
| 747 | // Be sure the node owner is listed as an ad owner |
| 748 | if (!db_result(db_query('SELECT oid FROM {ad_owners} WHERE uid = %d AND aid = %d', $node->uid, $node->nid))) { |
| 749 | ad_owners_add($node->nid, $node->uid); |
| 750 | } |
| 751 | |
| 752 | $header = array( |
| 753 | array('data' => t('Username'), 'field' => 'uid'), |
| 754 | array('data' => t('Options')), |
| 755 | ); |
| 756 | |
| 757 | $sql = "SELECT uid FROM {ad_owners} WHERE aid = $node->nid"; |
| 758 | $sql .= tablesort_sql($header); |
| 759 | $result = pager_query($sql, 25); |
| 760 | |
| 761 | $rows = array(); |
| 762 | while ($ad = db_fetch_object($result)) { |
| 763 | $row = array(); |
| 764 | $user = user_load(array('uid' => $ad->uid)); |
| 765 | $row[] = $user->name; |
| 766 | $row[] = l(t('permissions'), "node/$node->nid/ad/$user->uid/permissions") .' | '. l(t('notifications'), "node/$node->nid/ad/$user->uid/notifications"); |
| 767 | $rows[] = $row; |
| 768 | } |
| 769 | |
| 770 | $output = theme('table', $header, $rows); |
| 771 | $output .= theme('pager', NULL, 25, 0); |
| 772 | |
| 773 | $output .= '<p></p>'; |
| 774 | $output .= t('Ad owners are not implemented yet.'); |
| 775 | |
| 776 | return $output; |
| 777 | } |
| 778 | |
| 779 | /** |
| 780 | * Add an owner to an ad. |
| 781 | */ |
| 782 | function ad_owners_add($aid, $uid) { |
| 783 | db_query('LOCK TABLES {ad_owners} WRITE'); |
| 784 | if (!db_result(db_query('SELECT oid FROM {ad_owners} WHERE uid = %d AND aid = %d', $node->uid, $aid))) { |
| 785 | db_query('INSERT INTO {ad_owners} (aid, uid) VALUES(%d, %d)', $aid, $uid); |
| 786 | } |
| 787 | db_query('UNLOCK TABLES'); |
| 788 | } |
| 789 | |
| 790 | function ad_owner_permissions($aid, $uid) { |
| 791 | $output = t('Ad permissions are not implemented yet.'); |
| 792 | return $output; |
| 793 | } |
| 794 | |
| 795 | function ad_owner_notifications($aid, $uid) { |
| 796 | $output = t('Ad notifications are not implemented yet.'); |
| 797 | return $output; |
| 798 | } |
| 799 | |
| 800 | /** |
| 801 | * Create a unique host id for each ad owner, used when displaying ads remotely. |
| 802 | */ |
| 803 | function ad_host_id_create($uid) { |
| 804 | if (!db_result(db_query('SELECT hostid FROM {ad_hosts} WHERE uid = %d', $uid))) { |
| 805 | db_query("INSERT INTO {ad_hosts} (uid, hostid) VALUES (%d, '%s')", $uid, md5($uid . time())); |
| 806 | } |
| 807 | } |
| 808 | |
| 809 | /** |
| 810 | * Display a list of all ads. |
| 811 | * TODO: Cleanup output. |
| 812 | * TODO: Provide filters to help with managing large quantities of ads. |
| 813 | */ |
| 814 | function ad_admin_list() { |
| 815 | _ad_check_install(); |
| 816 | |
| 817 | $header = array( |
| 818 | array('data' => t('Title'), 'field' => 'n.title'), |
| 819 | array('data' => t('Type'), 'field' => 'a.adtype'), |
| 820 | array('data' => t('Group'), 'field' => 'a.gid'), |
| 821 | array('data' => t('Status'), 'field' => 'a.adstatus'), |
| 822 | array('data' => t('Options')), |
| 823 | ); |
| 824 | |
| 825 | $sql = 'SELECT a.aid, a.gid, a.adstatus, a.adtype, n.title FROM {ads} a LEFT JOIN {node} n ON a.aid = n.nid'; |
| 826 | $sql .= tablesort_sql($header); |
| 827 | $result = pager_query($sql, 50); |
| 828 | |
| 829 | while ($ad = db_fetch_object($result)) { |
| 830 | $row = array(); |
| 831 | $row[] = $ad->title; |
| 832 | $row[] = $ad->adtype; |
| 833 | $row[] = ad_group_name($ad->gid); |
| 834 | $row[] = $ad->adstatus; |
| 835 | $row[] = l(t('edit'), "node/$ad->aid/edit"); |
| 836 | $rows[] = $row; |
| 837 | } |
| 838 | |
| 839 | $output = theme('table', $header, $rows); |
| 840 | $output .= theme('pager', NULL, 50, 0); |
| 841 | return $output; |
| 842 | } |
| 843 | |
| 844 | /** |
| 845 | * Display a form for the ad module settings. |
| 846 | */ |
| 847 | function ad_admin_configure_settings($edit = array()) { |
| 848 | _ad_check_install(); |
| 849 | |
| 850 | $adserve = variable_get('adserve', ''); |
| 851 | $form['configuration'] = array( |
| 852 | '#type' => 'fieldset', |
| 853 | '#title' => t('Status'), |
| 854 | ); |
| 855 | $form['configuration']['adserve'] = array( |
| 856 | '#type' => 'markup', |
| 857 | '#value' => t('Using detected adserve script</em>: <em>%adserve</em>', array('%adserve' => ($adserve ? $adserve : t('not found')))), |
| 858 | ); |
| 859 | |
| 860 | $form['cache'] = array( |
| 861 | '#type' => 'fieldset', |
| 862 | '#title' => t('Cache settings') |
| 863 | ); |
| 864 | $form['cache']['ad_cache'] = array( |
| 865 | '#type' => 'radios', |
| 866 | '#title' => t('Type'), |
| 867 | '#default_value' => variable_get('ad_cache', 'database'), |
| 868 | '#options' => array('database' => t('Database'), 'file' => t('File')), |
| 869 | '#description' => t('The cache is used to efficiently track how many times advertisements are displayed and clicked. File based caching will usually offer better performance, however, it can be difficult to configure and will not offer valid statistics if you are using multiple load balanced web servers.') |
| 870 | ); |
| 871 | |
| 872 | // Only enable the 'files' option if the file cache is enabled. |
| 873 | if (variable_get('ad_cache', 'database') == 'file') { |
| 874 | $attributes = array('enabled' => 'enabled'); |
| 875 | $description = t('Please select the number of cache files the ad module should use. Select a smaller value for better accuracy when performaing automatic actions on advertisements at specified thresholds. Select a larger value for better performance.'); |
| 876 | } |
| 877 | else { |
| 878 | $attributes = array('disabled' => 'disabled'); |
| 879 | $description = t('This configuration setting is only relevant if the file cache is enabled.'); |
| 880 | } |
| 881 | |
| 882 | $form['cache']['ad_files'] = array( |
| 883 | '#type' => 'select', |
| 884 | '#title' => t('Number of cache files'), |
| 885 | '#default_value' => variable_get('ad_files', '1'), |
| 886 | '#options' => drupal_map_assoc(array(1, 3, 5, 10, 15)), |
| 887 | '#description' => $description, |
| 888 | '#attributes' => $attributes, |
| 889 | ); |
| 890 | |
| 891 | $form['save'] = array( |
| 892 | '#type' => 'submit', |
| 893 | '#value' => t('Save'), |
| 894 | ); |
| 895 | |
| 896 | return drupal_get_form('ad_settings_form', $form); |
| 897 | } |
| 898 | |
| 899 | /** |
| 900 | * Prevent people from enabling the file cache until it is implemented. |
| 901 | */ |
| 902 | function ad_settings_form_validate($form_id, $form_values) { |
| 903 | if ($form_values['ad_cache'] == 'file') { |
| 904 | form_set_error('ad_cache', t('Sorry, the file cache is not support by this version of the ad module. At this time you must use the database cache.')); |
| 905 | } |
| 906 | } |
| 907 | |
| 908 | /** |
| 909 | * Save updated values from settings form. |
| 910 | */ |
| 911 | function ad_settings_form_submit($form_id, $form_values) { |
| 912 | variable_set('ad_cache', $form_values['ad_cache']); |
| 913 | variable_set('ad_files', $form_values['ad_files']); |
| 914 | } |
| 915 | |
| 916 | /** |
| 917 | * Return an array of all groups. |
| 918 | */ |
| 919 | function ad_groups_list() { |
| 920 | static $groups = NULL; |
| 921 | if (is_array($groups)) { |
| 922 | return $groups; |
| 923 | } |
| 924 | $result = db_query('SELECT gid,name,description FROM {ad_groups}'); |
| 925 | while ($group = db_fetch_object($result)) { |
| 926 | $groups[$group->gid] = "$group->name<br />$group->description"; |
| 927 | } |
| 928 | return $groups; |
| 929 | } |
| 930 | |
| 931 | function ad_group_name($gid) { |
| 932 | static $groups = NULL; |
| 933 | if (isset($groups[$gid])) { |
| 934 | return $groups[$gid]; |
| 935 | } |
| 936 | $groups[$gid] = db_result(db_query('SELECT name FROM {ad_groups} WHERE gid = %d', $gid)); |
| 937 | return $groups[$gid]; |
| 938 | } |
| 939 | |
| 940 | function ad_admin_groups_configure($gid = 0, $op = NULL) { |
| 941 | _ad_check_install(); |
| 942 | |
| 943 | $header = array( |
| 944 | array('data' => t('Name'), 'field' => 'name'), |
| 945 | array('data' => t('Description'), 'field' => 'description'), |
| 946 | array('data' => t('Options')), |
| 947 | ); |
| 948 | |
| 949 | $sql = 'SELECT gid, name, description FROM {ad_groups}'; |
| 950 | $sql .= tablesort_sql($header); |
| 951 | $result = pager_query($sql, 15); |
| 952 | |
| 953 | if (db_num_rows($result)) { |
| 954 | while ($group = db_fetch_object($result)) { |
| 955 | $row = array(); |
| 956 | $row[] = $group->name; |
| 957 | $row[] = $group->description; |
| 958 | if ($group->gid == 1) { |
| 959 | $row[] = ''; |
| 960 | } |
| 961 | else { |
| 962 | $row[] = l(t('edit'), "admin/ad/groups/$group->gid/edit"); |
| 963 | } |
| 964 | $rows[] = $row; |
| 965 | } |
| 966 | } |
| 967 | else { |
| 968 | $rows[] = array(array('data' => t('No groups available.'), 'colspan' => 3)); |
| 969 | } |
| 970 | |
| 971 | $output = theme('table', $header, $rows); |
| 972 | $output .= theme('pager', NULL, 15, 0); |
| 973 | |
| 974 | if ($gid && $op == 'edit') { |
| 975 | $edit = TRUE; |
| 976 | $group = db_fetch_object(db_query('SELECT gid, name, description FROM {ad_groups} WHERE gid = %d', $gid)); |
| 977 | } |
| 978 | else { |
| 979 | $edit = FALSE; |
| 980 | } |
| 981 | |
| 982 | $form['group'] = array( |
| 983 | '#type' => 'fieldset', |
| 984 | '#title' => $edit ? t('Save group') : t('Create new group'), |
| 985 | ); |
| 986 | $form['group']['name'] = array( |
| 987 | '#type' => 'textfield', |
| 988 | '#title' => t('Group name'), |
| 989 | '#maxlength' => 255, |
| 990 | '#default_value' => $group->name, |
| 991 | '#required' => TRUE, |
| 992 | '#description' => t('Specify a name for your new ad group. The name can only contain numbers and letters. It can not contain spaces or punctuation.'), |
| 993 | ); |
| 994 | $form['group']['description'] = array( |
| 995 | '#type' => 'textarea', |
| 996 | '#title' => t('Group desciption'), |
| 997 | '#default_value' => $group->description, |
| 998 | '#required' => TRUE, |
| 999 | '#description' => t('Enter a description of your new ad group. This description is displayed when new advertisements are created.'), |
| 1000 | ); |
| 1001 | $form['group']['gid'] = array( |
| 1002 | '#type' => 'value', |
| 1003 | '#value' => $gid, |
| 1004 | ); |
| 1005 | $form['group']['actions'] = array( |
| 1006 | '#prefix' => '<div class="container-inline">', |
| 1007 | '#suffix' => '</div>', |
| 1008 | ); |
| 1009 | $form['group']['actions']['submit'] = array( |
| 1010 | '#type' => 'submit', |
| 1011 | '#value' => $edit ? t('Save group') : t('Create group'), |
| 1012 | ); |
| 1013 | if ($edit) { |
| 1014 | $form['group']['actions']['delete'] = array( |
| 1015 | '#type' => 'submit', |
| 1016 | '#value' => t('Delete group'), |
| 1017 | ); |
| 1018 | $form['group']['actions']['cancel'] = array( |
| 1019 | '#type' => 'markup', |
| 1020 | '#value' => l(t('Cancel'), 'admin/ad/groups'), |
| 1021 | ); |
| 1022 | } |
| 1023 | $output .= drupal_get_form('ad_admin_group_create', $form); |
| 1024 | |
| 1025 | return $output; |
| 1026 | } |
| 1027 | |
| 1028 | function ad_admin_group_create_validate($form_id, $form_values) { |
| 1029 |