pierre@0
|
1 <?php |
piotre@7
|
2 // $Id: ad_report.module,v 1.1.2.3.2.7.2.6.2.8 2009/07/03 18:37:44 jeremy Exp $ |
pierre@0
|
3 |
pierre@0
|
4 /** |
pierre@0
|
5 * @file |
pierre@0
|
6 * Provides comprehensive charts and reports about advertising statistics. |
pierre@0
|
7 * |
pierre@1
|
8 * Copyright (c) 2007-2009. |
pierre@0
|
9 * Jeremy Andrews <jeremy@tag1consulting.com>. |
pierre@0
|
10 */ |
pierre@0
|
11 |
pierre@0
|
12 /** |
pierre@0
|
13 * Implementation of hook_menu(). |
pierre@0
|
14 */ |
pierre@0
|
15 function ad_report_menu() { |
pierre@0
|
16 $items = array(); |
pierre@1
|
17 $items['admin/content/ad/report'] = array( |
pierre@1
|
18 'title' => t('Reports'), |
pierre@1
|
19 'page callback' => 'drupal_get_form', |
pierre@1
|
20 'page arguments' => array('ad_report_admin'), |
pierre@1
|
21 'access arguments' => array('generate administrative reports'), |
pierre@1
|
22 'type' => MENU_LOCAL_TASK, |
pierre@1
|
23 'weight' => 1 |
pierre@1
|
24 ); |
pierre@1
|
25 $items['admin/content/ad/report/display'] = array( |
pierre@1
|
26 'page callback' => 'ad_report_admin_display', |
pierre@1
|
27 'access arguments' => array('generate administrative reports'), |
pierre@1
|
28 'type' => MENU_CALLBACK |
pierre@1
|
29 ); |
pierre@1
|
30 $items['admin/content/ad/report/csv'] = array( |
pierre@1
|
31 'page callback' => 'ad_report_admin_ad_table', |
pierre@1
|
32 'page arguments' => array('0', '0', array(), TRUE), |
pierre@1
|
33 'access arguments' => array('generate administrative reports'), |
pierre@1
|
34 'type' => MENU_CALLBACK |
pierre@1
|
35 ); |
pierre@0
|
36 $items['node/%node/report'] = array( |
pierre@1
|
37 'title' => t('Reports'), |
pierre@1
|
38 'page callback' => 'ad_report_bargraph_handler', |
pierre@0
|
39 'page arguments' => array(1), |
pierre@0
|
40 'type' => MENU_LOCAL_TASK, |
pierre@1
|
41 'access callback' => 'ad_report_bargraph_access', |
pierre@0
|
42 'access arguments' => array(1), |
pierre@0
|
43 ); |
pierre@1
|
44 $items['ad_report/%node/bargraph/node/%/%'] = array( |
pierre@1
|
45 'title' => 'Bar graph', |
pierre@1
|
46 'page callback' => 'ad_report_generate_bargraph', |
pierre@1
|
47 'page arguments' => array(1, 'node', 4, 5), |
pierre@1
|
48 'type' => MENU_CALLBACK, |
pierre@1
|
49 'access callback' => 'ad_report_bargraph_access', |
pierre@0
|
50 'access arguments' => array(1), |
pierre@0
|
51 ); |
pierre@1
|
52 return $items; |
pierre@1
|
53 } |
pierre@1
|
54 |
pierre@1
|
55 /** |
pierre@1
|
56 * Drupal hook_perm implementation. |
pierre@1
|
57 */ |
pierre@1
|
58 function ad_report_perm() { |
pierre@1
|
59 return array(t('generate administrative reports')); |
pierre@1
|
60 } |
pierre@1
|
61 |
pierre@1
|
62 /** |
pierre@1
|
63 * Menu system callback, determine if current user can generate reports. |
pierre@1
|
64 */ |
pierre@1
|
65 function ad_report_bargraph_access($node) { |
pierre@1
|
66 if (isset($node->adtype)) { |
pierre@1
|
67 return ad_permission($node->nid, 'generate reports'); |
pierre@1
|
68 } |
pierre@1
|
69 } |
pierre@1
|
70 |
pierre@1
|
71 /** |
pierre@1
|
72 * |
pierre@1
|
73 */ |
pierre@1
|
74 function ad_report_bargraph_handler($node) { |
pierre@1
|
75 return ad_report_bargraph($node, "node/$node->nid/report", 'node', arg(3), arg(4)); |
pierre@1
|
76 } |
pierre@1
|
77 |
pierre@1
|
78 /** |
pierre@1
|
79 * Ad module hook_adapi. |
pierre@1
|
80 */ |
pierre@1
|
81 function ad_report_adapi($op, $node = NULL) { |
pierre@1
|
82 switch ($op) { |
pierre@1
|
83 case 'permissions': |
pierre@1
|
84 return array( |
pierre@1
|
85 'generate reports' => TRUE, |
pierre@1
|
86 ); |
pierre@1
|
87 } |
pierre@1
|
88 } |
pierre@1
|
89 |
pierre@1
|
90 /** |
pierre@1
|
91 * |
pierre@1
|
92 */ |
pierre@1
|
93 function ad_report_admin() { |
pierre@1
|
94 $form = array(); |
pierre@1
|
95 |
pierre@1
|
96 $start = isset($_SESSION['ad_report_start']) ? strtotime($_SESSION['ad_report_start']) : _ad_report_first_day_of_month(); |
pierre@1
|
97 $end = isset($_SESSION['ad_report_end']) ? strtotime($_SESSION['ad_report_end']) : _ad_report_last_day_of_month(); |
pierre@1
|
98 $group = isset($_SESSION['ad_report_group']) ? $_SESSION['ad_report_group'] : array('all'); |
pierre@1
|
99 |
pierre@1
|
100 $form['dates'] = array( |
pierre@1
|
101 '#type' => 'fieldset', |
pierre@1
|
102 '#title' => t('Report dates'), |
pierre@1
|
103 '#prefix' => '<div class="container-inline">', |
pierre@1
|
104 '#suffix' => '</div>', |
pierre@0
|
105 ); |
pierre@1
|
106 $form['dates']['start'] = array( |
pierre@1
|
107 '#type' => 'textfield', |
pierre@1
|
108 '#title' => t('Start'), |
pierre@1
|
109 '#size' => 24, |
pierre@1
|
110 '#maxlength' => 64, |
pierre@1
|
111 '#default_value' => _ad_report_format_date_human($start), |
pierre@1
|
112 // display pop up calendar if jstools jscalendar module enabled |
pierre@1
|
113 '#attributes' => array('class' => 'jscalendar'), |
pierre@1
|
114 '#jscalendar_ifFormat' => '%Y-%m-%d %H:%M', |
pierre@1
|
115 '#jscalendar_timeFormat' => '24', |
pierre@0
|
116 ); |
pierre@1
|
117 $form['dates']['space1'] = array( |
pierre@1
|
118 '#value' => ' ', |
pierre@1
|
119 ); |
pierre@1
|
120 $form['dates']['end'] = array( |
pierre@1
|
121 '#type' => 'textfield', |
pierre@1
|
122 '#title' => t('End'), |
pierre@1
|
123 '#size' => 24, |
pierre@1
|
124 '#maxlength' => 64, |
pierre@1
|
125 '#default_value' => _ad_report_format_date_human($end), |
pierre@1
|
126 // display pop up calendar if jstools jscalendar module enabled |
pierre@1
|
127 '#attributes' => array('class' => 'jscalendar'), |
pierre@1
|
128 '#jscalendar_ifFormat' => '%Y-%m-%d %H:%M', |
pierre@1
|
129 ); |
pierre@1
|
130 $form['dates']['space2'] = array( |
pierre@1
|
131 '#value' => ' ', |
pierre@0
|
132 ); |
pierre@0
|
133 |
pierre@1
|
134 // groups |
pierre@1
|
135 $groups = ad_groups_list(); |
pierre@1
|
136 $form['groups'] = array( |
pierre@1
|
137 '#type' => 'fieldset', |
pierre@1
|
138 '#title' => t('Groups'), |
pierre@1
|
139 ); |
pierre@1
|
140 $options = array(); |
pierre@1
|
141 $options['all'] = t('- All -'); |
pierre@1
|
142 $options = $options + $groups; |
pierre@1
|
143 $form['groups']['group'] = array( |
pierre@1
|
144 '#type' => 'select', |
pierre@1
|
145 '#title' => t('Ad groups'), |
pierre@1
|
146 '#options' => $options, |
pierre@1
|
147 '#multiple' => TRUE, |
pierre@1
|
148 '#required' => TRUE, |
pierre@1
|
149 '#default_value' => $group, |
pierre@1
|
150 ); |
pierre@1
|
151 |
pierre@1
|
152 // submit |
pierre@1
|
153 $form['submit'] = array( |
pierre@1
|
154 '#type' => 'submit', |
pierre@1
|
155 '#value' => t('Generate report'), |
pierre@1
|
156 '#weight' => 10, |
pierre@1
|
157 ); |
pierre@1
|
158 $form['reset'] = array( |
pierre@1
|
159 '#type' => 'submit', |
pierre@1
|
160 '#value' => t('Reset report'), |
pierre@1
|
161 '#weight' => 10, |
pierre@1
|
162 ); |
pierre@1
|
163 |
pierre@1
|
164 return $form; |
pierre@0
|
165 } |
pierre@1
|
166 |
pierre@0
|
167 /** |
pierre@1
|
168 * Sanity check the date range. |
pierre@1
|
169 */ |
pierre@1
|
170 function ad_report_admin_validate($form, $form_state) { |
pierre@1
|
171 if ($form_state['clicked_button']['#value'] == t('Reset report')) { |
pierre@1
|
172 unset($_SESSION['ad_report_start']); |
pierre@1
|
173 unset($_SESSION['ad_report_end']); |
pierre@1
|
174 unset($_SESSION['ad_report_group']); |
pierre@1
|
175 } |
pierre@1
|
176 else { |
pierre@1
|
177 $start = isset($form_state['values']['start']) ? strtotime($form_state['values']['start']) : 0; |
pierre@1
|
178 $end = isset($form_state['values']['start']) ? strtotime($form_state['values']['end']) : 0; |
pierre@1
|
179 if (!$start) { |
pierre@1
|
180 form_set_error('start', t('You must enter a valid start date.')); |
pierre@1
|
181 } |
pierre@1
|
182 else if ($start >= (time() - 3600)) { |
pierre@1
|
183 form_set_error('start', t('The report must start at least one hour before the current time.')); |
pierre@1
|
184 } |
pierre@1
|
185 else if ($start >= $end) { |
pierre@1
|
186 form_set_error('start', t('The report must start before it ends.')); |
pierre@1
|
187 } |
pierre@1
|
188 if (!$end) { |
pierre@1
|
189 form_set_error('end', t('You must enter a valid end date.')); |
pierre@1
|
190 } |
pierre@1
|
191 } |
pierre@0
|
192 } |
pierre@1
|
193 |
pierre@1
|
194 /** |
pierre@1
|
195 * Redirect to a path to generate the requested report. |
pierre@1
|
196 */ |
pierre@1
|
197 function ad_report_admin_submit($form, $form_state) { |
pierre@1
|
198 if ($form_state['clicked_button']['#value'] == t('Generate report')) { |
pierre@1
|
199 $start = date('YmdHi', strtotime($form_state['values']['start'])); |
pierre@1
|
200 $end = date('YmdHi', strtotime($form_state['values']['end'])); |
pierre@1
|
201 $group = $form_state['values']['group']; |
pierre@1
|
202 $_SESSION['ad_report_start'] = $start; |
pierre@1
|
203 $_SESSION['ad_report_end'] = $end; |
pierre@1
|
204 $_SESSION['ad_report_group'] = $group; |
pierre@1
|
205 |
pierre@1
|
206 drupal_goto('admin/content/ad/report/display'); |
pierre@1
|
207 } |
pierre@1
|
208 } |
pierre@1
|
209 |
pierre@1
|
210 /** |
pierre@1
|
211 * Display the administrative report. |
pierre@1
|
212 */ |
pierre@1
|
213 function ad_report_admin_display() { |
pierre@1
|
214 $start = isset($_SESSION['ad_report_start']) ? $_SESSION['ad_report_start'] : 0; |
pierre@1
|
215 $end = isset($_SESSION['ad_report_end']) ? $_SESSION['ad_report_end'] : 0; |
pierre@1
|
216 $group = isset($_SESSION['ad_report_group']) ? $_SESSION['ad_report_group'] : array(); |
pierre@1
|
217 if (!$start && !$end) { |
pierre@1
|
218 drupal_goto('admin/content/ad/report'); |
pierre@1
|
219 } |
pierre@1
|
220 $output = '<div class="image"><img src="'. url("ad_report/0/bargraph/admin/$start/$end") .'" /></div>'; |
pierre@1
|
221 $output .= ad_report_admin_ad_table(strtotime($start), strtotime($end), $group); |
pierre@1
|
222 $output .= '<div>'. l(t('Modify report'), 'admin/content/ad/report') .'</div>'; |
pierre@1
|
223 return $output; |
pierre@1
|
224 } |
pierre@1
|
225 |
pierre@1
|
226 /** |
pierre@1
|
227 * |
pierre@1
|
228 */ |
pierre@1
|
229 function ad_report_admin_ad_table($start = 0, $end = 0, $group = array(), $csv = FALSE) { |
pierre@1
|
230 if (!$start) { |
pierre@1
|
231 $start = isset($_SESSION['ad_report_start']) ? strtotime($_SESSION['ad_report_start']) : 0; |
pierre@1
|
232 } |
pierre@1
|
233 if (!$end) { |
pierre@1
|
234 $end = isset($_SESSION['ad_report_end']) ? strtotime($_SESSION['ad_report_end']) : 0; |
pierre@1
|
235 } |
pierre@1
|
236 if (empty($group)) { |
pierre@1
|
237 $group = isset($_SESSION['ad_report_group']) ? $_SESSION['ad_report_group'] : array(); |
pierre@1
|
238 } |
pierre@1
|
239 // prepare dates |
pierre@1
|
240 $start = _ad_report_format_date_db($start); |
pierre@1
|
241 $end = _ad_report_format_date_db($end); |
pierre@1
|
242 |
pierre@1
|
243 // prepare groups |
pierre@1
|
244 $groups = ad_groups_list(); |
pierre@1
|
245 $all = FALSE; |
pierre@1
|
246 $none = FALSE; |
pierre@1
|
247 if (is_array($group)) { |
pierre@1
|
248 if (in_array('all', $group)) { |
pierre@1
|
249 $all = TRUE; |
pierre@1
|
250 } |
pierre@1
|
251 if (!$all) { |
pierre@1
|
252 if (sizeof($group) == sizeof($groups)) { |
pierre@1
|
253 $all = TRUE; |
pierre@1
|
254 } |
pierre@1
|
255 } |
pierre@1
|
256 if (in_array('0', $group)) { |
pierre@1
|
257 unset($group[0]); |
pierre@1
|
258 $none = TRUE; |
pierre@1
|
259 } |
pierre@1
|
260 } |
pierre@1
|
261 |
pierre@1
|
262 $select = 'SELECT DISTINCT(aid) as nid FROM {ad_statistics} a'; |
pierre@1
|
263 if ($all) { |
pierre@1
|
264 $where = array( |
pierre@1
|
265 "a.action = 'view'", |
pierre@1
|
266 'a.date >= %d', |
pierre@1
|
267 'a.date <= %d', |
pierre@1
|
268 'a.aid > 0', |
pierre@1
|
269 ); |
pierre@1
|
270 $join = array(); |
pierre@1
|
271 $args = array($start, $end); |
pierre@1
|
272 } |
pierre@1
|
273 else if ($none) { |
pierre@1
|
274 if (sizeof($group)) { |
pierre@1
|
275 $where = array( |
pierre@1
|
276 '(t.tid IN (%s) OR ISNULL(t.tid))', |
pierre@1
|
277 "a.action = 'view'", |
pierre@1
|
278 'a.date >= %d', |
pierre@1
|
279 'a.date <= %d', |
pierre@1
|
280 ); |
pierre@1
|
281 $join = array( |
piotre@7
|
282 'LEFT JOIN {term_node} t ON a.aid = t.nid', |
pierre@1
|
283 ); |
pierre@1
|
284 $args = array(implode(',', $group), $start, $end); |
pierre@1
|
285 } |
pierre@1
|
286 else { |
pierre@1
|
287 $where = array( |
pierre@1
|
288 'ISNULL(t.tid)', |
pierre@1
|
289 "a.action = 'view'", |
pierre@1
|
290 'a.date >= %d', |
pierre@1
|
291 'a.date <= %d', |
pierre@1
|
292 ); |
pierre@1
|
293 $join = array( |
piotre@7
|
294 'LEFT JOIN {term_node} t ON a.aid = t.nid', |
pierre@1
|
295 ); |
pierre@1
|
296 $args = array($start, $end); |
pierre@1
|
297 } |
pierre@1
|
298 } |
pierre@1
|
299 else { |
pierre@1
|
300 $where = array( |
pierre@1
|
301 't.tid IN (%s)', |
pierre@1
|
302 "a.action = 'view'", |
pierre@1
|
303 'a.date >= %d', |
pierre@1
|
304 'a.date <= %d', |
pierre@1
|
305 ); |
pierre@1
|
306 $join = array( |
piotre@7
|
307 'LEFT JOIN {term_node} t ON a.aid = t.nid', |
pierre@1
|
308 ); |
pierre@1
|
309 $args = array(implode(',', $group), $start, $end); |
pierre@1
|
310 } |
pierre@1
|
311 |
pierre@1
|
312 $return = module_invoke_all('adreport', $join, $where, $args, $select); |
pierre@1
|
313 foreach ($return as $type => $value) { |
pierre@1
|
314 switch ($type) { |
pierre@1
|
315 case 'join': |
pierre@1
|
316 if (is_array($value)) { |
pierre@1
|
317 foreach ($value as $option) { |
pierre@1
|
318 $join[] = $option; |
pierre@1
|
319 } |
pierre@1
|
320 } |
pierre@1
|
321 break; |
pierre@1
|
322 case 'where': |
pierre@1
|
323 if (is_array($value)) { |
pierre@1
|
324 foreach ($value as $option) { |
pierre@1
|
325 $where[] = $option; |
pierre@1
|
326 } |
pierre@1
|
327 } |
pierre@1
|
328 break; |
pierre@1
|
329 case 'args': |
pierre@1
|
330 if (is_array($value)) { |
pierre@1
|
331 foreach ($value as $option) { |
pierre@1
|
332 $args[] = $option; |
pierre@1
|
333 } |
pierre@1
|
334 } |
pierre@1
|
335 break; |
pierre@1
|
336 } |
pierre@1
|
337 } |
pierre@1
|
338 |
pierre@1
|
339 // Build the query. |
pierre@1
|
340 $query = $select .' '. implode(' ', $join) .' WHERE '. implode(' AND ', $where); |
pierre@1
|
341 $ads = array(); |
pierre@1
|
342 $result = db_query($query, $args); |
pierre@1
|
343 while ($ad = db_fetch_object($result)) { |
pierre@1
|
344 if ($ad->nid) { |
pierre@1
|
345 $ads[$ad->nid] = $ad->nid; |
pierre@1
|
346 } |
pierre@1
|
347 } |
pierre@1
|
348 |
pierre@1
|
349 if ($csv) { |
pierre@1
|
350 header('Content-type: application/octet-stream'); |
pierre@1
|
351 header("Content-Disposition: attachment; filename=report-$start-$end.csv"); |
pierre@1
|
352 echo "ad id, title, first view, last view, clicks, views, click-thru\n"; |
pierre@1
|
353 } |
pierre@1
|
354 else { |
pierre@1
|
355 $output = '<div class="describe">' . t('There !count matching your parameters.', array('!count' => format_plural(sizeof($ads), 'was 1 active ad', 'were @count active ads'))) . '</div>'; |
pierre@1
|
356 |
pierre@1
|
357 $headers = array(t('Advertisement'), t('Active dates'), t('Views'), t('Clicks'), t('Click-thru')); |
pierre@1
|
358 // get counts for each ad |
pierre@1
|
359 $rows = array(); |
pierre@1
|
360 } |
pierre@1
|
361 $total_views = $total_clicks = 0; |
pierre@1
|
362 foreach ($ads as $nid) { |
pierre@1
|
363 $ad = node_load($nid); |
pierre@1
|
364 if ($ad->nid) { |
pierre@1
|
365 $views = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'view' AND date >= %d AND date <= %d", $nid, $start, $end)); |
pierre@1
|
366 $first = _ad_report_get_date_from_path((int)db_result(db_query("SELECT MIN(date) FROM {ad_statistics} WHERE aid = %d AND action = 'view' AND date >= %d AND date <= %d", $nid, $start, $end))); |
pierre@1
|
367 $first = format_date($first, 'small'); |
pierre@1
|
368 $last = _ad_report_get_date_from_path((int)db_result(db_query("SELECT MAX(date) FROM {ad_statistics} WHERE aid = %d AND action = 'view' AND date >= %d AND date <= %d", $nid, $start, $end))); |
pierre@1
|
369 $last = format_date($last, 'small'); |
pierre@1
|
370 $clicks = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'click' AND date >= %d AND date <= %d", $nid, $start, $end)); |
pierre@1
|
371 if ($views) { |
pierre@1
|
372 $clickthru = number_format($clicks / $views, 2) .'%'; |
pierre@1
|
373 } |
pierre@1
|
374 else { |
pierre@1
|
375 $clickthru = '0%'; |
pierre@1
|
376 } |
pierre@1
|
377 if ($views || $clicks) { |
pierre@1
|
378 if ($csv) { |
pierre@1
|
379 echo "$ad->nid, $ad->title, $first, $last, $views, $clicks, $clickthru\n"; |
pierre@1
|
380 } |
pierre@1
|
381 else { |
pierre@1
|
382 $row = array(); |
pierre@1
|
383 $row[] = l($ad->title, "node/$ad->nid"); |
pierre@1
|
384 $row[] = "first view: $first<br />last view: $last"; |
pierre@1
|
385 $row[] = number_format($views); |
pierre@1
|
386 $row[] = number_format($clicks); |
pierre@1
|
387 $row[] = $clickthru; |
pierre@1
|
388 $rows[] = $row; |
pierre@1
|
389 $total_views += $views; |
pierre@1
|
390 $total_clicks += $clicks; |
pierre@1
|
391 } |
pierre@1
|
392 } |
pierre@1
|
393 } |
pierre@1
|
394 } |
pierre@1
|
395 if ($csv) { |
pierre@1
|
396 return (0); |
pierre@1
|
397 } |
pierre@1
|
398 if ($total_views || $total_clicks) { |
pierre@1
|
399 $row = array(); |
pierre@1
|
400 $row[] = '<strong>'. t('Total') .'</strong>'; |
pierre@1
|
401 $row[] = ''; |
pierre@1
|
402 $row[] = '<strong>'. number_format($total_views) .'</strong>'; |
pierre@1
|
403 $row[] = '<strong>'. number_format($total_clicks) .'</strong>'; |
pierre@1
|
404 if ($total_views) { |
pierre@1
|
405 $row[] = '<strong>'. number_format($total_clicks / $total_views, 2) .'%' .'</strong>'; |
pierre@1
|
406 } |
pierre@1
|
407 else { |
pierre@1
|
408 $row[] = '<strong>'. '0%' .'</strong>'; |
pierre@1
|
409 } |
pierre@1
|
410 $rows[] = $row; |
pierre@1
|
411 } |
pierre@1
|
412 $output .= theme('table', $headers, $rows); |
pierre@1
|
413 $output .= l(t('Download CSV'), 'admin/content/ad/report/csv'); |
pierre@1
|
414 return $output; |
pierre@1
|
415 } |
pierre@1
|
416 |
pierre@1
|
417 /** |
pierre@1
|
418 * Returns a timestamp for the first hour of the first day of the month. |
pierre@1
|
419 */ |
pierre@1
|
420 function _ad_report_first_day_of_month($time = NULL) { |
pierre@1
|
421 if ($time === NULL) { |
pierre@1
|
422 $time = time(); |
pierre@1
|
423 } |
pierre@1
|
424 return strtotime(date('Ym010000', $time)); |
pierre@1
|
425 } |
pierre@1
|
426 |
pierre@1
|
427 /** |
pierre@1
|
428 * Returns a timestamp for the last hour of the last day of the month. |
pierre@1
|
429 */ |
pierre@1
|
430 function _ad_report_last_day_of_month($time = NULL) { |
pierre@1
|
431 if ($time === NULL) { |
pierre@1
|
432 $time = time(); |
pierre@1
|
433 } |
pierre@1
|
434 $month = date('m', $time); |
pierre@1
|
435 $year = date('Y', $time); |
pierre@1
|
436 $day = date('d', mktime(0, 0, 0, ($month + 1), 0, $year)); |
pierre@1
|
437 return strtotime("{$year}{$month}{$day}2359"); |
pierre@1
|
438 } |
pierre@1
|
439 |
pierre@0
|
440 /** |
pierre@0
|
441 * Page to display ad with bargraph. |
pierre@0
|
442 */ |
pierre@1
|
443 function ad_report_bargraph($data, $url, $type = 'node', $start = 0, $end = 0) { |
pierre@1
|
444 if ($type == 'node') { |
pierre@1
|
445 drupal_set_title($data->title); |
pierre@0
|
446 } |
pierre@1
|
447 $start_date = _ad_report_get_date_from_path($start); |
pierre@1
|
448 $end_date = _ad_report_get_date_from_path($end); |
pierre@1
|
449 $output = drupal_get_form('ad_report_range_form', $type, $url, $start_date, $end_date); |
pierre@1
|
450 if ($start && $end) { |
pierre@1
|
451 switch ($type) { |
pierre@1
|
452 case 'node': |
pierre@1
|
453 $ad = db_fetch_object(db_query('SELECT aid, redirect, adtype FROM {ads} WHERE aid = %d', $data->nid)); |
pierre@1
|
454 if ($ad->aid) { |
pierre@1
|
455 $output .= '<img src="'. url("ad_report/$data->nid/bargraph/node/$start/$end") .'" />'; |
pierre@1
|
456 $output .= theme('box', '', module_invoke("ad_$data->adtype", 'display_ad', $ad)); |
pierre@1
|
457 $output .= ad_report_group_table($data->nid, $type, $start, $end); |
pierre@1
|
458 } |
pierre@1
|
459 $output .= module_invoke('ad', 'click_history', $data->nid); |
pierre@1
|
460 break; |
pierre@1
|
461 default: |
pierre@1
|
462 $output = '<img src="'. url("ad_report/$data->uid/bargraph/$granularity/$type") .'" />'; |
pierre@1
|
463 break; |
pierre@1
|
464 } |
pierre@0
|
465 } |
pierre@0
|
466 return $output; |
pierre@0
|
467 } |
pierre@0
|
468 |
pierre@0
|
469 /** |
pierre@1
|
470 * Return a form for selecting a date range for generating a report. |
pierre@1
|
471 */ |
pierre@1
|
472 function ad_report_range_form($form_state, $type, $url = NULL, $start = NULL, $end = NULL) { |
pierre@1
|
473 $form = array(); |
pierre@1
|
474 |
pierre@1
|
475 $start = $start ? $start : _ad_report_first_day_of_month(); |
pierre@1
|
476 $end = $end ? $end : _ad_report_last_day_of_month(); |
pierre@1
|
477 |
pierre@1
|
478 $form['report'] = array( |
pierre@1
|
479 '#type' => 'fieldset', |
pierre@1
|
480 '#title' => t('Report dates'), |
pierre@1
|
481 '#prefix' => '<div class="container-inline">', |
pierre@1
|
482 '#suffix' => '</div>', |
pierre@1
|
483 ); |
pierre@1
|
484 $form['report']['type'] = array( |
pierre@1
|
485 '#value' => $type, |
pierre@1
|
486 '#type' => 'hidden', |
pierre@1
|
487 ); |
pierre@1
|
488 $form['report']['url'] = array( |
pierre@1
|
489 '#value' => $url, |
pierre@1
|
490 '#type' => 'hidden', |
pierre@1
|
491 ); |
pierre@1
|
492 $form['report']['start'] = array( |
pierre@1
|
493 '#type' => 'textfield', |
pierre@1
|
494 '#title' => t('Start'), |
pierre@1
|
495 '#size' => 24, |
pierre@1
|
496 '#maxlength' => 64, |
pierre@1
|
497 '#default_value' => _ad_report_format_date_human($start), |
pierre@1
|
498 // display pop up calendar if jstools jscalendar module enabled |
pierre@1
|
499 '#attributes' => array('class' => 'jscalendar'), |
pierre@1
|
500 '#jscalendar_ifFormat' => '%Y-%m-%d %H:%M', |
pierre@1
|
501 '#jscalendar_timeFormat' => '24', |
pierre@1
|
502 ); |
pierre@1
|
503 $form['report']['space1'] = array( |
pierre@1
|
504 '#value' => ' ', |
pierre@1
|
505 ); |
pierre@1
|
506 $form['report']['end'] = array( |
pierre@1
|
507 '#type' => 'textfield', |
pierre@1
|
508 '#title' => t('End'), |
pierre@1
|
509 '#size' => 24, |
pierre@1
|
510 '#maxlength' => 64, |
pierre@1
|
511 '#default_value' => _ad_report_format_date_human($end), |
pierre@1
|
512 // display pop up calendar if jstools jscalendar module enabled |
pierre@1
|
513 '#attributes' => array('class' => 'jscalendar'), |
pierre@1
|
514 '#jscalendar_ifFormat' => '%Y-%m-%d %H:%M', |
pierre@1
|
515 ); |
pierre@1
|
516 $form['report']['space2'] = array( |
pierre@1
|
517 '#value' => ' ', |
pierre@1
|
518 ); |
pierre@1
|
519 $form['report']['generate'] = array( |
pierre@1
|
520 '#type' => 'submit', |
pierre@1
|
521 '#value' => t('Generate report'), |
pierre@1
|
522 ); |
pierre@1
|
523 |
pierre@1
|
524 return $form; |
pierre@1
|
525 } |
pierre@1
|
526 |
pierre@1
|
527 /** |
pierre@1
|
528 * Validate the form range. |
pierre@1
|
529 */ |
pierre@1
|
530 function ad_report_range_form_validate($form, $form_state) { |
pierre@1
|
531 $start = isset($form_state['values']['start']) ? strtotime($form_state['values']['start']) : 0; |
pierre@1
|
532 $end = isset($form_state['values']['start']) ? strtotime($form_state['values']['end']) : 0; |
pierre@1
|
533 if (!$start) { |
pierre@1
|
534 form_set_error('start', t('You must enter a valid start date.')); |
pierre@1
|
535 } |
pierre@1
|
536 else if ($start >= (time() - 3600)) { |
pierre@1
|
537 form_set_error('start', t('The report must start at least one hour before the current time.')); |
pierre@1
|
538 } |
pierre@1
|
539 else if ($start >= $end) { |
pierre@1
|
540 form_set_error('start', t('The report must start before it ends.')); |
pierre@1
|
541 } |
pierre@1
|
542 if (!$end) { |
pierre@1
|
543 form_set_error('end', t('You must enter a valid end date.')); |
pierre@1
|
544 } |
pierre@1
|
545 } |
pierre@1
|
546 |
pierre@1
|
547 /** |
pierre@1
|
548 * Redirect to URL for displaying report. |
pierre@1
|
549 */ |
pierre@1
|
550 function ad_report_range_form_submit($form, $form_state) { |
pierre@1
|
551 $start = date('YmdHi', strtotime($form_state['values']['start'])); |
pierre@1
|
552 $end = date('YmdHi', strtotime($form_state['values']['end'])); |
pierre@1
|
553 drupal_goto($form_state['values']['url'] ."/$start/$end"); |
pierre@1
|
554 } |
pierre@1
|
555 |
pierre@1
|
556 /** |
pierre@1
|
557 * Helper function to extract date from URL. |
pierre@1
|
558 */ |
pierre@1
|
559 function _ad_report_get_date_from_path($path) { |
pierre@1
|
560 if (isset($path) && $path) { |
pierre@1
|
561 $year = substr($path, 0, 4); |
pierre@1
|
562 $month = substr($path, 4, 2); |
pierre@1
|
563 $day = substr($path, 6, 2); |
pierre@1
|
564 $hour = substr($path, 8, 2); |
pierre@1
|
565 if (strlen($path) == 12) { |
pierre@1
|
566 $minute = substr($path, 10, 2); |
pierre@1
|
567 } |
pierre@1
|
568 else { |
pierre@1
|
569 $minute = 0; |
pierre@1
|
570 } |
pierre@1
|
571 $date = strtotime("$month/$day/$year $hour:$minute"); |
pierre@1
|
572 if ($date > 0) { |
pierre@1
|
573 return $date; |
pierre@1
|
574 } |
pierre@1
|
575 drupal_set_message(t('Invalid date specified in range.'), 'error'); |
pierre@1
|
576 } |
pierre@1
|
577 } |
pierre@1
|
578 |
pierre@1
|
579 /** |
pierre@1
|
580 * Helper function to format date. |
pierre@1
|
581 */ |
pierre@1
|
582 function _ad_report_format_date_human($date) { |
pierre@1
|
583 return date('Y-m-d H:i', $date); |
pierre@1
|
584 } |
pierre@1
|
585 |
pierre@1
|
586 /** |
pierre@1
|
587 * Helper function to format date. |
pierre@1
|
588 */ |
pierre@1
|
589 function _ad_report_format_date_db($date) { |
pierre@1
|
590 return date('YmdH', $date); |
pierre@1
|
591 } |
pierre@1
|
592 |
pierre@1
|
593 /** |
pierre@1
|
594 * Display table with per-group statistics. |
pierre@1
|
595 */ |
pierre@1
|
596 function ad_report_group_table($id, $type, $start, $end) { |
pierre@1
|
597 $start_date = _ad_report_format_date_db(_ad_report_get_date_from_path($start)); |
pierre@1
|
598 $end_date = _ad_report_format_date_db(_ad_report_get_date_from_path($end)); |
pierre@1
|
599 // TODO: Support other types than nodes |
pierre@1
|
600 $result = db_query('SELECT DISTINCT(adgroup) FROM {ad_statistics} WHERE aid = %d AND date >= %d AND date <= %d', $id, $start_date, $end_date); |
pierre@1
|
601 // extract all groups that this advertisement has been displayed in |
pierre@1
|
602 while ($group = db_fetch_object($result)) { |
pierre@1
|
603 if ($group->adgroup) { |
pierre@1
|
604 $first = substr($group->adgroup, 0, 1); |
pierre@1
|
605 if ($first == 't') { |
pierre@1
|
606 $tids = $tids = explode(',', substr($group->adgroup, 1, strlen($group->adgroup))); |
pierre@1
|
607 foreach ($tids as $tid) { |
pierre@1
|
608 if ($tid) { |
pierre@1
|
609 $adgroups[$tid][] = $group->adgroup; |
pierre@1
|
610 } |
pierre@1
|
611 } |
pierre@1
|
612 } |
pierre@1
|
613 else { |
pierre@1
|
614 // handle this type of "group" |
pierre@1
|
615 $adgroups['other'][] = $group->adgroup; |
pierre@1
|
616 } |
pierre@1
|
617 } |
pierre@1
|
618 else { |
pierre@1
|
619 $adgroups[0][] = $group->adgroup; |
pierre@1
|
620 } |
pierre@1
|
621 } |
pierre@1
|
622 $headers = array(t('Group'), t('Active dates'), t('Views'), t('Clicks'), t('Click-thru')); |
pierre@1
|
623 // get counts for each group |
pierre@1
|
624 $groups = ad_groups_list(); |
pierre@1
|
625 $rows = array(); |
pierre@1
|
626 $total_views = $total_clicks = 0; |
pierre@1
|
627 foreach ($groups as $tid => $group) { |
pierre@1
|
628 $views = $clicks = 0; |
pierre@1
|
629 if (isset($adgroups[$tid]) && is_array($adgroups[$tid])) { |
pierre@1
|
630 foreach ($adgroups[$tid] as $adgroup) { |
pierre@1
|
631 $views += (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND adgroup = '%s' AND action = 'view' AND date >= %d AND date <= %d", $id, $adgroup, $start_date, $end_date)); |
pierre@1
|
632 $clicks += (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND adgroup = '%s' AND action = 'click' AND date >= %d AND date <= %d", $id, $adgroup, $start_date, $end_date)); |
pierre@1
|
633 } |
pierre@1
|
634 } |
pierre@1
|
635 if ($views || $clicks) { |
pierre@1
|
636 $begin = (int)db_result(db_query("SELECT MIN(date) FROM {ad_statistics} WHERE (adgroup LIKE '%%t%s' OR adgroup LIKE '%%,%s') AND action = 'view' AND date >= %d AND date <= %d", $tid, $tid, $start_date, $end_date)); |
pierre@1
|
637 if ($begin) { |
pierre@1
|
638 $begin = format_date(_ad_report_get_date_from_path($begin), 'small'); |
pierre@1
|
639 $finish = (int)db_result(db_query("SELECT MAX(date) FROM {ad_statistics} WHERE (adgroup LIKE '%%t%s' OR adgroup LIKE '%%,%s') AND action = 'view' AND date >= %d AND date <= %d", $tid, $tid, $start_date, $end_date)); |
pierre@1
|
640 if ($finish) { |
pierre@1
|
641 $finish = format_date(_ad_report_get_date_from_path($finish), 'small'); |
pierre@1
|
642 } |
pierre@1
|
643 } |
pierre@1
|
644 if ($begin && $finish) { |
pierre@1
|
645 $row = array(); |
pierre@1
|
646 $row[] = $group; |
pierre@1
|
647 $row[] = "first view: $begin<br />last view: $finish"; |
pierre@1
|
648 $row[] = number_format($views); |
pierre@1
|
649 $row[] = number_format($clicks); |
pierre@1
|
650 if ($views) { |
pierre@1
|
651 $row[] = number_format($clicks / $views, 2) .'%'; |
pierre@1
|
652 } |
pierre@1
|
653 else { |
pierre@1
|
654 $row[] = '0%'; |
pierre@1
|
655 } |
pierre@1
|
656 $rows[] = $row; |
pierre@1
|
657 $total_views += $views; |
pierre@1
|
658 $total_clicks += $clicks; |
pierre@1
|
659 } |
pierre@1
|
660 } |
pierre@1
|
661 } |
pierre@1
|
662 if ($total_views || $total_clicks) { |
pierre@1
|
663 $row = array(); |
pierre@1
|
664 $row[] = '<strong>'. t('Total') .'</strong>'; |
pierre@1
|
665 $row[] = ''; |
pierre@1
|
666 $row[] = '<strong>'. number_format($total_views) .'</strong>'; |
pierre@1
|
667 $row[] = '<strong>'. number_format($total_clicks) .'</strong>'; |
pierre@1
|
668 if ($total_views) { |
pierre@1
|
669 $row[] = '<strong>'. number_format($total_clicks / $total_views, 2) .'%' .'</strong>'; |
pierre@1
|
670 } |
pierre@1
|
671 else { |
pierre@1
|
672 $row[] = '<strong>'. '0%' .'</strong>'; |
pierre@1
|
673 } |
pierre@1
|
674 $rows[] = $row; |
pierre@1
|
675 } |
pierre@1
|
676 |
pierre@1
|
677 return theme('table', $headers, $rows); |
pierre@1
|
678 } |
pierre@1
|
679 |
pierre@1
|
680 /** |
pierre@0
|
681 * Page that utilizes gd to generate a bargraph. |
pierre@0
|
682 */ |
pierre@1
|
683 function ad_report_generate_bargraph($id, $type, $start, $end) { |
pierre@0
|
684 header("Content-type: image/png"); |
pierre@0
|
685 |
pierre@1
|
686 if ($type == 'node' && is_object($id)) { |
pierre@1
|
687 $id = $id->nid; |
pierre@1
|
688 } |
pierre@1
|
689 $start = _ad_report_get_date_from_path($start); |
pierre@1
|
690 $end = _ad_report_get_date_from_path($end); |
pierre@1
|
691 |
pierre@1
|
692 // be sure we've been passed in valid parameters |
pierre@1
|
693 $elapse = $end - $start; |
pierre@1
|
694 if ($elapse <= 0 || $start <= 0 || $end <= 0) { |
pierre@1
|
695 return NULL; |
pierre@1
|
696 } |
pierre@1
|
697 $increments = (int)($elapse / 3600); |
pierre@1
|
698 |
pierre@1
|
699 // image size |
pierre@1
|
700 $image_width = 700; |
pierre@1
|
701 $image_height = 360; |
pierre@1
|
702 |
pierre@1
|
703 // graph size |
pierre@1
|
704 $graph_width = 600; |
pierre@1
|
705 $graph_height = 250; |
pierre@1
|
706 $graph_x_offset = 8; |
pierre@1
|
707 $graph_y_offset = 8; |
pierre@1
|
708 $graph_y = 8; |
pierre@1
|
709 |
pierre@1
|
710 // calculate slices to extract from database |
pierre@1
|
711 $width = $graph_width / $increments; |
pierre@1
|
712 $number = $increments; |
pierre@1
|
713 $factor = 1; |
pierre@1
|
714 if ($width < 1) { |
pierre@1
|
715 $factor = 1 / $width; |
pierre@1
|
716 } |
pierre@1
|
717 $number = $number / $factor; |
pierre@1
|
718 $width = $width * $factor; |
pierre@1
|
719 $slice = $elapse / $number; |
pierre@1
|
720 |
pierre@1
|
721 // retrieve views and clicks from the database |
pierre@0
|
722 $views = array(); |
pierre@1
|
723 $clicks = array(); |
pierre@0
|
724 $max_views = 0; |
pierre@0
|
725 $max_clicks = 0; |
pierre@1
|
726 $key = 0; |
pierre@1
|
727 for ($i = $start; $i < $end; $i += $slice) { |
pierre@1
|
728 $start_date = _ad_report_format_date_db($i); |
pierre@1
|
729 $end_date = _ad_report_format_date_db($i + $slice); |
pierre@1
|
730 switch ($type) { |
pierre@1
|
731 case 'node': |
pierre@1
|
732 $views[] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'view' AND date >= %d AND date <= %d", $id, $start_date, $end_date)); |
pierre@1
|
733 $clicks[] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'click' AND date >= %d AND date <= %d", $id, $start_date, $end_date)); |
pierre@1
|
734 break; |
pierre@1
|
735 case 'user': |
pierre@1
|
736 $views[] = (int)db_result(db_query("SELECT SUM(a.count) FROM {ad_statistics} a LEFT JOIN {node} n ON a.aid = n.nid WHERE n.uid = %d AND n.type = 'ad' AND a.action = 'view' AND a.date >= %d AND a.date <= %d", $id, $start_date, $end_date)); |
pierre@1
|
737 $clicks[] = (int)db_result(db_query("SELECT SUM(a.count) FROM {ad_statistics} a LEFT JOIN {node} n ON a.aid = n.nid WHERE n.uid = %d AND n.type = 'ad' AND a.action = 'click' AND a.date >= %d AND a.date <= %d", $id, $start_date, $end_date)); |
pierre@1
|
738 break; |
pierre@1
|
739 case 'admin': |
pierre@1
|
740 $group = $_SESSION['ad_report_group']; |
pierre@1
|
741 $all = FALSE; |
pierre@1
|
742 $none = FALSE; |
pierre@1
|
743 if (is_array($group)) { |
pierre@1
|
744 if (in_array('all', $group)) { |
pierre@1
|
745 $all = TRUE; |
pierre@1
|
746 } |
pierre@1
|
747 if (!$all) { |
pierre@1
|
748 $groups = ad_groups_list(); |
pierre@1
|
749 if (sizeof($group) == sizeof($groups)) { |
pierre@1
|
750 $all = TRUE; |
pierre@1
|
751 } |
pierre@1
|
752 } |
pierre@1
|
753 if (in_array('0', $group)) { |
pierre@1
|
754 unset($group[0]); |
pierre@1
|
755 $none = TRUE; |
pierre@1
|
756 } |
pierre@1
|
757 } |
pierre@1
|
758 if ($all) { |
pierre@1
|
759 $views[] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE action = 'view' AND date >= %d AND date <= %d", $start_date, $end_date)); |
pierre@1
|
760 $clicks[] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE action = 'click' AND date >= %d AND date <= %d", $start_date, $end_date)); |
pierre@1
|
761 } |
pierre@1
|
762 else if ($none) { |
pierre@1
|
763 if (sizeof($group)) { |
pierre@1
|
764 $views[] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} a LEFT JOIN {term_node} t ON a.aid = t.tid WHERE (t.tid IN (%s) OR ISNULL(t.tid)) AND action = 'view' AND date >= %d AND date <= %d", implode(',', $group), $start_date, $end_date)); |
pierre@1
|
765 $clicks[] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} a LEFT JOIN {term_node} t ON a.aid = t.tid WHERE (t.tid IN (%s) OR ISNULL(t.tid)) AND action = 'click' AND date >= %d AND date <= %d", implode(',', $group), $start_date, $end_date)); |
pierre@1
|
766 } |
pierre@1
|
767 else { |
pierre@1
|
768 $views[] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} a LEFT JOIN {term_node} t ON a.aid = t.tid WHERE ISNULL(t.tid) AND action = 'view' AND date >= %d AND date <= %d", $start_date, $end_date)); |
pierre@1
|
769 $clicks[] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} a LEFT JOIN {term_node} t ON a.aid = t.tid WHERE ISNULL(t.tid) AND action = 'click' AND date >= %d AND date <= %d", $start_date, $end_date)); |
pierre@1
|
770 } |
pierre@1
|
771 } |
pierre@1
|
772 else { |
pierre@1
|
773 $views[] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} a LEFT JOIN {term_node} t ON a.aid = t.tid WHERE tid IN (%s) AND action = 'view' AND date >= %d AND date <= %d", implode(',', $group), $start_date, $end_date)); |
pierre@1
|
774 $clicks[] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} a LEFT JOIN {term_node} t ON a.aid = t.tid WHERE t.tid IN (%s) AND action = 'click' AND date >= %d AND date <= %d", implode(',', $group), $start_date, $end_date)); |
pierre@1
|
775 } |
pierre@1
|
776 break; |
pierre@1
|
777 default: |
pierre@1
|
778 $function = "ad_report_views_$type"; |
pierre@1
|
779 if (function_exists("$function")) { |
pierre@1
|
780 $views[] = $function($id, $day_start, $day_end); |
pierre@1
|
781 } |
pierre@1
|
782 $function = "ad_report_clicks_$type"; |
pierre@1
|
783 if (function_exists("$function")) { |
pierre@1
|
784 $clicks[] = $function($id, $day_start, $day_end); |
pierre@1
|
785 } |
pierre@1
|
786 break; |
pierre@1
|
787 } |
pierre@1
|
788 $max_views = $views[$key] > $max_views ? $views[$key] : $max_views; |
pierre@1
|
789 $max_clicks = $clicks[$key] > $max_clicks ? $clicks[$key] : $max_clicks; |
pierre@1
|
790 $key++; |
pierre@0
|
791 } |
pierre@0
|
792 |
pierre@1
|
793 // create graph |
pierre@0
|
794 $graph = imagecreate($image_width, $image_height); |
pierre@0
|
795 |
pierre@1
|
796 // configure colors to use in chart |
pierre@0
|
797 $color = array( |
pierre@0
|
798 'white' => imagecolorallocate($graph, 255, 255, 255), |
pierre@0
|
799 'black' => imagecolorallocate($graph, 0, 0, 0), |
pierre@0
|
800 'grey' => imagecolorallocate($graph, 192, 192, 192), |
pierre@0
|
801 'blue' => imagecolorallocate($graph, 0, 0, 255), |
pierre@0
|
802 'orange' => imagecolorallocate($graph, 220, 210, 60), |
pierre@1
|
803 'red' => imagecolorallocate($graph, 255, 0, 0), |
pierre@0
|
804 ); |
pierre@0
|
805 |
pierre@1
|
806 // determine how big the spacers should be |
pierre@1
|
807 $max = $max_views > $max_clicks ? $max_views : $max_clicks; |
pierre@1
|
808 $y_map = ceil($max / $graph_y / $graph_y) * $graph_y; |
pierre@1
|
809 $y_total = $y_map * $graph_y; |
pierre@0
|
810 |
pierre@1
|
811 if ($y_total) { |
pierre@1
|
812 // plot views and clicks on graph |
pierre@1
|
813 foreach ($views as $key => $value) { |
pierre@1
|
814 $view_height = $graph_height / $y_total * $value; |
pierre@1
|
815 if ($view_height) { |
pierre@1
|
816 imagefilledrectangle($graph, $graph_x_offset + $key * $width, $graph_y_offset + $graph_height - $view_height, $graph_x_offset + ($key + 1) * $width - 1, $graph_y_offset + $graph_height - 1, $color['blue']); |
pierre@1
|
817 } |
pierre@1
|
818 $click_height = $graph_height / $y_total * $clicks[$key]; |
pierre@1
|
819 if ($click_height) { |
pierre@1
|
820 imagefilledrectangle($graph, $graph_x_offset + $key * $width, $graph_y_offset + $graph_height - $click_height, $graph_x_offset + ($key + 1) * $width - 1, $graph_y_offset + $graph_height - 1, $color['red']); |
pierre@1
|
821 } |
pierre@0
|
822 } |
pierre@0
|
823 } |
pierre@0
|
824 |
pierre@1
|
825 // add scale to y |
pierre@1
|
826 if ($y_map) { |
pierre@1
|
827 $graph_y_width = $graph_height / $graph_y; |
pierre@1
|
828 for ($i = 1; $i <= $graph_y; $i++) { |
pierre@1
|
829 $text = number_format($i * $y_map); |
pierre@1
|
830 $len = strlen($text); |
pierre@1
|
831 $x_offset = $graph_width + 14; |
pierre@1
|
832 $y_pos = $graph_height - $i * $graph_y_width; |
pierre@1
|
833 //imagestring($graph, 1, $x_offset, $graph_y_offset + $y_pos - 3, $text, $color['black']); |
pierre@1
|
834 imagestring($graph, 2, $x_offset, $graph_y_offset + $y_pos - 7, $text, $color['black']); |
pierre@0
|
835 } |
pierre@1
|
836 } |
pierre@1
|
837 else { |
pierre@1
|
838 $graph_y_width = 0; |
pierre@0
|
839 } |
pierre@0
|
840 |
pierre@1
|
841 // add scale to x |
pierre@1
|
842 $graph_x = _ad_report_select_x($number, 8, 0); |
pierre@1
|
843 $offset = $elapse / $graph_x; |
pierre@1
|
844 $graph_x_width = $graph_width / $graph_x; |
pierre@1
|
845 $x_offset = $graph_x_width / 2; |
pierre@1
|
846 for ($i = 1; $i <= $graph_x; $i++) { |
pierre@1
|
847 $text = date('M d, Y H', $start + ($offset * $i) - $offset / 2); |
pierre@1
|
848 $len = strlen($text); |
pierre@1
|
849 $x_pos = $graph_x_offset - $x_offset + $i * $graph_x_width - 7; |
pierre@1
|
850 $y_pos = $graph_height + $graph_y_offset + ($len * 6) + 3; |
pierre@1
|
851 imagestringup($graph, 2, $x_pos, $y_pos, $text, $color['black']); |
pierre@1
|
852 //$x_pos = $graph_x_offset - $x_offset + $i * $graph_x_width - 4; |
pierre@1
|
853 //$y_pos = $graph_height + $graph_y_offset + ($len * 5) + 3; |
pierre@1
|
854 //imagestringup($graph, 1, $x_pos, $y_pos, $text, $color['black']); |
pierre@1
|
855 } |
pierre@1
|
856 |
pierre@1
|
857 // draw a grid |
pierre@1
|
858 $style = array($color['grey'], IMG_COLOR_TRANSPARENT, IMG_COLOR_TRANSPARENT); |
pierre@1
|
859 imagesetstyle($graph, $style); |
pierre@1
|
860 for ($i = 1; $i <= $graph_x; $i++) { |
pierre@1
|
861 imageline($graph, $graph_x_offset + $i * $graph_x_width - $graph_x_width / 2, $graph_y_offset, $graph_x_offset + $i * $graph_x_width - $graph_x_width / 2, $graph_y_offset + $graph_height - 1, IMG_COLOR_STYLED); |
pierre@1
|
862 } |
pierre@1
|
863 for ($i = 1; $i < $graph_y; $i++) { |
pierre@1
|
864 imageline($graph, $graph_x_offset, $graph_y_offset + $i * $graph_y_width, $graph_x_offset + $graph_width, $graph_y_offset + $i * $graph_y_width, IMG_COLOR_STYLED); |
pierre@1
|
865 } |
pierre@1
|
866 // left, right, top, and bottom borders, respectively |
pierre@1
|
867 imageline($graph, $graph_x_offset, $graph_y_offset, $graph_x_offset, $graph_y_offset + $graph_height, $color['grey']); |
pierre@1
|
868 imageline($graph, $graph_x_offset + $graph_width - 1, $graph_y_offset, $graph_x_offset + $graph_width - 1, $graph_y_offset + $graph_height, $color['grey']); |
pierre@1
|
869 imageline($graph, $graph_x_offset, $graph_y_offset, $graph_x_offset + $graph_width - 1, $graph_y_offset, $color['grey']); |
pierre@1
|
870 imageline($graph, $graph_x_offset, $graph_y_offset + $graph_height, $graph_x_offset + $graph_width - 1, $graph_y_offset + $graph_height, $color['grey']); |
pierre@1
|
871 |
pierre@1
|
872 // display the graph |
pierre@1
|
873 imagepng($graph); |
pierre@1
|
874 imagedestroy($graph); |
pierre@1
|
875 } |
pierre@1
|
876 |
pierre@1
|
877 /** |
pierre@1
|
878 * Figure out how many x columns to display. |
pierre@1
|
879 * TODO: Find a better algorithm than this slop. |
pierre@1
|
880 */ |
pierre@1
|
881 function _ad_report_select_x($number, $divisor, $diff) { |
pierre@1
|
882 if ($divisor < 2) { |
pierre@1
|
883 return $number; |
pierre@1
|
884 } |
pierre@1
|
885 $divisor = $divisor + $diff; |
pierre@1
|
886 if ($divisor == 0) { |
pierre@1
|
887 $divisor = $divisor + $diff; |
pierre@1
|
888 } |
pierre@1
|
889 $result = (int)($number / $divisor); |
pierre@1
|
890 if ($result < 8) { |
pierre@1
|
891 $diff -= 1; |
pierre@1
|
892 if ($diff) { |
pierre@1
|
893 return _ad_report_select_x($number, $divisor, $diff); |
pierre@0
|
894 } |
pierre@0
|
895 } |
pierre@1
|
896 else if ($result > 12) { |
pierre@1
|
897 $diff += 1; |
pierre@1
|
898 if ($diff) { |
pierre@1
|
899 return _ad_report_select_x($number, $divisor, $diff); |
pierre@1
|
900 } |
pierre@1
|
901 } |
pierre@1
|
902 return $result; |
pierre@0
|
903 } |