Completed
Push — master ( f7580f...170d41 )
by
unknown
13:34
created

wps_statistics_ctr::add_scripts()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 13
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 10
nc 2
nop 1
dl 0
loc 13
rs 9.4285
c 0
b 0
f 0
1
<?php if ( !defined( 'ABSPATH' ) ) exit;
2
3
class wps_statistics_ctr {
4
5
	private $wps_stats_mdl;
6
7
	function __construct() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
8
		// WP Main Actions
9
		add_action( 'admin_menu', array(&$this, 'register_stats_menu'), 250);
10
		add_action( 'save_post', array( &$this, 'wps_statistics_save_customer_infos') );
11
		add_action( 'add_meta_boxes', array( &$this, 'add_customer_meta_box'), 1 );
12
13
		// Add Javascript Files & CSS File in admin
14
		add_action( 'admin_enqueue_scripts', array( $this, 'add_scripts' ) );
15
16
		add_action( 'wp_ajax_wps_statistics_custom_date_view', array( $this, 'wps_statistics_custom_date_view' ) );
17
18
		$this->wps_stats_mdl = new wps_statistics_mdl();
19
	}
20
21
	/**
22
	* Add Javascript & CSS files
23
	*/
24
	function add_scripts( $hook ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
25
		global $current_screen;
26
		if( ! in_array( $current_screen->post_type, array( WPSHOP_NEWTYPE_IDENTIFIER_CUSTOMERS ), true ) && $hook != 'wpshop_shop_order_page_wpshop_statistics' )
27
			return;
28
29
		wp_enqueue_script( 'wps_statistics_js_chart', WPSHOP_JS_URL . 'Chart.js' );
30
		wp_enqueue_script( 'jquery' );
31
		wp_enqueue_script( 'jquery-ui-datepicker' );
32
		wp_enqueue_script( 'jquery-form' );
33
34
		wp_register_style( 'jquery-ui-wpsstats', '//code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css', '', WPSHOP_VERSION );
35
		wp_enqueue_style( 'jquery-ui-wpsstats' );
36
	}
37
38
	/**
39
	 * Add Meta Boxes to exclude customers of WPShop Statistics
40
	 */
41
	function add_customer_meta_box() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
42
		global $post;
43
		add_meta_box( 'wps_statistics_customer', __( 'Statistics', 'wps_price' ), array( &$this, 'wps_statistics_meta_box_content' ), WPSHOP_NEWTYPE_IDENTIFIER_CUSTOMERS, 'side', 'low' );
44
	}
45
46
	/**
47
	 * Meta box content to exclude customers of statistics
48
	 */
49
	function wps_statistics_meta_box_content() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
50
		global $post;
51
		$user_meta = '';
52
		if ( !empty($post) && !empty($post->post_author) ) {
53
			$user_meta = get_user_meta( $post->post_author, 'wps_statistics_exclude_customer', true );
54
		}
55
		$output = '<input type="checkbox" name="wps_statistics_exclude_customer" id="wps_statistics_exclude_customer" ' .( (!empty($user_meta) ) ? 'checked="checked"' : '' ). '/> <label for="wps_statistics_exclude_customer">' .__('Exclude this customer from WPShop Statistics', 'wpshop'). '</label>';
56
		echo $output;
57
	}
58
59
	/**
60
	 * Save action to exclude customer of statistics
61
	 */
62
	function wps_statistics_save_customer_infos() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
63
		$action = !empty( $_POST['action'] ) ? sanitize_text_field( $_POST['action'] ) : '';
64
		$post_type = !empty( $_POST['post_type'] ) ? sanitize_text_field( $_POST['post_type'] ) : '';
65
		$post_id = !empty( $_POST['post_ID'] ) ? (int) $_POST['post_ID'] : 0;
66
		$wps_statistics_exclude_customer = isset( $_POST['wps_statistics_exclude_customer'] ) ? (int) $_POST['wps_statistics_exclude_customer'] : 0;
67
68
		if ( !empty($action) && $action != 'autosave' && !empty($post_type) && $post_type == WPSHOP_NEWTYPE_IDENTIFIER_CUSTOMERS ) {
69
			$customer_def = get_post( $post_id );
70
			if( isset( $wps_statistics_exclude_customer ) ) {
71
				update_user_meta( $customer_def->post_author, 'wps_statistics_exclude_customer', $wps_statistics_exclude_customer );
72
			}
73
		}
