Issues (1182)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

admin/reports/class-wc-report-coupon-usage.php (10 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
if ( ! defined( 'ABSPATH' ) ) {
4
	exit; // Exit if accessed directly
5
}
6
7
/**
8
 * WC_Report_Coupon_Usage
9
 *
10
 * @author      WooThemes
11
 * @category    Admin
12
 * @package     WooCommerce/Admin/Reports
13
 * @version     2.1.0
14
 */
15
class WC_Report_Coupon_Usage extends WC_Admin_Report {
16
17
	/**
18
	 * Chart colours.
19
	 *
20
	 * @var array
21
	 */
22
	public $chart_colours = array();
23
24
	/**
25
	 * Coupon codes.
26
	 *
27
	 * @var array
28
	 */
29
	public $coupon_codes = array();
30
31
	/**
32
	 * Constructor.
33
	 */
34 View Code Duplication
	public function __construct() {
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
35
		if ( isset( $_GET['coupon_codes'] ) && is_array( $_GET['coupon_codes'] ) ) {
36
			$this->coupon_codes = array_filter( array_map( 'sanitize_text_field', $_GET['coupon_codes'] ) );
37
		} elseif ( isset( $_GET['coupon_codes'] ) ) {
38
			$this->coupon_codes = array_filter( array( sanitize_text_field( $_GET['coupon_codes'] ) ) );
39
		}
40
	}
41
42
	/**
43
	 * Get the legend for the main chart sidebar.
44
	 *
45
	 * @return array
46
	 */
47
	public function get_chart_legend() {
48
		$legend = array();
49
50
		$total_discount_query = array(
51
			'data' => array(
52
				'discount_amount' => array(
53
					'type'            => 'order_item_meta',
54
					'order_item_type' => 'coupon',
55
					'function'        => 'SUM',
56
					'name'            => 'discount_amount'
57
				)
58
			),
59
			'where' => array(
60
				array(
61
					'key'      => 'order_item_type',
62
					'value'    => 'coupon',
63
					'operator' => '='
64
				)
65
			),
66
			'query_type'   => 'get_var',
67
			'filter_range' => true,
68
			'order_types'  => wc_get_order_types( 'order-count' ),
69
		);
70
71
		$total_coupons_query = array(
72
			'data' => array(
73
				'order_item_id' => array(
74
					'type'            => 'order_item',
75
					'order_item_type' => 'coupon',
76
					'function'        => 'COUNT',
77
					'name'            => 'order_coupon_count'
78
				)
79
			),
80
			'where' => array(
81
				array(
82
					'key'      => 'order_item_type',
83
					'value'    => 'coupon',
84
					'operator' => '='
85
				)
86
			),
87
			'query_type'   => 'get_var',
88
			'filter_range' => true,
89
			'order_types'  => wc_get_order_types( 'order-count' ),
90
		);
91
92 View Code Duplication
		if ( ! empty( $this->coupon_codes ) ) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
93
			$coupon_code_query = array(
94
				'type'     => 'order_item',
95
				'key'      => 'order_item_name',
96
				'value'    => $this->coupon_codes,
97
				'operator' => 'IN'
98
			);
99
100
			$total_discount_query['where'][] = $coupon_code_query;
101
			$total_coupons_query['where'][]  = $coupon_code_query;
102
		}
103
104
		$total_discount = $this->get_order_report_data( $total_discount_query );
105
		$total_coupons  = absint( $this->get_order_report_data( $total_coupons_query ) );
106
107
		$legend[] = array(
108
			'title' => sprintf( __( '%s discounts in total', 'woocommerce' ), '<strong>' . wc_price( $total_discount ) . '</strong>' ),
109
			'color' => $this->chart_colours['discount_amount'],
110
			'highlight_series' => 1
111
		);
112
113
		$legend[] = array(
114
			'title' => sprintf( __( '%s coupons used in total', 'woocommerce' ), '<strong>' . $total_coupons . '</strong>' ),
115
			'color' => $this->chart_colours['coupon_count' ],
116
			'highlight_series' => 0
117
		);
118
119
		return $legend;
120
	}
121
122
	/**
123
	 * Output the report.
124
	 */
125 View Code Duplication
	public function output_report() {
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
126
127
		$ranges = array(
128
			'year'         => __( 'Year', 'woocommerce' ),
129
			'last_month'   => __( 'Last Month', 'woocommerce' ),
130
			'month'        => __( 'This Month', 'woocommerce' ),
131
			'7day'         => __( 'Last 7 Days', 'woocommerce' )
132
		);
133
134
		$this->chart_colours = array(
135
			'discount_amount' => '#3498db',
136
			'coupon_count'    => '#d4d9dc',
137
		);
138
139
		$current_range = ! empty( $_GET['range'] ) ? sanitize_text_field( $_GET['range'] ) : '7day';
140
141
		if ( ! in_array( $current_range, array( 'custom', 'year', 'last_month', 'month', '7day' ) ) ) {
142
			$current_range = '7day';
143
		}
144
145
		$this->calculate_current_range( $current_range );
146
147
		include( WC()->plugin_path() . '/includes/admin/views/html-report-by-date.php');
148
	}
149
150
	/**
151
	 * Get chart widgets.
152
	 *
153
	 * @return array
154
	 */
155
	public function get_chart_widgets() {
156
		$widgets = array();
157
158
		$widgets[] = array(
159
			'title'    => '',
160
			'callback' => array( $this, 'coupons_widget' )
161
		);
162
163
		return $widgets;
164
	}
165
166
	/**
167
	 * Output coupons widget.
168
	 */
169
	public function coupons_widget() {
170
		?>
171
		<h4 class="section_title"><span><?php _e( 'Filter by coupon', 'woocommerce' ); ?></span></h4>
172
		<div class="section">
173
			<form method="GET">
174
				<div>
175
					<?php
176
						$used_coupons = $this->get_order_report_data( array(
177
							'data' => array(
178
								'order_item_name' => array(
179
									'type'            => 'order_item',
180
									'order_item_type' => 'coupon',
181
									'function'        => '',
182
									'distinct'        => true,
183
									'name'            => 'order_item_name'
184
								)
185
							),
186
							'where' => array(
187
								array(
188
									'key'      => 'order_item_type',
189
									'value'    => 'coupon',
190
									'operator' => '='
191
								)
192
							),
193
							'query_type'   => 'get_col',
194
							'filter_range' => false
195
						) );
196
197
						if ( ! is_null( $used_coupons ) ) :
198
					?>
199
						<select id="coupon_codes" name="coupon_codes" class="wc-enhanced-select" data-placeholder="<?php esc_attr_e( 'Choose coupons&hellip;', 'woocommerce' ); ?>" style="width:100%;">
200
							<option value=""><?php _e( 'All coupons', 'woocommerce' ); ?></option>
201
							<?php
202
								foreach ( $used_coupons as $coupon ) {
0 ignored issues
show
The expression $used_coupons of type object|integer|double|string|array|boolean is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
203
									echo '<option value="' . esc_attr( $coupon ) . '" ' . selected( in_array( $coupon, $this->coupon_codes ), true, false ) . '>' . $coupon . '</option>';
204
								}
205
							 ?>
206
						</select>
207
						<input type="submit" class="submit button" value="<?php esc_attr_e( 'Show', 'woocommerce' ); ?>" />
208
						<input type="hidden" name="range" value="<?php if ( ! empty( $_GET['range'] ) ) echo esc_attr( $_GET['range'] ) ?>" />
209
						<input type="hidden" name="start_date" value="<?php if ( ! empty( $_GET['start_date'] ) ) echo esc_attr( $_GET['start_date'] ) ?>" />
210
						<input type="hidden" name="end_date" value="<?php if ( ! empty( $_GET['end_date'] ) ) echo esc_attr( $_GET['end_date'] ) ?>" />
211
						<input type="hidden" name="page" value="<?php if ( ! empty( $_GET['page'] ) ) echo esc_attr( $_GET['page'] ) ?>" />
212
						<input type="hidden" name="tab" value="<?php if ( ! empty( $_GET['tab'] ) ) echo esc_attr( $_GET['tab'] ) ?>" />
213
						<input type="hidden" name="report" value="<?php if ( ! empty( $_GET['report'] ) ) echo esc_attr( $_GET['report'] ) ?>" />
214
					<?php else : ?>
215
						<span><?php _e( 'No used coupons found', 'woocommerce' ); ?></span>
216
					<?php endif; ?>
217
				</div>
218
			</form>
219
		</div>
220
		<h4 class="section_title"><span><?php _e( 'Most Popular', 'woocommerce' ); ?></span></h4>
221
		<div class="section">
222
			<table cellspacing="0">
223
				<?php
224
				$most_popular = $this->get_order_report_data( array(
225
					'data' => array(
226
						'order_item_name' => array(
227
							'type'            => 'order_item',
228
							'order_item_type' => 'coupon',
229
							'function'        => '',
230
							'name'            => 'coupon_code'
231
						),
232
						'order_item_id' => array(
233
							'type'            => 'order_item',
234
							'order_item_type' => 'coupon',
235
							'function'        => 'COUNT',
236
							'name'            => 'coupon_count'
237
						),
238
					),
239
					'where' => array(
240
						array(
241
							'type'     => 'order_item',
242
							'key'      => 'order_item_type',
243
							'value'    => 'coupon',
244
							'operator' => '='
245
						)
246
					),
247
					'order_by'     => 'coupon_count DESC',
248
					'group_by'     => 'order_item_name',
249
					'limit'        => 12,
250
					'query_type'   => 'get_results',
251
					'filter_range' => true
252
				) );
253
254 View Code Duplication
				if ( ! is_null( $most_popular ) ) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
255
					foreach ( $most_popular as $coupon ) {
0 ignored issues
show
The expression $most_popular of type object|integer|double|string|array|boolean is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
256
						echo '<tr class="' . ( in_array( $coupon->coupon_code, $this->coupon_codes ) ? 'active' : '' ) . '">
257
							<td class="count" width="1%">' . $coupon->coupon_count . '</td>
258
							<td class="name"><a href="' . esc_url( add_query_arg( 'coupon_codes', $coupon->coupon_code ) ) . '">' . $coupon->coupon_code . '</a></td>
259
						</tr>';
260
					}
261
				} else {
262
					echo '<tr><td colspan="2">' . __( 'No coupons found in range', 'woocommerce' ) . '</td></tr>';
263
				}
264
				?>
265
			</table>
266
		</div>
267
		<h4 class="section_title"><span><?php _e( 'Most Discount', 'woocommerce' ); ?></span></h4>
268
		<div class="section">
269
			<table cellspacing="0">
270
				<?php
271
				$most_discount = $this->get_order_report_data( array(
272
					'data' => array(
273
						'order_item_name' => array(
274
							'type'            => 'order_item',
275
							'order_item_type' => 'coupon',
276
							'function'        => '',
277
							'name'            => 'coupon_code'
278
						),
279
						'discount_amount' => array(
280
							'type'            => 'order_item_meta',
281
							'order_item_type' => 'coupon',
282
							'function'        => 'SUM',
283
							'name'            => 'discount_amount'
284
						)
285
					),
286
					'where' => array(
287
						array(
288
							'type'     => 'order_item',
289
							'key'      => 'order_item_type',
290
							'value'    => 'coupon',
291
							'operator' => '='
292
						)
293
					),
294
					'order_by'     => 'discount_amount DESC',
295
					'group_by'     => 'order_item_name',
296
					'limit'        => 12,
297
					'query_type'   => 'get_results',
298
					'filter_range' => true
299
				) );
300
301 View Code Duplication
				if ( ! is_null( $most_discount ) ) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
302
303
					foreach ( $most_discount as $coupon ) {
0 ignored issues
show
The expression $most_discount of type object|integer|double|string|array|boolean is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
304
						echo '<tr class="' . ( in_array( $coupon->coupon_code, $this->coupon_codes ) ? 'active' : '' ) . '">
305
							<td class="count" width="1%">' . wc_price( $coupon->discount_amount ) . '</td>
306
							<td class="name"><a href="' . esc_url( add_query_arg( 'coupon_codes', $coupon->coupon_code ) ) . '">' . $coupon->coupon_code . '</a></td>
307
						</tr>';
308
					}
309
				} else {
310
					echo '<tr><td colspan="3">' . __( 'No coupons found in range', 'woocommerce' ) . '</td></tr>';
311
				}
