pierre@0
|
1 <?php |
pierre@0
|
2 // $Id: ad_report.module,v 1.1.2.3.2.7.2.6 2009/02/16 23:12:29 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@0
|
8 * Copyright (c) 2005-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@0
|
17 |
pierre@0
|
18 $items['node/%node/report'] = array( |
pierre@0
|
19 'title' => 'Reports', |
pierre@0
|
20 'page callback' => 'ad_report_bargraph', |
pierre@0
|
21 'page arguments' => array(1), |
pierre@0
|
22 'type' => MENU_LOCAL_TASK, |
pierre@0
|
23 'access callback' => 'ad_report_access', |
pierre@0
|
24 'access arguments' => array(1), |
pierre@0
|
25 ); |
pierre@0
|
26 $items['node/%node/report/monthly'] = array( |
pierre@0
|
27 'title' => 'Monthly Reports', |
pierre@0
|
28 'page callback' => 'ad_report_bargraph', |
pierre@0
|
29 'page arguments' => array(1,3), |
pierre@0
|
30 'type' => MENU_LOCAL_TASK, |
pierre@0
|
31 'access callback' => 'ad_report_access', |
pierre@0
|
32 'access arguments' => array(1), |
pierre@0
|
33 ); |
pierre@0
|
34 $items['node/%node/report/weekly'] = array( |
pierre@0
|
35 'title' => 'Weekly Reports', |
pierre@0
|
36 'page callback' => 'ad_report_bargraph', |
pierre@0
|
37 'page arguments' => array(1,3), |
pierre@0
|
38 'type' => MENU_LOCAL_TASK, |
pierre@0
|
39 'access callback' => 'ad_report_access', |
pierre@0
|
40 'access arguments' => array(1), |
pierre@0
|
41 ); |
pierre@0
|
42 $items['node/%node/report/daily'] = array( |
pierre@0
|
43 'title' => 'Daily Reports', |
pierre@0
|
44 'page callback' => 'ad_report_bargraph', |
pierre@0
|
45 'page arguments' => array(1,3), |
pierre@0
|
46 'type' => MENU_DEFAULT_LOCAL_TASK, |
pierre@0
|
47 'access callback' => 'ad_report_access', |
pierre@0
|
48 'access arguments' => array(1), |
pierre@0
|
49 ); |
pierre@0
|
50 $items['node/%node/report/hourly'] = array( |
pierre@0
|
51 'title' => 'Hourly Reports', |
pierre@0
|
52 'page callback' => 'ad_report_bargraph', |
pierre@0
|
53 'page arguments' => array(1,3), |
pierre@0
|
54 'type' => MENU_LOCAL_TASK, |
pierre@0
|
55 'access callback' => 'ad_report_access', |
pierre@0
|
56 'access arguments' => array(1), |
pierre@0
|
57 ); |
pierre@0
|
58 $items['ad_report/%node/bargraph'] = array( |
pierre@0
|
59 'title' => 'Bar graph', |
pierre@0
|
60 'page callback' => 'ad_report_generate_bargraph', |
pierre@0
|
61 'page arguments' => array(1), |
pierre@0
|
62 'type' => MENU_CALLBACK, |
pierre@0
|
63 'access callback' => 'ad_report_access', |
pierre@0
|
64 'access arguments' => array(1), |
pierre@0
|
65 ); |
pierre@0
|
66 |
pierre@0
|
67 return $items; |
pierre@0
|
68 } |
pierre@0
|
69 /** |
pierre@0
|
70 * Implementation of access callback. |
pierre@0
|
71 * |
pierre@0
|
72 * @param mixed $node |
pierre@0
|
73 * Ad object. |
pierre@0
|
74 */ |
pierre@0
|
75 function ad_report_access($node){ |
pierre@0
|
76 return ($node->type == 'ad') && ad_adaccess($node, 'access statistics'); |
pierre@0
|
77 } |
pierre@0
|
78 /** |
pierre@0
|
79 * Page to display ad with bargraph. |
pierre@0
|
80 */ |
pierre@0
|
81 function ad_report_bargraph($node, $granularity = 'daily', $type = 'node') { |
pierre@0
|
82 switch ($granularity) { |
pierre@0
|
83 case 'hourly': |
pierre@0
|
84 drupal_set_title(t('Past twelve hours')); |
pierre@0
|
85 break; |
pierre@0
|
86 case 'daily': |
pierre@0
|
87 drupal_set_title(t('Past twelve days')); |
pierre@0
|
88 break; |
pierre@0
|
89 case 'weekly': |
pierre@0
|
90 drupal_set_title(t('Past twelve weeks')); |
pierre@0
|
91 break; |
pierre@0
|
92 case 'monthly': |
pierre@0
|
93 drupal_set_title(t('Past twelve months')); |
pierre@0
|
94 break; |
pierre@0
|
95 } |
pierre@0
|
96 |
pierre@0
|
97 switch ($type) { |
pierre@0
|
98 case 'node': |
pierre@0
|
99 if ($node->aid) { |
pierre@0
|
100 $output = '<img src="'. url("ad_report/$node->nid/bargraph/$granularity/node") .'" />'; |
pierre@0
|
101 $ad_link = module_invoke('ad_' . $node->adtype, 'display_ad', $node); |
pierre@0
|
102 $output .= theme('box', $node->title, $ad_link); |
pierre@0
|
103 } |
pierre@0
|
104 break; |
pierre@0
|
105 default: |
pierre@0
|
106 $output = '<img src="'. url("ad_report/$node->uid/bargraph/$granularity/$type") .'" />'; |
pierre@0
|
107 break; |
pierre@0
|
108 } |
pierre@0
|
109 return $output; |
pierre@0
|
110 } |
pierre@0
|
111 |
pierre@0
|
112 /** |
pierre@0
|
113 * Page that utilizes gd to generate a bargraph. |
pierre@0
|
114 * |
pierre@0
|
115 * TODO: Make this more dynamic, allowing to move through time, etc. |
pierre@0
|
116 */ |
pierre@0
|
117 function ad_report_generate_bargraph($node, $granularity = 'daily', $type = 'node') { |
pierre@0
|
118 $id = $node->nid; |
pierre@0
|
119 header("Content-type: image/png"); |
pierre@0
|
120 |
pierre@0
|
121 // Preperation. |
pierre@0
|
122 $views = array(); |
pierre@0
|
123 $max_views = 0; |
pierre@0
|
124 $statistics = array(); |
pierre@0
|
125 $clicks = array(); |
pierre@0
|
126 $max_clicks = 0; |
pierre@0
|
127 $time = time(); |
pierre@0
|
128 |
pierre@0
|
129 $increments = 12; |
pierre@0
|
130 $end_add = 0; |
pierre@0
|
131 switch ($granularity) { |
pierre@0
|
132 case 'hourly': |
pierre@0
|
133 $start_time = (60 * 60 * 11); |
pierre@0
|
134 // Increment hourly. |
pierre@0
|
135 $increment_time = (60 * 60); |
pierre@0
|
136 |
pierre@0
|
137 $format_start = 'YmdH'; |
pierre@0
|
138 $format_end = 'YmdH'; |
pierre@0
|
139 $format_end_append = ''; |
pierre@0
|
140 $format_upper = 'M d'; |
pierre@0
|
141 $format_lower = 'ga'; |
pierre@0
|
142 $graph_height = 250; |
pierre@0
|
143 break; |
pierre@0
|
144 case 'daily': |
pierre@0
|
145 default: |
pierre@0
|
146 $start_time = (60 * 60 * 24 * 11); |
pierre@0
|
147 // Increment daily. |
pierre@0
|
148 $increment_time = (60 * 60 * 24); |
pierre@0
|
149 |
pierre@0
|
150 $format_start = 'Ymd00'; |
pierre@0
|
151 $format_end = 'Ymd'; |
pierre@0
|
152 $format_end_append = '24'; |
pierre@0
|
153 $format_upper = 'D'; |
pierre@0
|
154 $format_lower = 'M d'; |
pierre@0
|
155 break; |
pierre@0
|
156 case 'weekly': |
pierre@0
|
157 $start_time = (60 * 60 * 24 * 7 * 11); |
pierre@0
|
158 // Increment weekly. |
pierre@0
|
159 $increment_time = (60 * 60 * 24 * 7); |
pierre@0
|
160 |
pierre@0
|
161 $format_start = 'Ymd00'; |
pierre@0
|
162 $format_end = 'Ymd'; |
pierre@0
|
163 $format_end_append = '24'; |
pierre@0
|
164 $end_add = (60 * 60 * 24 * 6); |
pierre@0
|
165 //$end_add = 600; |
pierre@0
|
166 $format_upper = 'M d -'; |
pierre@0
|
167 $format_lower = ''; |
pierre@0
|
168 break; |
pierre@0
|
169 case 'monthly': |
pierre@0
|
170 $start_time = ((60 * 60 * 24 * 2) + (60 * 60 * 24 * 7 * 4)) * 11; |
pierre@0
|
171 // Increment monthly (every 30 days). |
pierre@0
|
172 $increment_time = (60 * 60 * 24 * 2) + (60 * 60 * 24 * 7 * 4); |
pierre@0
|
173 |
pierre@0
|
174 $format_start = 'Ymd00'; |
pierre@0
|
175 $format_end = 'Ymd'; |
pierre@0
|
176 $format_end_append = '24'; |
pierre@0
|
177 $end_add = (60 * 60 * 24 * 29); |
pierre@0
|
178 $format_upper = 'M d -'; |
pierre@0
|
179 $format_lower = ''; |
pierre@0
|
180 break; |
pierre@0
|
181 } |
pierre@0
|
182 |
pierre@0
|
183 // Retrive data from database. |
pierre@0
|
184 for ($i = $time - $start_time; $i <= $time; $i = $i + $increment_time) { |
pierre@0
|
185 $day_start = date($format_start, $i); |
pierre@0
|
186 $day_end = date($format_end, $i + $end_add). $format_end_append; |
pierre@0
|
187 if ($type == 'node') { |
pierre@0
|
188 $view = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'view' AND date >= %d AND date <= %d", $id, $day_start, $day_end)); |
pierre@0
|
189 $click = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'click' AND date >= %d AND date <= %d", $id, $day_start, $day_end)); |
pierre@0
|
190 } |
pierre@0
|
191 else if ($type == 'user') { |
pierre@0
|
192 $view = (int)db_result(db_query("SELECT SUM(a.count) FROM {ad_statistics} a LEFT JOIN {node} n ON a.aid = n.nid WHERE uid = %d AND type = 'ad' AND (action = 'view' OR action = 'count') AND date >= %d AND date <= %d", $id, $day_start, $day_end)); |
pierre@0
|
193 $click = (int)db_result(db_query("SELECT SUM(a.count) FROM {ad_statistics} a LEFT JOIN {node} n ON a.aid = n.nid WHERE uid = %d AND type = 'ad' AND action = 'click' AND date >= %d AND date <= %d", $id, $day_start, $day_end)); |
pierre@0
|
194 } |
pierre@0
|
195 else { |
pierre@0
|
196 $function = "ad_report_views_$type"; |
pierre@0
|
197 if (function_exists("$function")) { |
pierre@0
|
198 $view = $function($id, $day_start, $day_end); |
pierre@0
|
199 } |
pierre@0
|
200 $function = "ad_report_clicks_$type"; |
pierre@0
|
201 if (function_exists("$function")) { |
pierre@0
|
202 $click = $function($id, $day_start, $day_end); |
pierre@0
|
203 } |
pierre@0
|
204 } |
pierre@0
|
205 if ($view > $max_views) { |
pierre@0
|
206 $max_views = $view; |
pierre@0
|
207 } |
pierre@0
|
208 $statistics[] = array( |
pierre@0
|
209 'upper' => date($format_upper, $i), |
pierre@0
|
210 'lower' => date($format_lower, $i), |
pierre@0
|
211 'views' => $view, |
pierre@0
|
212 'clicks' => $click |
pierre@0
|
213 ); |
pierre@0
|
214 } |
pierre@0
|
215 |
pierre@0
|
216 // Build graph image. |
pierre@0
|
217 $image_width = 50 * $increments + 1; |
pierre@0
|
218 $image_height = 300; |
pierre@0
|
219 $graph_width = 50 * $increments; |
pierre@0
|
220 $graph_height = 250; |
pierre@0
|
221 |
pierre@0
|
222 $graph = imagecreate($image_width, $image_height); |
pierre@0
|
223 |
pierre@0
|
224 // Configure colors to use in chart. |
pierre@0
|
225 $color = array( |
pierre@0
|
226 'white' => imagecolorallocate($graph, 255, 255, 255), |
pierre@0
|
227 'black' => imagecolorallocate($graph, 0, 0, 0), |
pierre@0
|
228 'grey' => imagecolorallocate($graph, 192, 192, 192), |
pierre@0
|
229 'blue' => imagecolorallocate($graph, 0, 0, 255), |
pierre@0
|
230 'orange' => imagecolorallocate($graph, 220, 210, 60), |
pierre@0
|
231 ); |
pierre@0
|
232 |
pierre@0
|
233 // Draw the outside edges of the graph. |
pierre@0
|
234 imageline($graph, 0, 0, 0, $graph_height, $color['grey']); |
pierre@0
|
235 imageline($graph, 0, 0, $graph_width, 0, $color['grey']); |
pierre@0
|
236 imageline($graph, $graph_width - 1, 0, $graph_width - 1, $graph_height, $color['grey']); |
pierre@0
|
237 imageline($graph, 0, $graph_height - 1, $graph_width - 1, $graph_height - 1, $color['grey']); |
pierre@0
|
238 |
pierre@0
|
239 // Draw a grid. |
pierre@0
|
240 for ($i = 0; $i < ($increments + 1); $i++) { |
pierre@0
|
241 imageline($graph, $i*50, 0, $i*50, $graph_height, $color['grey']); |
pierre@0
|
242 } |
pierre@0
|
243 for ($i = 0; $i < 11; $i++) { |
pierre@0
|
244 imageline($graph, 0, $i*25, $graph_width, $i*25, $color['grey']); |
pierre@0
|
245 } |
pierre@0
|
246 |
pierre@0
|
247 $multiply = 0; |
pierre@0
|
248 if ($max_views > $graph_height) { |
pierre@0
|
249 if (!$multiply) { |
pierre@0
|
250 $multiply = .9; |
pierre@0
|
251 } |
pierre@0
|
252 while (($max_views * $multiply) >= $graph_height) { |
pierre@0
|
253 $multiply *= .9; |
pierre@0
|
254 } |
pierre@0
|
255 } |
pierre@0
|
256 else if ($max_views) { |
pierre@0
|
257 while (($max_views * ($multiply + 1)) <= $graph_height) { |
pierre@0
|
258 $multiply++; |
pierre@0
|
259 } |
pierre@0
|
260 } |
pierre@0
|
261 |
pierre@0
|
262 // Display impressions. |
pierre@0
|
263 for ($i = 0; $i < $increments ; $i++) { |
pierre@0
|
264 $view = $multiply ? $statistics[$i]['views'] * $multiply : $statistics[$i]['views']; |
pierre@0
|
265 if ($view) { |
pierre@0
|
266 imagefilledrectangle($graph, $i*50 + 4, $graph_height-$view, ($i+1)*50, $graph_height, $color['grey']); |
pierre@0
|
267 $string_height = $view < 10 ? $graph_height - 10 : $graph_height - $view; |
pierre@0
|
268 imagestring($graph, 2, $i*50 + 15, $string_height, $statistics[$i]['views'], $color['black']); |
pierre@0
|
269 } |
pierre@0
|
270 // Display timestamp |
pierre@0
|
271 imagestring($graph, 2, $i*50 + 2, 255, $statistics[$i]['upper'], $color['black']); |
pierre@0
|
272 imagestring($graph, 2, $i*50 + 3, 265, $statistics[$i]['lower'], $color['black']); |
pierre@0
|
273 } |
pierre@0
|
274 |
pierre@0
|
275 // Display clicks. |
pierre@0
|
276 for ($i = 0; $i < $increments; $i++) { |
pierre@0
|
277 $click = $multiply ? $statistics[$i]['clicks'] * $multiply : $statistics[$i]['clicks']; |
pierre@0
|
278 if ($click) { |
pierre@0
|
279 imagefilledrectangle($graph, $i*50 + 10, $graph_height-$click, ($i+1)*50, $graph_height, $color['blue']); |
pierre@0
|
280 $string_height = $click < 10 ? $graph_height - 10 : $graph_height - $click; |
pierre@0
|
281 imagestring($graph, 2, $i*50 + 20, $string_height, $statistics[$i]['clicks'], $color['white']); |
pierre@0
|
282 } |
pierre@0
|
283 } |
pierre@0
|
284 |
pierre@0
|
285 imagepng($graph); |
pierre@0
|
286 imagedestroy($graph); |
pierre@0
|
287 |
pierre@0
|
288 } |
pierre@0
|
289 |