Issues (2756)

includes/functions-infos.php (16 issues)

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:
0 ignored issues
show
Unused Code Comprehensibility introduced by
44% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
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 ) );
0 ignored issues
show
$day of type string is incompatible with the type integer expected by parameter $day of mktime(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

143
				$key = date( 'M d, Y', mktime( 0, 0, 0, $_month, /** @scrutinizer ignore-type */ $day, $_year ) );
Loading history...
$_year of type string is incompatible with the type integer expected by parameter $year of mktime(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

143
				$key = date( 'M d, Y', mktime( 0, 0, 0, $_month, $day, /** @scrutinizer ignore-type */ $_year ) );
Loading history...
$_month of type string is incompatible with the type integer expected by parameter $month of mktime(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

143
				$key = date( 'M d, Y', mktime( 0, 0, 0, /** @scrutinizer ignore-type */ $_month, $day, $_year ) );
Loading history...
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( '//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'";
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $value instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
300
			}
301
			$str .= "$value";
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $value instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
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";
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $function_name instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
317
	$code .= "function $function_name() { \n";
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $function_name instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
318
319
	$code .= "$data\n";
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $data instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
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\"";
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $value instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
325
		}
326
		$code .= "\t'$field': $value,\n";
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $field instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $value instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
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 );";
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $graph_type instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $id instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
332
	$code .= "}\n";
333
	$code .= "google.setOnLoadCallback( $function_name );\n";
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $function_name instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
334
	$code .= "</script>\n";
335
	$code .= "<div id=\"visualization_$id\"></div>\n";
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $id instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
336
337
	return $code;
338
}
339
340