312
				?>
313
			</table>
314
		</div>
315
		<script type="text/javascript">
316
			jQuery('.section_title').click(function(){
317
				var next_section = jQuery(this).next('.section');
318
319
				if ( jQuery(next_section).is(':visible') )
320
					return false;
321
322
				jQuery('.section:visible').slideUp();
323
				jQuery('.section_title').removeClass('open');
324
				jQuery(this).addClass('open').next('.section').slideDown();
325
326
				return false;
327
			});
328
			jQuery('.section').slideUp( 100, function() {
329
				<?php if ( empty( $this->coupon_codes ) ) : ?>
330
					jQuery('.section_title:eq(1)').click();
331
				<?php else : ?>
332
					jQuery('.section_title:eq(0)').click();
333
				<?php endif; ?>
334
			});
335
		</script>
336
		<?php
337
	}
338
339
	/**
340
	 * Output an export link.
341
	 */
342 View Code Duplication
	public function get_export_button() {
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
343
		$current_range = ! empty( $_GET['range'] ) ? sanitize_text_field( $_GET['range'] ) : '7day';
344
		?>
345
		<a
346
			href="#"
347
			download="report-<?php echo esc_attr( $current_range ); ?>-<?php echo date_i18n( 'Y-m-d', current_time('timestamp') ); ?>.csv"
348
			class="export_csv"
349
			data-export="chart"
350
			data-xaxes="<?php esc_attr_e( 'Date', 'woocommerce' ); ?>"
351
			data-groupby="<?php echo $this->chart_groupby; ?>"
352
		>
353
			<?php _e( 'Export CSV', 'woocommerce' ); ?>
354
		</a>
355
		<?php
356
	}
