]> CyberLeo.Net >> Repos - Github/YOURLS.git/blob - includes/functions-infos.php
Add plain API format
[Github/YOURLS.git] / includes / functions-infos.php
1 <?php
2
3 /**
4  * Echoes an image tag of Google Charts map from sorted array of 'country_code' => 'number of visits' (sort by DESC)
5  *
6  */
7 function yourls_stats_countries_map( $countries, $id = null ) {
8
9         yourls_do_action( 'pre_stats_countries_map' );
10         
11         // if $id is null then assign a random string
12         if( $id === null )
13                 $id = uniqid ( 'yourls_stats_map_' );
14
15         $data = array_merge( array( 'Country' => 'Hits' ), $countries );
16         $data = yourls_google_array_to_data_table( $data );
17
18         $options = array(
19                 'backgroundColor' => "white",
20                 'colorAxis'       => "{colors:['A8D0ED','99C4E4','8AB8DB','7BACD2','6BA1C9','5C95C0','4D89B7','3E7DAE','2E72A5','1F669C']}",
21                 'width'           => "550",
22                 'height'          => "340",
23                 'theme'           => 'maximized'
24         );
25         $options = yourls_apply_filter( 'stats_countries_map_options', $options );
26         
27         $map = yourls_google_viz_code( 'GeoChart', $data, $options, $id );
28
29         echo yourls_apply_filter( 'stats_countries_map', $map, $countries, $options, $id );
30 }
31
32 /**
33  * Echoes an image tag of Google Charts pie from sorted array of 'data' => 'value' (sort by DESC). Optional $limit = (integer) limit list of X first countries, sorted by most visits
34  *
35  */
36 function yourls_stats_pie( $data, $limit = 10, $size = '340x220', $id = null ) {
37
38         yourls_do_action( 'pre_stats_pie' );
39         
40         // if $id is null then assign a random string
41         if( $id === null )
42                 $id = uniqid ( 'yourls_stats_pie_' );
43
44         // Trim array: $limit first item + the sum of all others
45         if ( count( $data ) > $limit ) {
46                 $i= 0;
47                 $trim_data = array( 'Others' => 0 );
48                 foreach( $data as $item=>$value ) {
49                         $i++;
50                         if( $i <= $limit ) {
51                                 $trim_data[$item] = $value;
52                         } else {
53                                 $trim_data['Others'] += $value;
54                         }
55                 }
56                 $data = $trim_data;
57         }
58         
59         // Scale items
60         $_data = yourls_scale_data( $data );
61         
62         list($width, $height) = explode( 'x', $size );
63         
64         $options = array(
65                 'theme'  => 'maximized',
66                 'width'   => $width,
67                 'height'   => $height,
68                 'colors'    => "['A8D0ED','99C4E4','8AB8DB','7BACD2','6BA1C9','5C95C0','4D89B7','3E7DAE','2E72A5','1F669C']",
69                 'legend'     => 'none',
70                 'chartArea'   => '{top: "5%", height: "90%"}',
71                 'pieSliceText' => 'label',
72         );
73         $options = yourls_apply_filter( 'stats_pie_options', $options );
74
75         $script_data = array_merge( array( 'Country' => 'Value' ), $_data );
76         $script_data = yourls_google_array_to_data_table( $script_data );
77
78         $pie = yourls_google_viz_code( 'PieChart', $script_data, $options, $id );
79
80         echo yourls_apply_filter( 'stats_pie', $pie, $data, $limit, $size, $options, $id );
81 }
82
83 /**
84  * Build a list of all daily values between d1/m1/y1 to d2/m2/y2.
85  *
86  */
87 function yourls_build_list_of_days( $dates ) {
88         /* Say we have an array like:
89         $dates = array (
90                 2009 => array (
91                         '08' => array (
92                                 29 => 15,
93                                 30 => 5,
94                                 ),
95                         '09' => array (
96                                 '02' => 3,
97                                 '03' => 5,
98                                 '04' => 2,
99                                 '05' => 99,
100                                 ),
101                         ),
102                 )
103         */
104         
105         if( !$dates )
106                 return array();
107
108         // Get first & last years from our range. In our example: 2009 & 2009
109         $first_year = key( $dates );
110         $_keys      = array_keys( $dates );
111         $last_year  = end( $_keys );
112         reset( $dates );
113
114         // Get first & last months from our range. In our example: 08 & 09
115         $first_month = key( $dates[ $first_year ] );
116         $_keys       = array_keys( $dates[ $last_year ] );
117         $last_month  = end( $_keys );
118         reset( $dates );
119         
120         // Get first & last days from our range. In our example: 29 & 05
121         $first_day = key( $dates[ $first_year ][ $first_month ] );
122         $_keys     = array_keys( $dates[ $last_year ][ $last_month ] );
123         $last_day  = end( $_keys );
124         
125         unset( $_keys );
126
127         // Now build a list of all years (2009), month (08 & 09) and days (all from 2009-08-29 to 2009-09-05)
128         $list_of_years  = array();
129         $list_of_months = array();
130         $list_of_days   = array();
131         for ( $year = $first_year; $year <= $last_year; $year++ ) {
132                 $_year = sprintf( '%04d', $year );
133                 $list_of_years[ $_year ] = $_year;
134                 $current_first_month = ( $year == $first_year ? $first_month : '01' );
135                 $current_last_month  = ( $year == $last_year ? $last_month : '12' );
136                 for ( $month = $current_first_month; $month <= $current_last_month; $month++ ) {
137                         $_month = sprintf( '%02d', $month );
138                         $list_of_months[ $_month ] = $_month;
139                         $current_first_day = ( $year == $first_year && $month == $first_month ? $first_day : '01' );
140                         $current_last_day  = ( $year == $last_year && $month == $last_month ? $last_day : yourls_days_in_month( $month, $year) );
141                         for ( $day = $current_first_day; $day <= $current_last_day; $day++ ) {
142                                 $day = sprintf( '%02d', $day );
143                                 $key = date( 'M d, Y', mktime( 0, 0, 0, $_month, $day, $_year ) );
144                                 $list_of_days[ $key ] = isset( $dates[$_year][$_month][$day] ) ? $dates[$_year][$_month][$day] : 0;
145                         }
146                 }
147         }
148         
149         return array(
150                 'list_of_days'   => $list_of_days,
151                 'list_of_months' => $list_of_months,
152                 'list_of_years'  => $list_of_years,
153         );
154 }
155
156 /**
157  * Echoes an image tag of Google Charts line graph from array of values (eg 'number of clicks').
158  * 
159  * $legend1_list & legend2_list are values used for the 2 x-axis labels. $id is an HTML/JS id
160  *
161  */
162 function yourls_stats_line( $values, $id = null ) {
163
164         yourls_do_action( 'pre_stats_line' );
165         
166         // if $id is null then assign a random string
167         if( $id === null )
168                 $id = uniqid ( 'yourls_stats_line_' );
169                 
170         // If we have only 1 day of data, prepend a fake day with 0 hits for a prettier graph
171         if ( count( $values ) == 1 )
172                 array_unshift( $values, 0 );
173                 
174         // Keep only a subset of values to keep graph smooth
175         $values = yourls_array_granularity( $values, 30 );
176         
177         $data = array_merge( array( 'Time' => 'Hits' ), $values );
178         $data = yourls_google_array_to_data_table( $data );
179         
180         $options = array(
181                 "legend"      => "none",
182                 "pointSize"   => "3",
183                 "theme"       => "maximized",
184                 "curveType"   => "function",
185                 "width"       => 430,
186                 "height"          => 220,
187                 "hAxis"       => "{minTextSpacing: 80, maxTextLines: 1, maxAlternation: 1}",
188                 "vAxis"       => "{minValue: 0, format: '#'}",
189                 "colors"          => "['#2a85b3']",
190         );
191         $options = yourls_apply_filter( 'stats_line_options', $options );
192         
193         $lineChart = yourls_google_viz_code( 'LineChart', $data, $options, $id );
194
195         echo yourls_apply_filter( 'stats_line', $lineChart, $values, $options, $id );
196 }
197
198 /**
199  * Return the number of days in a month. From php.net, used if PHP built without calendar functions
200  *
201  */
202 function yourls_days_in_month( $month, $year ) {
203         // calculate number of days in a month
204         return $month == 2 ? ( $year % 4 ? 28 : ( $year % 100 ? 29 : ( $year % 400 ? 28 : 29 ) ) ) : ( ( $month - 1 ) % 7 % 2 ? 30 : 31 );
205 }
206
207 /**
208  * Get max value from date array of 'Aug 12, 2012' = '1337'
209  *
210  */
211 function yourls_stats_get_best_day( $list_of_days ) {
212         $max = max( $list_of_days );
213         foreach( $list_of_days as $k=>$v ) {
214                 if ( $v == $max )
215                         return array( 'day' => $k, 'max' => $max );
216         }
217 }
218
219 /**
220  * Return domain of a URL
221  *
222  */
223 function yourls_get_domain( $url, $include_scheme = false ) {
224         $parse = @parse_url( $url ); // Hiding ugly stuff coming from malformed referrer URLs
225
226         // Get host & scheme. Fall back to path if not found.
227         $host = isset( $parse['host'] ) ? $parse['host'] : '';
228         $scheme = isset( $parse['scheme'] ) ? $parse['scheme'] : '';
229         $path = isset( $parse['path'] ) ? $parse['path'] : '';
230         if( !$host )
231                 $host = $path;  
232                 
233         if ( $include_scheme && $scheme )
234                 $host = $scheme.'://'.$host;
235                 
236         return $host;
237 }
238
239 /**
240  * Return favicon URL
241  *
242  */
243 function yourls_get_favicon_url( $url ) {
244         return yourls_match_current_protocol( 'http://www.google.com/s2/favicons?domain=' . yourls_get_domain( $url, false ) );
245 }
246
247 /**
248  * Scale array of data from 0 to 100 max
249  *
250  */
251 function yourls_scale_data( $data ) {
252         $max = max( $data );
253         if( $max > 100 ) {
254                 foreach( $data as $k=>$v ) {
255                         $data[$k] = intval( $v / $max * 100 );
256                 }
257         }
258         return $data;
259 }
260
261 /**
262  * Tweak granularity of array $array: keep only $grain values. This make less accurate but less messy graphs when too much values. See http://code.google.com/apis/chart/formats.html#granularity
263  *
264  */
265 function yourls_array_granularity( $array, $grain = 100, $preserve_max = true ) {
266         if ( count( $array ) > $grain ) {
267                 $max = max( $array );
268                 $step = intval( count( $array ) / $grain );
269                 $i = 0;
270                 // Loop through each item and unset except every $step (optional preserve the max value)
271                 foreach( $array as $k=>$v ) {
272                         $i++;
273                         if ( $i % $step != 0 ) {
274                                 if ( $preserve_max == false ) {
275                                         unset( $array[$k] );
276                                 } else {
277                                         if ( $v < $max )
278                                                 unset( $array[$k] );
279                                 }
280                         }
281                 }
282         }
283         return $array;
284 }
285
286 /**
287  * Transform data array to data table for Google API
288  *
289  */
290 function yourls_google_array_to_data_table( $data ){
291         $str  = "var data = google.visualization.arrayToDataTable([\n";
292         foreach( $data as $label => $values ){
293                 if( !is_array( $values ) ) {
294                         $values = array( $values );
295                 }
296                 $str .= "\t['$label',"; 
297                 foreach( $values as $value ){
298                         if( !is_numeric( $value ) && strpos( $value, '[' ) !== 0 && strpos( $value, '{' ) !== 0 ) { 
299                                 $value = "'$value'";
300                         }
301                         $str .= "$value";
302                 }               
303                 $str .= "],\n";
304         }
305         $str = substr( $str, 0, -2 ) . "\n"; // remove the trailing comma/return, reappend the return
306         $str .= "]);\n"; // wrap it up  
307         return $str;
308 }
309
310 /**
311  * Return javascript code that will display the Google Chart
312  *
313  */
314 function yourls_google_viz_code( $graph_type, $data, $options, $id ) {
315         $function_name = 'yourls_graph' . $id;
316         $code  = "\n<script id=\"$function_name\" type=\"text/javascript\">\n";
317         $code .= "function $function_name() { \n";
318
319         $code .= "$data\n";
320
321         $code .= "var options = {\n";
322         foreach( $options as $field => $value ) {
323                 if( !is_numeric( $value ) && strpos( $value, '[' ) !== 0 && strpos( $value, '{' ) !== 0 ) { 
324                         $value = "\"$value\"";
325                 }
326                 $code .= "\t'$field': $value,\n";
327         }
328         $code  = substr( $code, 0, -2 ) . "\n"; // remove the trailing comma/return, reappend the return
329         $code .= "\t}\n";
330
331         $code .= "new google.visualization.$graph_type( document.getElementById('visualization_$id') ).draw( data, options );";
332         $code .= "}\n";
333         $code .= "google.setOnLoadCallback( $function_name );\n";
334         $code .= "</script>\n";
335         $code .= "<div id=\"visualization_$id\"></div>\n";
336         
337         return $code;
338 }
339