74
	}
75
76
	/**
77
	 * Register statistics Menu
78
	 */
79
	function register_stats_menu() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
80
		add_submenu_page( 'edit.php?post_type=' . WPSHOP_NEWTYPE_IDENTIFIER_ORDER, __('Statistics', 'wpshop' ), __('Statistics', 'wpshop'), 'wpshop_view_statistics', 'wpshop_statistics', array($this, 'wps_display_statistics'));
81
	}
82
83
	/**
84
	 * Display Statistics Interface
85
	 */
86
	function wps_display_statistics() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
87
		$shop_orders = $this->wps_stats_mdl->wps_orders_all( );
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $shop_orders is correct as $this->wps_stats_mdl->wps_orders_all() (which targets wps_statistics_mdl::wps_orders_all()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
88
89
		$main_stats_count = 5;
90
91
		$ordered_customers = array();
92
		foreach ( $shop_orders as $order ) {
0 ignored issues
show
Bug introduced by
The expression $shop_orders of type null is not traversable.
Loading history...
93
			$user_id = $order['order_postmeta']['customer_id'];
94
			$customer_id = null;
95
			$args = array(
96
				'post_type'				=> WPSHOP_NEWTYPE_IDENTIFIER_CUSTOMERS,
97
				'author'					=> $user_id,
98
				'orderby'	 				=> 'post_date',
99
				'order'	 					=> 'ASC',
100
				'post_status'	 		=> 'all',
101
				'posts_per_page' 	=>	1,
102
			);
103
			$customer = new WP_Query( $args );
104
105
			if ( ! isset( $ordered_customers[ $user_id ]['count'] ) ) {
106
				$ordered_customers[ $user_id ]['count'] = 0;
107
				$ordered_customers[ $user_id ]['total_amount'] = 0;
108
			}
109
			$ordered_customers[ $user_id ]['count']++;
110
			$ordered_customers[ $user_id ]['id'] = $user_id;
111
			$ordered_customers[ $user_id ]['post_id'] = $customer->post->ID;
112
			$ordered_customers[ $user_id ]['name'] = ( !empty($order['order_info']) && !empty($order['order_info']['billing']) && !empty($order['order_info']['billing']['address']) && !empty($order['order_info']['billing']['address']['address_last_name']) && !empty($order['order_info']['billing']['address']['address_first_name']) ) ? $order['order_info']['billing']['address']['address_first_name'].' '.$order['order_info']['billing']['address']['address_last_name'] : '';;
113
			$ordered_customers[ $user_id ]['total_amount'] += $order['order_postmeta']['order_grand_total'];
114
		}
115
116
		require( wpshop_tools::get_template_part( WPS_STATISTICS_DIR, WPS_STATISTICS_TEMPLATES_MAIN_DIR, "backend", "wps-statistics") );
117
	}
118
119
	/**
120
	 * Get the average duration between
121
	 *
122
	 * @param  [type] $order_list [description]
0 ignored issues
show
Documentation introduced by
The doc-type [type] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
123
	 *
124
	 * @return [type]             [description]
0 ignored issues
show
Documentation introduced by
The doc-type [type] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
125
	 */
126
	function get_average_time_between_orders( $order_list ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
127
		$time_between_orders = 0;
128
		$last_date = null;
129
		foreach ( $order_list as $order ) {
130
			if ( null !== $last_date ) {
131
				$last_order = new DateTime( $last_date );
132
				$current_order = new DateTime( $order['order_postmeta']['order_date'] );
133
				$time_between_orders += $last_order->getTimestamp() - $current_order->getTimestamp();
134
			} else {
0 ignored issues
show
Unused Code introduced by
This else statement is empty and can be removed.

This check looks for the else branches of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These else branches can be removed.

if (rand(1, 6) > 3) {
print "Check failed";
} else {
    //print "Check succeeded";
}

could be turned into

if (rand(1, 6) > 3) {
    print "Check failed";
}

This is much more concise to read.

Loading history...
135
136
			}
137
138
			$last_date = $order['order_postmeta']['order_date'];
139
		}
140
141
		return round( $time_between_orders / count( $order_list ) );
142
	}
143
144
	/**
145
	 * Check if the shop is out of bounds for time since last order
146
	 *
147
	 * @return boolean The boolean state allowing to know if the shop is out of bounds for time since last order
148
	 */