357
358
	/**
359
	 * Get the main chart.
360
	 *
361
	 * @return string
362
	 */
363
	public function get_main_chart() {
364
		global $wp_locale;
365
366
		// Get orders and dates in range - we want the SUM of order totals, COUNT of order items, COUNT of orders, and the date
367
		$order_coupon_counts_query = array(
368
			'data' => array(
369
				'order_item_name' => array(
370
					'type'            => 'order_item',
371
					'order_item_type' => 'coupon',
372
					'function'        => 'COUNT',
373
					'name'            => 'order_coupon_count'
374
				),
375
				'post_date' => array(
376
					'type'     => 'post_data',
377
					'function' => '',
378
					'name'     => 'post_date'
379
				),
380
			),
381
			'where' => array(
382
				array(
383
					'key'      => 'order_item_type',
384
					'value'    => 'coupon',
385
					'operator' => '='
386
				)
387
			),
388
			'group_by'     => $this->group_by_query,
389
			'order_by'     => 'post_date ASC',
390
			'query_type'   => 'get_results',
391
			'filter_range' => true,
392
			'order_types'  => wc_get_order_types( 'order-count' )
393
		);
394
395
		$order_discount_amounts_query = array(
396
			'data' => array(
397
				'discount_amount' => array(
398
					'type'            => 'order_item_meta',
399
					'order_item_type' => 'coupon',
400
					'function'        => 'SUM',
401
					'name'            => 'discount_amount'
402
				),
403
				'post_date' => array(
404
					'type'     => 'post_data',
405
					'function' => '',
406
					'name'     => 'post_date'
407
				),
408
			),
409
			'where' => array(
410
				array(
411
					'key'      => 'order_item_type',
412
					'value'    => 'coupon',
413
					'operator' => '='
414
				)
415
			),
416
			'group_by'     => $this->group_by_query . ', order_item_name',
417
			'order_by'     => 'post_date ASC',
418
			'query_type'   => 'get_results',
419
			'filter_range' => true,
420
			'order_types'  => wc_get_order_types( 'order-count' )
421
		);
422
423 View Code Duplication
		if ( ! empty( $this->coupon_codes ) ) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
424
			$coupon_code_query = array(
425
				'type'     => 'order_item',
426
				'key'      => 'order_item_name',
427
				'value'    => $this->coupon_codes,
428
				'operator' => 'IN'
429
			);
430
431
			$order_coupon_counts_query['where'][]    = $coupon_code_query;
432
			$order_discount_amounts_query['where'][] = $coupon_code_query;
433
		}
