Completed
Pull Request — master (#11797)
by Aristeides
08:16
created

WC_REST_System_Status_Controller   F

Complexity

Total Complexity 64

Size/Duplication

Total Lines 800
Duplicated Lines 5 %

Coupling/Cohesion

Components 2
Dependencies 4

Importance

Changes 4
Bugs 1 Features 0
Metric Value
c 4
b 1
f 0
dl 40
loc 800
rs 3.862
wmc 64
lcom 2
cbo 4

12 Methods

Rating   Name   Duplication   Size   Complexity  
F get_environment_info() 6 71 17
A register_routes() 11 11 1
A get_items_permissions_check() 0 6 2
A get_items() 0 17 4
B get_item_schema() 0 333 1
A get_item_mappings() 0 10 1
A get_settings() 0 22 2
A get_collection_params() 0 5 1
C get_pages() 0 63 8
B get_database_info() 0 36 3
C get_active_plugins() 17 67 10
C get_theme_info() 6 67 14

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like WC_REST_System_Status_Controller often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use WC_REST_System_Status_Controller, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * REST API WC System Status controller
4
 *
5
 * Handles requests to the /system_status endpoint.
6
 *
7
 * @author   WooThemes
8
 * @category API
9
 * @package  WooCommerce/API
10
 * @since    2.7.0
11
 */
12
13
if ( ! defined( 'ABSPATH' ) ) {
14
	exit;
15
}
16
17
/**
18
 * @package WooCommerce/API
19
 * @extends WC_REST_Controller
20
 */
21
class WC_REST_System_Status_Controller extends WC_REST_Controller {
22
23
	/**
24
	 * Endpoint namespace.
25
	 *
26
	 * @var string
27
	 */
28
	protected $namespace = 'wc/v1';
29
30
	/**
31
	 * Route base.
32
	 *
33
	 * @var string
34
	 */
35
	protected $rest_base = 'system_status';
36
37
	/**
38
	 * Register the route for /system_status
39
	 */
40 View Code Duplication
	public function register_routes() {
0 ignored issues
show
Duplication introduced by
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...
41
        register_rest_route( $this->namespace, '/' . $this->rest_base, array(
42
			array(
43
				'methods'             => WP_REST_Server::READABLE,
44
				'callback'            => array( $this, 'get_items' ),
45
                'permission_callback' => array( $this, 'get_items_permissions_check' ),
46
				'args'                => $this->get_collection_params(),
47
			),
48
			'schema' => array( $this, 'get_public_item_schema' ),
49
		) );
50
	}
51
52
    /**
53
	 * Check whether a given request has permission to view system status.
54
	 *
55
	 * @param  WP_REST_Request $request Full details about the request.
56
	 * @return WP_Error|boolean
57
	 */
58
	public function get_items_permissions_check( $request ) {
59
        if ( ! wc_rest_check_manager_permissions( 'system_status', 'read' ) ) {
60
        	return new WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you cannot list resources.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
61
		}
62
		return true;
63
	}
64
65
    /**
66
	 * Get a system status info, by section.
67
	 *
68
	 * @param WP_REST_Request $request Full details about the request.
69
	 * @return WP_Error|WP_REST_Response
70
	 */
71
	public function get_items( $request ) {
72
		$schema    = $this->get_item_schema();
73
		$mappings  = $this->get_item_mappings();
74
		$response  = array();
75
76
		foreach ( $mappings as $section => $values ) {
77
			settype( $values, $schema['properties'][ $section ]['type'] );
78
			foreach ( $values as $key => $value ) {
79
				if ( isset( $schema['properties'][ $section ]['properties'][ $key ]['type'] ) ) {
80
					settype( $values[ $key ], $schema['properties'][ $section ]['properties'][ $key ]['type'] );
81
				}
82
			}
83
			$response[ $section ] = $values;
84
		}
85
86
		return rest_ensure_response( $response );
87
	}
88
89
    /**
90
	 * Get the system status schema, conforming to JSON Schema.
91
	 *
92
	 * @return array
93
	 */
94
	public function get_item_schema() {
95
		$schema = array(
96
			'$schema'    => 'http://json-schema.org/draft-04/schema#',
97
			'title'      => 'system_status',
98
			'type'       => 'object',
99
			'properties' => array(
100
				'environment' => array(
101
					'description' => __( 'Environment', 'woocommerce' ),
102
					'type'        => 'array',
103
					'context'     => array( 'view', 'edit' ),
104
					'properties'  => array(
105
						'home_url' => array(
106
							'description' => __( 'Home URL', 'woocommerce' ),
107
							'type'        => 'string',
108
		                    'format'      => 'uri',
109
							'context'     => array( 'view', 'edit' ),
110
						),
111
		                'site_url' => array(
112
		                    'description' => __( 'Site URL', 'woocommerce' ),
113
		                    'type'        => 'string',
114
		                    'format'      => 'uri',
115
		                    'context'     => array( 'view', 'edit' ),
116
		                ),
117
		                'wc_version' => array(
118
		                    'description' => __( 'WooCommerce Version', 'woocommerce' ),
119
		                    'type'        => 'string',
120
		                    'context'     => array( 'view', 'edit' ),
121
		                ),
122
		                'log_directory' => array(
123
		                    'description' => __( 'Log Directory', 'woocommerce' ),
124
		                    'type'        => 'string',
125
		                    'context'     => array( 'view', 'edit' ),
126
		                ),
127
		                'log_directory_writable' => array(
128
		                    'description' => __( 'Is Log Directory Writable?', 'woocommerce' ),
129
		                    'type'        => 'boolean',
130
		                    'context'     => array( 'view', 'edit' ),
131
		                ),
132
		                'wp_version' => array(
133
		                    'description' => __( 'WordPress Version', 'woocommerce' ),
134
		                    'type'        => 'string',
135
		                    'context'     => array( 'view', 'edit' ),
136
		                ),
137
		                'wp_multisite' => array(
138
		                    'description' => __( 'Is WordPress Multisite?', 'woocommerce' ),
139
		                    'type'        => 'boolean',
140
		                    'context'     => array( 'view', 'edit' ),
141
		                ),
142
		                'wp_memory_limit' => array(
143
		                    'description' => __( 'WordPress Memory Limit', 'woocommerce' ),
144
		                    'type'        => 'integer',
145
		                    'context'     => array( 'view', 'edit' ),
146
		                ),
147
		                'wp_debug_mode' => array(
148
		                    'description' => __( 'Is WordPress Debug Mode Active?', 'woocommerce' ),
149
		                    'type'        => 'boolean',
150
		                    'context'     => array( 'view', 'edit' ),
151
		                ),
152
		                'wp_cron' => array(
153
		                    'description' => __( 'Are WordPress Cron Jobs Enabled?', 'woocommerce' ),
154
		                    'type'        => 'boolean',
155
		                    'context'     => array( 'view', 'edit' ),
156
		                ),
157
		                'language' => array(
158
		                    'description' => __( 'WordPress Language', 'woocommerce' ),
159
		                    'type'        => 'string',
160
		                    'context'     => array( 'view', 'edit' ),
161
		                ),
162
		                'server_info' => array(
163
		                    'description' => __( 'Server Info', 'woocommerce' ),
164
		                    'type'        => 'string',
165
		                    'context'     => array( 'view', 'edit' ),
166
		                ),
167
		                'php_version' => array(
168
		                    'description' => __( 'PHP Version', 'woocommerce' ),
169
		                    'type'        => 'string',
170
		                    'context'     => array( 'view', 'edit' ),
171
		                ),
172
		                'php_post_max_size' => array(
173
		                    'description' => __( 'PHP Post Max Size', 'woocommerce' ),
174
		                    'type'        => 'integer',
175
		                    'context'     => array( 'view', 'edit' ),
176
		                ),
177
		                'php_max_execution_time' => array(
178
		                    'description' => __( 'PHP Max Execution Time', 'woocommerce' ),
179
		                    'type'        => 'integer',
180
		                    'context'     => array( 'view', 'edit' ),
181
		                ),
182
		                'php_max_input_vars' => array(
183
		                    'description' => __( 'PHP Max Input Vars', 'woocommerce' ),
184
		                    'type'        => 'integer',
185
		                    'context'     => array( 'view', 'edit' ),
186
		                ),
187
		                'curl_version' => array(
188
		                    'description' => __( 'cURL Version', 'woocommerce' ),
189
		                    'type'        => 'string',
190
		                    'context'     => array( 'view', 'edit' ),
191
		                ),
192
						'suhosin_installed' => array(
193
							'description' => __( 'Is SUHOSIN Installed?', 'woocommerce' ),
194
							'type'        => 'boolean',
195
							'context'     => array( 'view', 'edit' ),
196
						),
197
						'max_upload_size' => array(
198
							'description' => __( 'Max Upload Size', 'woocommerce' ),
199
							'type'        => 'integer',
200
							'context'     => array( 'view', 'edit' ),
201
						),
202
						'mysql_version' => array(
203
							'description' => __( 'MySQL Version', 'woocommerce' ),
204
							'type'        => 'string',
205
							'context'     => array( 'view', 'edit' ),
206
						),
207
						'default_timezone' => array(
208
							'description' => __( 'Default Timezone', 'woocommerce' ),
209
							'type'        => 'string',
210
							'context'     => array( 'view', 'edit' ),
211
						),
212
						'fsockopen_or_curl_enabled' => array(
213
							'description' => __( 'Is fsockopen/cURL Enabled?', 'woocommerce' ),
214
							'type'        => 'boolean',
215
							'context'     => array( 'view', 'edit' ),
216
						),
217
						'soapclient_enabled' => array(
218
							'description' => __( 'Is SoapClient Class Enabled?', 'woocommerce' ),
219
							'type'        => 'boolean',
220
							'context'     => array( 'view', 'edit' ),
221
						),
222
						'domdocument_enabled' => array(
223
							'description' => __( 'Is DomDocument Class Enabled?', 'woocommerce' ),
224
							'type'        => 'boolean',
225
							'context'     => array( 'view', 'edit' ),
226
						),
227
						'gzip_enabled' => array(
228
							'description' => __( 'Is GZip Enabled?', 'woocommerce' ),
229
							'type'        => 'boolean',
230
							'context'     => array( 'view', 'edit' ),
231
						),
232
						'mbstring_enabled' => array(
233
							'description' => __( 'Is mbstring Enabled?', 'woocommerce' ),
234
							'type'        => 'boolean',
235
							'context'     => array( 'view', 'edit' ),
236
						),
237
						'remote_post_successful' => array(
238
							'description' => __( 'Remote POST Successful?', 'woocommerce' ),
239
							'type'        => 'boolean',
240
							'context'     => array( 'view', 'edit' ),
241
						),
242
						'remote_post_response' => array(
243
							'description' => __( 'Remote POST Response', 'woocommerce' ),
244
							'type'        => 'string',
245
							'context'     => array( 'view', 'edit' ),
246
						),
247
						'remote_get_successful' => array(
248
							'description' => __( 'Remote GET Successful?', 'woocommerce' ),
249
							'type'        => 'boolean',
250
							'context'     => array( 'view', 'edit' ),
251
						),
252
						'remote_get_response' => array(
253
							'description' => __( 'Remote GET Response', 'woocommerce' ),
254
							'type'        => 'string',
255
							'context'     => array( 'view', 'edit' ),
256
						),
257
					),
258
				),
259
				'database' => array(
260
					'description' => __( 'Database', 'woocommerce' ),
261
					'type'        => 'array',
262
					'context'     => array( 'view', 'edit' ),
263
					'properties'  => array(
264
						'wc_database_version' => array(
265
							'description' => __( 'WC Database Version', 'woocommerce' ),
266
							'type'        => 'string',
267
							'context'     => array( 'view', 'edit' ),
268
						),
269
						'database_prefix' => array(
270
							'description' => __( 'Database Prefix', 'woocommerce' ),
271
							'type'        => 'string',
272
							'context'     => array( 'view', 'edit' ),
273
						),
274
						'maxmind_geoip_database' => array(
275
							'description' => __( 'MaxMind GeoIP Database', 'woocommerce' ),
276
							'type'        => 'string',
277
							'context'     => array( 'view', 'edit' ),
278
						),
279
						'database_tables' => array(
280
							'description' => __( 'Database Tables', 'woocommerce' ),
281
							'type'        => 'array',
282
							'context'     => array( 'view', 'edit' ),
283
						),
284
					),
285
				),
286
				'active_plugins' => array(
287
					'description' => __( 'Active Plugins', 'woocommerce' ),
288
					'type'        => 'array',
289
					'context'     => array( 'view', 'edit' ),
290
				),
291
				'theme' => array(
292
					'description' => __( 'Theme', 'woocommerce' ),
293
					'type'        => 'array',
294
					'context'     => array( 'view', 'edit' ),
295
					'properties'  => array(
296
						'name' => array(
297
							'description' => __( 'Theme Name', 'woocommerce' ),
298
							'type'        => 'string',
299
							'context'     => array( 'view', 'edit' ),
300
						),
301
						'version' => array(
302
							'description' => __( 'Theme Version', 'woocommerce' ),
303
							'type'        => 'string',
304
							'context'     => array( 'view', 'edit' ),
305
						),
306
						'version_latest' => array(
307
							'description' => __( 'Latest Version Of Theme', 'woocommerce' ),
308
							'type'        => 'string',
309
							'context'     => array( 'view', 'edit' ),
310
						),
311
						'author_url' => array(
312
							'description' => __( 'Theme Author URL', 'woocommerce' ),
313
							'type'        => 'string',
314
							'format'      => 'uri',
315
							'context'     => array( 'view', 'edit' ),
316
						),
317
						'is_child_theme' => array(
318
							'description' => __( 'Is this theme a child theme?', 'woocommerce' ),
319
							'type'        => 'boolean',
320
							'context'     => array( 'view', 'edit' ),
321
						),
322
						'has_woocommerce_support' => array(
323
							'description' => __( 'Does the theme declare WooCommerce support?', 'woocommerce' ),
324
							'type'        => 'boolean',
325
							'context'     => array( 'view', 'edit' ),
326
						),
327
						'has_woocommerce_file' => array(
328
							'description' => __( 'Does the theme have a woocommerce.php file?', 'woocommerce' ),
329
							'type'        => 'boolean',
330
							'context'     => array( 'view', 'edit' ),
331
						),
332
						'has_outdated_templates' => array(
333
							'description' => __( 'Does this theme have outdated templates?', 'woocommerce' ),
334
							'type'        => 'boolean',
335
							'context'     => array( 'view', 'edit' ),
336
						),
337
						'overrides' => array(
338
							'description' => __( 'Template Overrides', 'woocommerce' ),
339
							'type'        => 'array',
340
							'context'     => array( 'view', 'edit' ),
341
						),
342
						'parent_name' => array(
343
							'description' => __( 'Parent Theme Name', 'woocommerce' ),
344
							'type'        => 'string',
345
							'context'     => array( 'view', 'edit' ),
346
						),
347
						'parent_version' => array(
348
							'description' => __( 'Parent Theme Version', 'woocommerce' ),
349
							'type'        => 'string',
350
							'context'     => array( 'view', 'edit' ),
351
						),
352
						'parent_author_url' => array(
353
							'description' => __( 'Parent Theme Author URL', 'woocommerce' ),
354
							'type'        => 'string',
355
							'format'      => 'uri',
356
							'context'     => array( 'view', 'edit' ),
357
						),
358
					),
359
				),
360
				'settings' => array(
361
					'description' => __( 'Settings', 'woocommerce' ),
362
					'type'        => 'array',
363
					'context'     => array( 'view', 'edit' ),
364
					'properties'  => array(
365
						'api_enabled' => array(
366
							'description' => __( 'REST API Enabled?', 'woocommerce' ),
367
							'type'        => 'boolean',
368
							'context'     => array( 'view', 'edit' ),
369
						),
370
						'force_ssl' => array(
371
							'description' => __( 'SSL Forced?', 'woocommerce' ),
372
							'type'        => 'boolean',
373
							'context'     => array( 'view', 'edit' ),
374
						),
375
						'currency' => array(
376
							'description' => __( 'Currency', 'woocommerce' ),
377
							'type'        => 'string',
378
							'context'     => array( 'view', 'edit' ),
379
						),
380
						'currency_symbol' => array(
381
							'description' => __( 'Currency Symbol', 'woocommerce' ),
382
							'type'        => 'string',
383
							'context'     => array( 'view', 'edit' ),
384
						),
385
						'currency_position' => array(
386
							'description' => __( 'Currency Position', 'woocommerce' ),
387
							'type'        => 'string',
388
							'context'     => array( 'view', 'edit' ),
389
						),
390
						'thousand_separator' => array(
391
							'description' => __( 'Thousand Separator', 'woocommerce' ),
392
							'type'        => 'string',
393
							'context'     => array( 'view', 'edit' ),
394
						),
395
						'decimal_separator' => array(
396
							'description' => __( 'Decimal Separator', 'woocommerce' ),
397
							'type'        => 'string',
398
							'context'     => array( 'view', 'edit' ),
399
						),
400
						'number_of_decimals' => array(
401
							'description' => __( 'Number of Decimals', 'woocommerce' ),
402
							'type'        => 'integer',
403
							'context'     => array( 'view', 'edit' ),
404
						),
405
						'geolocation_enabled' => array(
406
							'description' => __( 'Geolocation Enabled?', 'woocommerce' ),
407
							'type'        => 'boolean',
408
							'context'     => array( 'view', 'edit' ),
409
						),
410
						'taxonomies' => array(
411
							'description' => __( 'Taxonomy Terms for Product/Order Statuses', 'woocommerce' ),
412
							'type'        => 'array',
413
							'context'     => array( 'view', 'edit' ),
414
						),
415
					),
416
				),
417
				'pages' => array(
418
					'description' => __( 'WooCommerce Pages', 'woocommerce' ),
419
					'type'        => 'array',
420
					'context'     => array( 'view', 'edit' ),
421
				),
422
			),
423
		);
424
425
		return $this->add_additional_fields_schema( $schema );
426
	}
427
428
    /**
429
	 * Return an array of sections and the data associated with each.
430
	 *
431
	 * @return array
432
	 */
433
	public function get_item_mappings() {
434
		return array(
435
			'environment'    => $this->get_environment_info(),
436
			'database'       => $this->get_database_info(),
437
			'active_plugins' => $this->get_active_plugins(),
438
			'theme'          => $this->get_theme_info(),
439
			'settings'       => $this->get_settings(),
440
			'pages'          => $this->get_pages(),
441
		);
442
	}
443
444
	/**
445
	 * Get array of environment information. Includes thing like software
446
	 * versions, and various server settings.
447
	 *
448
	 * @return array
449
	 */
450
	public function get_environment_info() {
451
		global $wpdb;
452
453
		// Figure out cURL version, if installed.
454
		$curl_version = '';
455
		if ( function_exists( 'curl_version' ) ) {
456
            $curl_version = curl_version();
457
            $curl_version = $curl_version['version'] . ', ' . $curl_version['ssl_version'];
458
        }
459
460
		// WP memory limit
461
        $wp_memory_limit = wc_let_to_num( WP_MEMORY_LIMIT );
462
        if ( function_exists( 'memory_get_usage' ) ) {
463
            $wp_memory_limit = max( $wp_memory_limit, wc_let_to_num( @ini_get( 'memory_limit' ) ) );
464
        }
465
466
		// Test POST requests
467
		$post_response = wp_safe_remote_post( 'https://www.paypal.com/cgi-bin/webscr', array(
468
			'timeout'     => 60,
469
			'user-agent'  => 'WooCommerce/' . WC()->version,
470
			'httpversion' => '1.1',
471
			'body'        => array(
472
				'cmd'    => '_notify-validate',
473
			),
474
		) );
475
		$post_response_successful = false;
476 View Code Duplication
		if ( ! is_wp_error( $post_response ) && $post_response['response']['code'] >= 200 && $post_response['response']['code'] < 300 ) {
0 ignored issues
show
Duplication introduced by
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...
477
			$post_response_successful = true;
478
		}
479
480
		// Test GET requests
481
		$get_response = wp_safe_remote_get( 'https://woocommerce.com/wc-api/product-key-api?request=ping&network=' . ( is_multisite() ? '1' : '0' ) );
482
		$get_response_successful = false;
483 View Code Duplication
		if ( ! is_wp_error( $post_response ) && $post_response['response']['code'] >= 200 && $post_response['response']['code'] < 300 ) {
0 ignored issues
show
Duplication introduced by
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...
484
			$get_response_successful = true;
485
		}
486
487
		// Return all environment info. Described by JSON Schema.
488
		return array(
489
            'home_url'                  => get_option( 'home' ),
490
            'site_url'                  => get_option( 'siteurl' ),
491
            'version'                => WC()->version,
492
            'log_directory'             => WC_LOG_DIR,
493
            'log_directory_writable'    => ( @fopen( WC_LOG_DIR . 'test-log.log', 'a' ) ? true : false ),
494
            'wp_version'                => get_bloginfo('version'),
495
            'wp_multisite'              => is_multisite(),
496
            'wp_memory_limit'           => $wp_memory_limit,
497
            'wp_debug_mode'             => ( defined( 'WP_DEBUG' ) && WP_DEBUG ),
498
            'wp_cron'                   => ! ( defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON ),
499
            'language'                  => get_locale(),
500
            'server_info'               => $_SERVER['SERVER_SOFTWARE'],
501
            'php_version'               => phpversion(),
502
            'php_post_max_size'         => wc_let_to_num( ini_get( 'post_max_size' ) ),
503
            'php_max_execution_time'    => ini_get( 'max_execution_time' ),
504
            'php_max_input_vars'        => ini_get( 'max_input_vars' ),
505
            'curl_version'              => $curl_version,
506
			'suhosin_installed'         => extension_loaded( 'suhosin' ),
507
			'max_upload_size'           => wp_max_upload_size(),
508
			'mysql_version'             => ( ! empty( $wpdb->is_mysql ) ? $wpdb->db_version() : '' ),
509
			'default_timezone'          => date_default_timezone_get(),
510
			'fsockopen_or_curl_enabled' => ( function_exists( 'fsockopen' ) || function_exists( 'curl_init' ) ),
511
			'soapclient_enabled'        => class_exists( 'SoapClient' ),
512
			'domdocument_enabled'       => class_exists( 'DOMDocument' ),
513
			'gzip_enabled'              => is_callable( 'gzopen' ),
514
			'mbstring_enabled'          => extension_loaded( 'mbstring' ),
515
			'remote_post_successful'    => $post_response_successful,
516
			'remote_post_response'      => ( is_wp_error( $post_response ) ? $post_response->get_error_message() : $post_response['response']['code'] ),
517
			'remote_get_successful'     => $get_response_successful,
518
			'remote_get_response'       => ( is_wp_error( $get_response ) ? $get_response->get_error_message() : $get_response['response']['code'] ),
519
        );
520
	}
521
522
	/**
523
	 * Get array of database information. Version, prefix, and table existence.
524
	 *
525
	 * @return array
526
	 */
527
	public function get_database_info() {
528
		global $wpdb;
529
530
		// WC Core tables to check existence of
531
		$tables = apply_filters( 'woocommerce_database_tables', array(
532
			'woocommerce_sessions',
533
			'woocommerce_api_keys',
534
			'woocommerce_attribute_taxonomies',
535
			'woocommerce_downloadable_product_permissions',
536
			'woocommerce_order_items',
537
			'woocommerce_order_itemmeta',
538
			'woocommerce_tax_rates',
539
			'woocommerce_tax_rate_locations',
540
			'woocommerce_shipping_zones',
541
			'woocommerce_shipping_zone_locations',
542
			'woocommerce_shipping_zone_methods',
543
			'woocommerce_payment_tokens',
544
			'woocommerce_payment_tokenmeta',
545
		) );
546
547
		if ( get_option( 'db_version' ) < 34370 ) {
548
			$tables[] = 'woocommerce_termmeta';
549
		}
550
		$table_exists = array();
551
		foreach ( $tables as $table ) {
552
			$table_exists[ $table ] = ( $wpdb->get_var( $wpdb->prepare( "SHOW TABLES LIKE %s;", $wpdb->prefix . $table ) ) === $wpdb->prefix . $table );
553
		}
554
555
		// Return all database info. Described by JSON Schema.
556
		return array(
557
			'wc_database_version'    => get_option( 'woocommerce_db_version' ),
558
			'database_prefix'        => $wpdb->prefix,
559
			'maxmind_geoip_database' => WC_Geolocation::get_local_database_path(),
560
			'database_tables'        => $table_exists,
561
		);
562
	}
563
564
	/**
565
	 * Get a list of plugins active on the site.
566
	 *
567
	 * @return array
568
	 */
569
	public function get_active_plugins() {
570
		require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
571
572
		// Get both site plugins and network plugins
573
		$active_plugins = (array) get_option( 'active_plugins', array() );
574
		if ( is_multisite() ) {
575
			$network_activated_plugins = array_keys( get_site_option( 'active_sitewide_plugins', array() ) );
576
			$active_plugins            = array_merge( $active_plugins, $network_activated_plugins );
577
		}
578
579
		$active_plugins_data = array();
580
		foreach ( $active_plugins as $plugin ) {
581
			$data                 = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin );
582
			$dirname              = dirname( $plugin );
583
			$theme_version_latest = '';
584
			if ( strstr( $data['PluginURI'], 'woothemes.com' ) ) {
585 View Code Duplication
				if ( false === ( $version_data = get_transient( md5( $plugin ) . '_version_data' ) ) ) {
0 ignored issues
show
Duplication introduced by
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...
586
					$changelog = wp_safe_remote_get( 'http://dzv365zjfbd8v.cloudfront.net/changelogs/' . $dirname . '/changelog.txt' );
587
					$cl_lines  = explode( "\n", wp_remote_retrieve_body( $changelog ) );
588
					if ( ! empty( $cl_lines ) ) {
589
						foreach ( $cl_lines as $line_num => $cl_line ) {
590
							if ( preg_match( '/^[0-9]/', $cl_line ) ) {
591
								$date         = str_replace( '.' , '-' , trim( substr( $cl_line , 0 , strpos( $cl_line , '-' ) ) ) );
592
								$version      = preg_replace( '~[^0-9,.]~' , '' ,stristr( $cl_line , "version" ) );
593
								$update       = trim( str_replace( "*" , "" , $cl_lines[ $line_num + 1 ] ) );
594
								$version_data = array( 'date' => $date , 'version' => $version , 'update' => $update , 'changelog' => $changelog );
595
								set_transient( md5( $plugin ) . '_version_data', $version_data, DAY_IN_SECONDS );
596
								break;
597
							}
598
						}
599
					}
600
				}
601
				$theme_version_latest = $version_data['version'];
602
			} else {
603
				include_once( ABSPATH . 'wp-admin/includes/plugin-install.php' );
604
				$slug = explode( '/', $plugin );
605
				$slug = explode( '.', end( $slug ) );
606
				$slug = $slug[0];
607
608
				$api = plugins_api( 'plugin_information', array(
609
					'slug'     => $slug,
610
					'fields'   => array(
611
						'sections' => false,
612
						'tags'     => false,
613
					),
614
				) );
615
616
				if ( is_object( $api ) && ! is_wp_error( $api ) ) {
617
					$theme_version_latest = $api->version;
618
				}
619
			}
620
621
			// convert plugin data to json response format.
622
			$active_plugins_data[] = array(
623
				'plugin'            => $plugin,
624
				'name'              => $data['Name'],
625
				'version'           => $data['Version'],
626
				'version_latest'    => $theme_version_latest,
627
				'url'               => $data['PluginURI'],
628
				'author_name'       => $data['AuthorName'],
629
				'author_url'        => esc_url_raw( $data['AuthorURI'] ),
630
				'network_activated' => $data['Network'],
631
			);
632
		}
633
634
		return $active_plugins_data;
635
	}
636
637
	/**
638
	 * Get info on the current active theme, info on parent theme (if presnet)
639
	 * and a list of template overrides.
640
	 *
641
	 * @return array
642
	 */
643
	public function get_theme_info() {
644
		$active_theme = wp_get_theme();
645
646
		// Get parent theme info if this theme is a child theme, otherwise
647
		// pass empty info in the response.
648
		if ( is_child_theme() ) {
649
			$parent_theme      = wp_get_theme( $active_theme->Template );
650
			$parent_theme_info = array(
651
				'parent_name'           => $parent_theme->Name,
652
				'parent_version'        => $parent_theme->Version,
653
				'parent_version_latest' => WC_Admin_Status::get_latest_theme_version( $parent_theme ),
654
				'parent_author_url'     => $parent_theme->{'Author URI'},
655
			);
656
		} else {
657
			$parent_theme_info = array( 'parent_name' => '', 'parent_version' => '', 'parent_version_latest' => '', 'parent_author_url' => '' );
658
		}
659
660
		/**
661
		 * Scan the theme directory for all WC templates to see if our theme
662
		 * overrides any of them.
663
		 */
664
		$override_files     = array();
665
		$outdated_templates = false;
666
		$scan_files         = WC_Admin_Status::scan_template_files( WC()->plugin_path() . '/templates/' );
667
		foreach ( $scan_files as $file ) {
668
			if ( file_exists( get_stylesheet_directory() . '/' . $file ) ) {
669
				$theme_file = get_stylesheet_directory() . '/' . $file;
670 View Code Duplication
			} elseif ( file_exists( get_stylesheet_directory() . '/' . WC()->template_path() . $file ) ) {
0 ignored issues
show
Duplication introduced by
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...
671
				$theme_file = get_stylesheet_directory() . '/' . WC()->template_path() . $file;
672
			} elseif ( file_exists( get_template_directory() . '/' . $file ) ) {
673
				$theme_file = get_template_directory() . '/' . $file;
674 View Code Duplication
			} elseif ( file_exists( get_template_directory() . '/' . WC()->template_path() . $file ) ) {
0 ignored issues
show
Duplication introduced by
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...
675
				$theme_file = get_template_directory() . '/' . WC()->template_path() . $file;
676
			} else {
677
				$theme_file = false;
678
			}
679
680
			if ( ! empty( $theme_file ) ) {
681
				$core_version  = WC_Admin_Status::get_file_version( WC()->plugin_path() . '/templates/' . $file );
682
				$theme_version = WC_Admin_Status::get_file_version( $theme_file );
683
				if ( $core_version && ( empty( $theme_version ) || version_compare( $theme_version, $core_version, '<' ) ) ) {
684
					if ( ! $outdated_templates ) {
685
						$outdated_templates = true;
686
					}
687
				}
688
				$override_files[] = array(
689
					'file'         => str_replace( WP_CONTENT_DIR . '/themes/', '', $theme_file ),
690
					'version'      => $theme_version,
691
					'core_version' => $core_version,
692
				);
693
			}
694
		}
695
696
		$active_theme_info = array(
697
			'name'                    => $active_theme->Name,
698
			'version'                 => $active_theme->Version,
699
			'version_latest'          => WC_Admin_Status::get_latest_theme_version( $active_theme ),
700
			'author_url'              => esc_url_raw( $active_theme->{'Author URI'} ),
701
			'is_child_theme'          => is_child_theme(),
702
			'has_woocommerce_support' => ( current_theme_supports( 'woocommerce' ) || in_array( $active_theme->template, wc_get_core_supported_themes() ) ),
703
			'has_woocommerce_file'    => ( file_exists( get_stylesheet_directory() . '/woocommerce.php' ) || file_exists( get_template_directory() . '/woocommerce.php' ) ),
704
			'has_outdated_templates'  => $outdated_templates,
705
			'overrides'               => $override_files,
706
		);
707
708
		return array_merge( $active_theme_info, $parent_theme_info );
709
	}
710
711
	/**
712
	 * Get some setting values for the site that are useful for debugging
713
	 * purposes. For full settings access, use the settings api.
714
	 *
715
	 * @return array
716
	 */
717
	public function get_settings() {
718
		// Get a list of terms used for product/order taxonomies
719
		$term_response = array();
720
		$terms         = get_terms( 'product_type', array( 'hide_empty' => 0 ) );
721
		foreach ( $terms as $term ) {
722
			$term_response[ $term->slug ] = strtolower( $term->name );
723
		}
724
725
		// Return array of useful settings for debugging.
726
		return array(
727
			'api_enabled'         => 'yes' === get_option( 'woocommerce_api_enabled' ),
728
			'force_ssl'           => 'yes' === get_option( 'woocommerce_force_ssl_checkout' ),
729
			'currency'            => get_woocommerce_currency(),
730
			'currency_symbol'     => get_woocommerce_currency_symbol(),
731
			'currency_position'   => get_option( 'woocommerce_currency_pos' ),
732
			'thousand_separator'  => wc_get_price_thousand_separator(),
733
			'decimal_separator'   => wc_get_price_decimal_separator(),
734
			'number_of_decimals'  => wc_get_price_decimals(),
735
			'geolocation_enabled' => in_array( get_option( 'woocommerce_default_customer_address' ), array( 'geolocation_ajax', 'geolocation' ) ),
736
			'taxonomies'          => $term_response,
737
		);
738
	}
739
740
	/**
741
	 * Returns a mini-report on WC pages and if they are configured correctly:
742
	 * Present, visible, and including the correct shortcode.
743
	 *
744
	 * @return array
745
	 */
746
	public function get_pages() {
747
		// WC pages to check against
748
		$check_pages = array(
749
			_x( 'Shop Base', 'Page setting', 'woocommerce' ) => array(
750
				'option'    => 'woocommerce_shop_page_id',
751
				'shortcode' => '',
752
			),
753
			_x( 'Cart', 'Page setting', 'woocommerce' ) => array(
754
				'option'    => 'woocommerce_cart_page_id',
755
				'shortcode' => '[' . apply_filters( 'woocommerce_cart_shortcode_tag', 'woocommerce_cart' ) . ']',
756
			),
757
			_x( 'Checkout', 'Page setting', 'woocommerce' ) => array(
758
				'option'    => 'woocommerce_checkout_page_id',
759
				'shortcode' => '[' . apply_filters( 'woocommerce_checkout_shortcode_tag', 'woocommerce_checkout' ) . ']',
760
			),
761
			_x( 'My Account', 'Page setting', 'woocommerce' ) => array(
762
				'option'    => 'woocommerce_myaccount_page_id',
763
				'shortcode' => '[' . apply_filters( 'woocommerce_my_account_shortcode_tag', 'woocommerce_my_account' ) . ']',
764
			),
765
		);
766
767
		$pages_output = array();
768
		foreach ( $check_pages as $page_name => $values ) {
769
			$errors   = array();
0 ignored issues
show
Unused Code introduced by
$errors 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...
770
			$page_id  = get_option( $values['option'] );
771
			$page_set = $page_exists = $page_visible = false;
772
			$shortcode_present = $shortcode_required = false;
773
774
			// Page checks
775
			if ( $page_id ) {
776
				$page_set = true;
777
			}
778
			if ( get_post( $page_id ) ) {
779
				$page_exists = true;
780
			}
781
			if ( 'publish' === get_post_status( $page_id ) ) {
782
				$page_visible = true;
783
			}
784
785
			// Shortcode checks
786
			if ( $values['shortcode']  && get_post( $page_id ) ) {
787
				$shortcode_required = true;
788
				$page = get_post( $page_id );
789
				if ( strstr( $page->post_content, $values['shortcode'] ) ) {
790
					$shortcode_present = true;
791
				}
792
			}
793
794
			// Wrap up our findings into an output array
795
			$pages_output[] = array(
796
					'page_name'          => $page_name,
797
					'page_id'            => $page_id,
798
					'page_set'           => $page_set,
799
					'page_exists'        => $page_exists,
800
					'page_visible'       => $page_visible,
801
					'shortcode'          => $values['shortcode'],
802
					'shortcode_required' => $shortcode_required,
803
					'shortcode_present'  => $shortcode_present,
804
			);
805
		}
806
807
		return $pages_output;
808
	}
809
810
	/**
811
	 * Get any query params needed.
812
	 *
813
	 * @return array
814
	 */
815
	public function get_collection_params() {
816
		return array(
817
			'context' => $this->get_context_param( array( 'default' => 'view' ) ),
818
		);
819
	}
820
}
821