149
	function check_current_time_since_last_order( $list_orders ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
150
		$average_check = array(
151
			'status'		=> false,
152
			'last_date'	=> null,
153
			'average'		=> null,
154
			'duration'	=> null,
155
		);
156
		$current_date = new DateTime( current_time( 'Y-m-d H:i:s', 0 ) );
157
158
		if ( ! empty( $list_orders ) ) {
159
			$last_order = array_slice( $list_orders, 0, 1 );
160
			foreach ( $last_order as $order ) {
161
				$average_check['last_date'] = $order['order_postmeta']['order_date'];
162
			}
163
			$last_order_dateTime = new DateTime( $average_check['last_date'] );
164
165
			$duration_since_last_order = $current_date->getTimestamp() - $last_order_dateTime->getTimestamp();
166
			$average_check['duration'] = $duration_since_last_order;
167
			$average_check['average'] = $this->get_average_time_between_orders( $list_orders );
168
169
			$average_check['status'] = ( $average_check['duration'] > $average_check['average'] ? true : false );
170
		}
171
172
		return $average_check;
173
	}
174
175
	/**
176
	 * Main Statistics output
177
	 */
178
	function wps_display_main_statistics( $shop_orders = null ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
179
		global $current_month_offset;
180
181
		if ( null === $shop_orders ) {
182
			$shop_orders = $this->wps_stats_mdl->wps_orders_all();
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $shop_orders is correct as $this->wps_stats_mdl->wps_orders_all() (which targets wps_statistics_mdl::wps_orders_all()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
Unused Code introduced by
$shop_orders is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
183
		}
184
185
		$current_month_offset = (int) current_time( 'm' );
186
		$current_month_offset = isset( $_GET['month'] ) ? (int) $_GET['month'] : $current_month_offset;
187
188
		$current_month_start = date( 'Y-m-d 00:00:00', strtotime( 'first day of this month', time() ) );
189
		$current_month_end = date( 'Y-m-d 23:59:59', strtotime( 'last day of this month', time() ) );
190
191
		$last_month_start = date( 'Y-m-d 00:00:00', strtotime( 'first day of last month', time() ) );
192
		$last_month_end = date( 'Y-m-d 23:59:59', strtotime( 'last day of last month', time() ) );
193
		$one_month_ago = date( 'Y-m-d 23:59:59', strtotime( '-1 month', time() ) );
194
195
		$dates = array(
0 ignored issues
show
Unused Code introduced by
$dates is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
196
			__( 'Current month', 'wpshop' ) => array(
197
				'after'			=> $current_month_start,
198
				'before'		=> $current_month_end,
199
				'inclusive'	=> true,
200
			),
201
			sprintf( __( 'One month ago (%s)', 'wpshop' ), mysql2date( get_option( 'date_format' ), $one_month_ago, true ) ) => array(
202
				'after'			=> $last_month_start,
203
				'before'		=> $one_month_ago,
204
				'inclusive'	=> true,
205
			),
206
			__( 'Last month', 'wpshop' ) => array(
207
				'after'			=> $last_month_start,
208
				'before'		=> $last_month_end,
209
				'inclusive'	=> true,
210
			),
211
			__( 'From the beginning', 'wpshop' ) => null,
212
		);
213
214
		require_once( wpshop_tools::get_template_part( WPS_STATISTICS_DIR, WPS_STATISTICS_TEMPLATES_MAIN_DIR, 'backend', 'wps_statistics_main' ) );
215
	}
216
217
	/**
218
	 * Display custom Statistics area. Allows to choose date for stats displaying
219
	 *
220
	 * @param array  $shop_orders The list of orders to use for stats.
221
	 * @param string $start      Optionnal. The start date to get stats for.
222
	 * @param string $end        Optionnal. The end date to get stats for.
223
	 */
224
	function wps_display_custom_statistics( $shop_orders, $start = null, $end = null ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
225
		$current_month_start = date( 'Y-m-d', strtotime( 'first day of this month', time() ) );
226
		$current_month_end = date( 'Y-m-d', strtotime( 'last day of this month', time() ) );
227
228
		$last_month_start = date( 'Y-m-d', strtotime( 'first day of last month', time() ) );
229
		$last_month_end = date( 'Y-m-d', strtotime( 'last day of last month', time() ) );
230
231
		$date_start = null !== $start ? $start : $current_month_start;
232
		$date_end = null !== $end ? $end : $current_month_end;
233
234
		$stats_translations = array(
235
			'numberOfSales'		=> __( 'Number of sales', 'wpshop' ),
236
			'sales'						=> __( 'sales', 'wpshop' ),
237
			'salesAmount'			=> __( 'Sales amount', 'wpshop' ),
238
			'wpshopCurrency'	=> wpshop_tools::wpshop_get_currency(),
239
		);
240
241
		$orders_total_amount = $orders_total_shipping_cost = $order_count = 0;
242
		$orders_number_stats = $orders_amount_stats = array();
243
		if ( ! empty( $shop_orders ) ) {
244
			foreach ( $shop_orders as $order ) {
245
				$order_data = $order['order_postmeta'];
246
				if ( ( $date_start <= $order_data['order_date'] ) && ( $date_end >= $order_data['order_date'] ) ) {
247
					$orders_total_amount += $order_data['order_grand_total'];
248
					$order_count++;
249
250
					$time = strtotime( date( 'Ymd', strtotime( $order_data['order_date'] ) ) ) . '000';
251
					if ( ! isset( $orders_number_stats[ $time ] ) ) {
252
						$orders_number_stats[ $time ] = 0;
253
					}
254
					$orders_number_stats[ $time ]++;
255
256
					if ( ! isset( $orders_amount_stats[ $time ] ) ) {
257
						$orders_amount_stats[ $time ] = 0;
258
					}
259
					$orders_amount_stats[ $time ] += $order_data['order_grand_total'];
260
261
					$orders_total_shipping_cost += $order_data['order_shipping_cost'];
262
				}
263
			}
264
		}
265
266
		$orders_number_for_stats = null;
267
		if ( ! empty( $orders_number_stats ) ) {
268
			$orders_numbers = array();
269
			foreach ( $orders_number_stats as $time => $number ) {
270
				$orders_numbers[] = "[$time, $number]";
271
			}
272
			$orders_number_for_stats = implode( ',', $orders_numbers );
273
		}
274
275
		$orders_amount_for_stats = null;
276
		if ( ! empty( $orders_amount_stats ) ) {
277
			$orders_amounts = array();
278
			foreach ( $orders_amount_stats as $time => $amount ) {
279
				$orders_amounts[] = "[$time, $amount]";
280
			}
281
			$orders_amount_for_stats = implode( ',', $orders_amounts );
282
		}
283
284
		$user_subscription_number = new WP_User_Query( array(
285
			'date_query' => array(
286
				array(
287
					'after'			=> $date_start,
288
					'before'		=> $date_end,
289
					'inclusive'	=> true,
290
				),
291
			),
292
			'count_total' => true,
293
		) );
294
295
		require( wpshop_tools::get_template_part( WPS_STATISTICS_DIR, WPS_STATISTICS_TEMPLATES_MAIN_DIR, 'backend', 'wps_statistics_custom' ) );
296
	}
297
298
	/**
299
	 * Ajax callback - Display custom statistics for given date
300
	 */
301
	function wps_statistics_custom_date_view() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
302
		check_ajax_referer( 'wps_statistics_custom_date_view' );
303
304
		$start_date = ! empty( $_POST ) && ! empty( $_POST['wps_statistics_start_date'] ) ? sanitize_text_field( $_POST['wps_statistics_start_date'] ) : date( 'Y-m-d', strtotime( 'first day of this month', time() ) );
305
		$end_date = ! empty( $_POST ) && ! empty( $_POST['wps_statistics_end_date'] ) ? sanitize_text_field( $_POST['wps_statistics_end_date'] ) : date( 'Y-m-d', strtotime( 'last day of this month', time() ) );
306
307
		$order_list = $this->wps_stats_mdl->wps_orders_all( array(
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $order_list is correct as $this->wps_stats_mdl->wp...'inclusive' => true)))) (which targets wps_statistics_mdl::wps_orders_all()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
308
			'date_query' => array(
309
				array(
310
					'after'			=> $date_start,
0 ignored issues
show
Bug introduced by
The variable $date_start does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
311
					'before'		=> $date_end,
0 ignored issues
show
Bug introduced by
The variable $date_end does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
312
					'inclusive'	=> true,
313
				),
314
			),
315
		) );
316
317
		ob_start();
318
		$this->wps_display_custom_statistics( $order_list, $start_date, $end_date );
0 ignored issues
show
Documentation introduced by
$order_list is of type null, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
319
		$output = ob_get_clean();
320
321
		wp_die( $output );
322
	}
323
324
}
325