434
435
		$order_coupon_counts    = $this->get_order_report_data( $order_coupon_counts_query );
436
		$order_discount_amounts = $this->get_order_report_data( $order_discount_amounts_query );
437
438
		// Prepare data for report
439
		$order_coupon_counts    = $this->prepare_chart_data( $order_coupon_counts, 'post_date', 'order_coupon_count' , $this->chart_interval, $this->start_date, $this->chart_groupby );
440
		$order_discount_amounts = $this->prepare_chart_data( $order_discount_amounts, 'post_date', 'discount_amount', $this->chart_interval, $this->start_date, $this->chart_groupby );
441
442
		// Encode in json format
443
		$chart_data = json_encode( array(
444
			'order_coupon_counts'    => array_values( $order_coupon_counts ),
445
			'order_discount_amounts' => array_values( $order_discount_amounts )
446
		) );
447
		?>
448
		<div class="chart-container">
449
			<div class="chart-placeholder main"></div>
450
		</div>
451
		<script type="text/javascript">
452
			var main_chart;
453
454
			jQuery(function(){
455
				var order_data = jQuery.parseJSON( '<?php echo $chart_data; ?>' );
456
457
				var drawGraph = function( highlight ) {
458
					var series = [
459
						{
460
							label: "<?php echo esc_js( __( 'Number of coupons used', 'woocommerce' ) ) ?>",
461
							data: order_data.order_coupon_counts,
462
							color: '<?php echo $this->chart_colours['coupon_count' ]; ?>',
463
							bars: { fillColor: '<?php echo $this->chart_colours['coupon_count' ]; ?>', fill: true, show: true, lineWidth: 0, barWidth: <?php echo $this->barwidth; ?> * 0.5, align: 'center' },
464
							shadowSize: 0,
465
							hoverable: false
466
						},
467
						{
468
							label: "<?php echo esc_js( __( 'Discount amount', 'woocommerce' ) ) ?>",
469
							data: order_data.order_discount_amounts,
470
							yaxis: 2,
471
							color: '<?php echo $this->chart_colours['discount_amount']; ?>',
472
							points: { show: true, radius: 5, lineWidth: 3, fillColor: '#fff', fill: true },
473
							lines: { show: true, lineWidth: 4, fill: false },
474
							shadowSize: 0,
475
							<?php echo $this->get_currency_tooltip(); ?>
476
						}
477
					];
478
479
					if ( highlight !== 'undefined' && series[ highlight ] ) {
480
						highlight_series = series[ highlight ];
481
482
						highlight_series.color = '#9c5d90';
483
484
						if ( highlight_series.bars )
485
							highlight_series.bars.fillColor = '#9c5d90';
486
487
						if ( highlight_series.lines ) {
488
							highlight_series.lines.lineWidth = 5;
489
						}
490
					}
491
492
					main_chart = jQuery.plot(
493
						jQuery('.chart-placeholder.main'),
494
						series,
495
						{
496
							legend: {
497
								show: false
498
							},
499
							grid: {
500
								color: '#aaa',
501
								borderColor: 'transparent',
502
								borderWidth: 0,
503
								hoverable: true
504
							},
505
							xaxes: [ {
506
								color: '#aaa',
507
								position: "bottom",
508
								tickColor: 'transparent',
509
								mode: "time",
510
								timeformat: "<?php if ( $this->chart_groupby == 'day' ) echo '%d %b'; else echo '%b'; ?>",
511
								monthNames: <?php echo json_encode( array_values( $wp_locale->month_abbrev ) ) ?>,
512
								tickLength: 1,
513
								minTickSize: [1, "<?php echo $this->chart_groupby; ?>"],
514
								font: {
515
									color: "#aaa"
516
								}
517
							} ],
518
							yaxes: [
519
								{
520
									min: 0,
521
									minTickSize: 1,
522
									tickDecimals: 0,
523
									color: '#ecf0f1',
524
									font: { color: "#aaa" }
525
								},
526
								{
527
									position: "right",
528
									min: 0,
529
									tickDecimals: 2,
530
									alignTicksWithAxis: 1,
531
									color: 'transparent',
532
									font: { color: "#aaa" }
533
								}
534
							],
535
						}
536
					);
537
538
					jQuery('.chart-placeholder').resize();
539
				}
540
541
				drawGraph();
542
543
				jQuery('.highlight_series').hover(
544
					function() {
545
						drawGraph( jQuery(this).data('series') );
546
					},
547
					function() {
548
						drawGraph();
549
					}
550
				);
551
			});
552
		</script>
553
		<?php
554
	}
555
}
556