| [ Index ] |
PHP Cross Reference of YOURLS |
[Summary view] [Print] [Text view]
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 * @param array $countries Array of 'country_code' => 'number of visits' 7 * @param string $id Optional HTML element ID 8 * @return void 9 */ 10 function yourls_stats_countries_map($countries, $id = null) { 11 12 yourls_do_action( 'pre_stats_countries_map' ); 13 14 // if $id is null then assign a random string 15 if( $id === null ) 16 $id = uniqid ( 'yourls_stats_map_' ); 17 18 $data = array_merge( array( 'Country' => 'Hits' ), $countries ); 19 $data = yourls_google_array_to_data_table( $data ); 20 21 $options = array( 22 'backgroundColor' => "white", 23 'colorAxis' => "{colors:['A8D0ED','99C4E4','8AB8DB','7BACD2','6BA1C9','5C95C0','4D89B7','3E7DAE','2E72A5','1F669C']}", 24 'width' => "550", 25 'height' => "340", 26 'theme' => 'maximized' 27 ); 28 $options = yourls_apply_filter( 'stats_countries_map_options', $options ); 29 30 $map = yourls_google_viz_code( 'GeoChart', $data, $options, $id ); 31 32 echo yourls_apply_filter( 'stats_countries_map', $map, $countries, $options, $id ); 33 } 34 35 36 /** 37 * 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 38 * 39 * @param array $data Array of 'data' => 'value' 40 * @param int $limit Optional limit list of X first countries 41 * @param int $size Optional size of the image 42 * @param mixed $id Optional HTML element ID 43 * @return void 44 */ 45 function yourls_stats_pie($data, $limit = 10, $size = '340x220', $id = null) { 46 47 yourls_do_action( 'pre_stats_pie' ); 48 49 // if $id is null then assign a random string 50 if( $id === null ) 51 $id = uniqid ( 'yourls_stats_pie_' ); 52 53 // Trim array: $limit first item + the sum of all others 54 if ( count( $data ) > $limit ) { 55 $i= 0; 56 $trim_data = array( 'Others' => 0 ); 57 foreach( $data as $item=>$value ) { 58 $i++; 59 if( $i <= $limit ) { 60 $trim_data[$item] = $value; 61 } else { 62 $trim_data['Others'] += $value; 63 } 64 } 65 $data = $trim_data; 66 } 67 68 // Scale items 69 $_data = yourls_scale_data( $data ); 70 71 list($width, $height) = explode( 'x', $size ); 72 73 $options = array( 74 'theme' => 'maximized', 75 'width' => $width, 76 'height' => $height, 77 'colors' => "['A8D0ED','99C4E4','8AB8DB','7BACD2','6BA1C9','5C95C0','4D89B7','3E7DAE','2E72A5','1F669C']", 78 'legend' => 'none', 79 'chartArea' => '{top: "5%", height: "90%"}', 80 'pieSliceText' => 'label', 81 ); 82 $options = yourls_apply_filter( 'stats_pie_options', $options ); 83 84 $script_data = array_merge( array( 'Country' => 'Value' ), $_data ); 85 $script_data = yourls_google_array_to_data_table( $script_data ); 86 87 $pie = yourls_google_viz_code( 'PieChart', $script_data, $options, $id ); 88 89 echo yourls_apply_filter( 'stats_pie', $pie, $data, $limit, $size, $options, $id ); 90 } 91 92 93 /** 94 * Build a list of all daily values between d1/m1/y1 to d2/m2/y2. 95 * 96 * @param array $dates 97 * @return array[] Array of arrays of days, months, years 98 */ 99 function yourls_build_list_of_days($dates) { 100 /* Say we have an array like: 101 $dates = array ( 102 2009 => array ( 103 '08' => array ( 104 29 => 15, 105 30 => 5, 106 ), 107 '09' => array ( 108 '02' => 3, 109 '03' => 5, 110 '04' => 2, 111 '05' => 99, 112 ), 113 ), 114 ) 115 */ 116 117 if( !$dates ) 118 return array(); 119 120 // Get first & last years from our range. In our example: 2009 & 2009 121 $first_year = key( $dates ); 122 $_keys = array_keys( $dates ); 123 $last_year = end( $_keys ); 124 reset( $dates ); 125 126 // Get first & last months from our range. In our example: 08 & 09 127 $first_month = key( $dates[ $first_year ] ); 128 $_keys = array_keys( $dates[ $last_year ] ); 129 $last_month = end( $_keys ); 130 reset( $dates ); 131 132 // Get first & last days from our range. In our example: 29 & 05 133 $first_day = key( $dates[ $first_year ][ $first_month ] ); 134 $_keys = array_keys( $dates[ $last_year ][ $last_month ] ); 135 $last_day = end( $_keys ); 136 137 unset( $_keys ); 138 139 // Extend to today 140 $today = new DateTime(); 141 $today->setTime( 0, 0, 0 ); // Start of today 142 $today_year = $today->format( 'Y' ); 143 $today_month = $today->format( 'm' ); 144 $today_day = $today->format( 'd' ); 145 146 // Now build a list of all years (2009), month (08 & 09) and days (all from 2009-08-29 to 2009-09-05) 147 $list_of_years = array(); 148 $list_of_months = array(); 149 $list_of_days = array(); 150 for ( $year = $first_year; $year <= $today_year; $year++ ) { 151 $_year = sprintf( '%04d', $year ); 152 $list_of_years[ $_year ] = $_year; 153 $current_first_month = ( $year == $first_year ? $first_month : '01' ); 154 $current_last_month = ( $year == $today_year ? $today_month : '12' ); 155 for ( $month = $current_first_month; $month <= $current_last_month; $month++ ) { 156 $_month = sprintf( '%02d', $month ); 157 $list_of_months[ $_month ] = $_month; 158 $current_first_day = ( $year == $first_year && $month == $first_month ? $first_day : '01' ); 159 $current_last_day = ( $year == $today_year && $month == $today_month ? $today_day : yourls_days_in_month( $month, $year ) ); 160 for ( $day = $current_first_day; $day <= $current_last_day; $day++ ) { 161 $day = sprintf( '%02d', $day ); 162 $key = date( 'M d, Y', mktime( 0, 0, 0, $_month, $day, $_year ) ); 163 $list_of_days[ $key ] = isset( $dates[$_year][$_month][$day] ) ? $dates[$_year][$_month][$day] : 0; 164 } 165 } 166 } 167 168 return array( 169 'list_of_days' => $list_of_days, 170 'list_of_months' => $list_of_months, 171 'list_of_years' => $list_of_years, 172 ); 173 } 174 175 176 /** 177 * Echoes an image tag of Google Charts line graph from array of values (eg 'number of clicks'). 178 * 179 * $legend1_list & legend2_list are values used for the 2 x-axis labels. $id is an HTML/JS id 180 * 181 * @param array $values Array of values (eg 'number of clicks') 182 * @param string $id HTML element id 183 * @return void 184 */ 185 function yourls_stats_line($values, $id = null) { 186 187 yourls_do_action( 'pre_stats_line' ); 188 189 // if $id is null then assign a random string 190 if( $id === null ) 191 $id = uniqid ( 'yourls_stats_line_' ); 192 193 // If we have only 1 day of data, prepend a fake day with 0 hits for a prettier graph 194 if ( count( $values ) == 1 ) 195 array_unshift( $values, 0 ); 196 197 // Keep only a subset of values to keep graph smooth 198 $values = yourls_array_granularity( $values, 30 ); 199 200 $data = array_merge( array( 'Time' => 'Hits' ), $values ); 201 $data = yourls_google_array_to_data_table( $data ); 202 203 $options = array( 204 "legend" => "none", 205 "pointSize" => "3", 206 "theme" => "maximized", 207 "curveType" => "function", 208 "width" => 430, 209 "height" => 220, 210 "hAxis" => "{minTextSpacing: 80, maxTextLines: 1, maxAlternation: 1}", 211 "vAxis" => "{minValue: 0, format: '#'}", 212 "colors" => "['#2a85b3']", 213 ); 214 $options = yourls_apply_filter( 'stats_line_options', $options ); 215 216 $lineChart = yourls_google_viz_code( 'LineChart', $data, $options, $id ); 217 218 echo yourls_apply_filter( 'stats_line', $lineChart, $values, $options, $id ); 219 } 220 221 222 /** 223 * Return the number of days in a month. From php.net. 224 * 225 * @param int $month 226 * @param int $year 227 * @return int 228 */ 229 function yourls_days_in_month($month, $year) { 230 // calculate number of days in a month 231 return $month == 2 ? ( $year % 4 ? 28 : ( $year % 100 ? 29 : ( $year % 400 ? 28 : 29 ) ) ) : ( ( $month - 1 ) % 7 % 2 ? 30 : 31 ); 232 } 233 234 235 /** 236 * Get max value from date array of 'Aug 12, 2012' = '1337' 237 * 238 * @param array $list_of_days 239 * @return array 240 */ 241 function yourls_stats_get_best_day($list_of_days) { 242 $max = max( $list_of_days ); 243 foreach( $list_of_days as $k=>$v ) { 244 if ( $v == $max ) 245 return array( 'day' => $k, 'max' => $max ); 246 } 247 } 248 249 /** 250 * Return domain of a URL 251 * 252 * @param string $url 253 * @param bool $include_scheme 254 * @return string 255 */ 256 function yourls_get_domain(string $url, bool $include_scheme = false): string { 257 $parse = parse_url($url); 258 259 // parse_url() returns false on seriously malformed URLs 260 if ($parse === false) { 261 return ''; 262 } 263 264 // Get host & scheme. Fall back to path if not found. 265 $host = $parse['host'] ?? ''; 266 $scheme = $parse['scheme'] ?? ''; 267 $path = $parse['path'] ?? ''; 268 if (!$host) { 269 $host = $path; 270 } 271 272 // Validate host: only allow valid hostname/IP characters. 273 // IPv6 addresses are wrapped in brackets eg [::1] 274 if ($host && !preg_match('/^(\[[\da-fA-F:]+\]|[a-zA-Z0-9._-]+)$/', $host)) { 275 // ASCII check failed - may be an IDN hostname (eg münchen.de) 276 if (function_exists('idn_to_ascii')) { 277 $ascii = idn_to_ascii($host, IDNA_DEFAULT, INTL_IDNA_VARIANT_UTS46); 278 if ($ascii === false || !preg_match('/^[a-zA-Z0-9._-]+$/', $ascii)) { 279 return ''; 280 } 281 $host = $ascii; 282 } else { 283 // No intl extension: accept unicode letters/digits, dots and hyphens only 284 if (!preg_match('/^[\pL\pN._-]+$/u', $host)) { 285 return ''; 286 } 287 } 288 } 289 290 if ($include_scheme && $scheme) { 291 $host = $scheme . '://' . $host; 292 } 293 294 return $host; 295 } 296 297 298 /** 299 * Return favicon URL 300 * 301 * @param string $url 302 * @return string 303 */ 304 function yourls_get_favicon_url(string $url): string { 305 return yourls_match_current_protocol( '//www.google.com/s2/favicons?domain=' . yourls_esc_url(yourls_get_domain( $url, false ) ) ); 306 } 307 308 /** 309 * Scale array of data from 0 to 100 max 310 * 311 * @param array $data 312 * @return array 313 */ 314 function yourls_scale_data($data ) { 315 $max = max( $data ); 316 if( $max > 100 ) { 317 foreach( $data as $k=>$v ) { 318 $data[$k] = intval( $v / $max * 100 ); 319 } 320 } 321 return $data; 322 } 323 324 325 /** 326 * Tweak granularity of array $array: keep only $grain values. 327 * 328 * This make less accurate but less messy graphs when too much values. 329 * See https://developers.google.com/chart/image/docs/gallery/line_charts?hl=en#data-granularity 330 * 331 * @param array $array 332 * @param int $grain 333 * @param bool $preserve_max 334 * @return array 335 */ 336 function yourls_array_granularity($array, $grain = 100, $preserve_max = true) { 337 if ( count( $array ) > $grain ) { 338 $max = max( $array ); 339 $step = intval( count( $array ) / $grain ); 340 $i = 0; 341 // Loop through each item and unset except every $step (optional preserve the max value) 342 foreach( $array as $k=>$v ) { 343 $i++; 344 if ( $i % $step != 0 ) { 345 if ( $preserve_max == false ) { 346 unset( $array[$k] ); 347 } else { 348 if ( $v < $max ) 349 unset( $array[$k] ); 350 } 351 } 352 } 353 } 354 return $array; 355 } 356 357 /** 358 * Transform data array to data table for Google API 359 * 360 * @param array $data 361 * @return string 362 */ 363 function yourls_google_array_to_data_table(array $data): string { 364 $str = "var data = google.visualization.arrayToDataTable([\n"; 365 foreach( $data as $label => $values ){ 366 if( !is_array( $values ) ) { 367 $values = array( $values ); 368 } 369 $str .= "\t['" . yourls_esc_js($label) . "',"; 370 foreach( $values as $value ){ 371 $value = yourls_esc_url( $value ); 372 if( !is_numeric( $value ) && !str_starts_with($value, '[') && !str_starts_with($value, '{')) { 373 $value = "'" . yourls_esc_js($value) . "'"; 374 } 375 $str .= "$value"; 376 } 377 $str .= "],\n"; 378 } 379 $str = substr( $str, 0, -2 ) . "\n"; // remove the trailing comma/return, reappend the return 380 $str .= "]);\n"; // wrap it up 381 return $str; 382 } 383 384 /** 385 * Return javascript code that will display the Google Chart 386 * 387 * @param string $graph_type 388 * @param string $data 389 * @param array $options 390 * @param string $id 391 * @return string 392 */ 393 function yourls_google_viz_code($graph_type, $data, $options, $id ) { 394 $function_name = 'yourls_graph' . $id; 395 $code = "\n<script id=\"$function_name\" type=\"text/javascript\">\n"; 396 $code .= "function $function_name() { \n"; 397 398 $code .= "$data\n"; 399 400 $code .= "var options = {\n"; 401 foreach( $options as $field => $value ) { 402 if( !is_numeric( $value ) && strpos( $value, '[' ) !== 0 && strpos( $value, '{' ) !== 0 ) { 403 $value = "\"$value\""; 404 } 405 $code .= "\t'$field': $value,\n"; 406 } 407 $code = substr( $code, 0, -2 ) . "\n"; // remove the trailing comma/return, reappend the return 408 $code .= "\t}\n"; 409 410 $code .= "new google.visualization.$graph_type( document.getElementById('visualization_$id') ).draw( data, options );"; 411 $code .= "}\n"; 412 $code .= "google.setOnLoadCallback( $function_name );\n"; 413 $code .= "</script>\n"; 414 $code .= "<div id=\"visualization_$id\"></div>\n"; 415 416 return $code; 417 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Sat Jun 13 05:10:47 2026 | Cross-referenced by PHPXref 0.7.1 |