Passed
Push — master ( 235569...65c96d )
by Paul
03:43
created

System::getWordpressDetails()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 22
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 20
nc 1
nop 0
dl 0
loc 22
ccs 0
cts 22
cp 0
crap 2
rs 9.6
c 0
b 0
f 0
1
<?php
2
3
namespace GeminiLabs\SiteReviews\Modules;
4
5
use GeminiLabs\SiteReviews\Application;
6
use GeminiLabs\SiteReviews\Database\Cache;
7
use GeminiLabs\SiteReviews\Database\CountsManager;
8
use GeminiLabs\SiteReviews\Database\OptionManager;
9
use GeminiLabs\SiteReviews\Helper;
10
use Sinergi\BrowserDetector\Browser;
11
12
class System
13
{
14
	const PAD = 40;
15
16
	/**
17
	 * @return string
18
	 */
19
	public function __toString()
20
	{
21
		return $this->get();
22
	}
23
24
	/**
25
	 * @return string
26
	 */
27
	public function get()
28
	{
29
		$details = [
30
			'plugin' => 'Plugin Details',
31
			'addon' => 'Addon Details',
32
			'browser' => 'Browser Details',
33
			'server' => 'Server Details',
34
			'php' => 'PHP Configuration',
35
			'wordpress' => 'WordPress Configuration',
36
			'mu-plugin' => 'Must-Use Plugins',
37
			'multisite-plugin' => 'Network Active Plugins',
38
			'active-plugin' => 'Active Plugins',
39
			'inactive-plugin' => 'Inactive Plugins',
40
			'setting' => 'Plugin Settings',
41
			'reviews' => 'Review Counts',
42
		];
43
		$systemInfo = array_reduce( array_keys( $details ), function( $carry, $key ) use( $details ) {
44
			$methodName = glsr( Helper::class )->buildMethodName( 'get-'.$key.'-details' );
45
			if( method_exists( $this, $methodName ) && $systemDetails = $this->$methodName() ) {
46
				return $carry.$this->implode( strtoupper( $details[$key] ), $systemDetails );
47
			}
48
			return $carry;
49
		});
50
		return trim( $systemInfo );
51
	}
52
53
	/**
54
	 * @return array
55
	 */
56
	public function getActivePluginDetails()
57
	{
58
		$plugins = get_plugins();
59
		$activePlugins = (array)get_option( 'active_plugins', [] );
60
		$inactive = array_diff_key( $plugins, array_flip( $activePlugins ));
61
		return $this->normalizePluginList( array_diff_key( $plugins, $inactive ));
62
	}
63
64
	/**
65
	 * @return array
66
	 */
67
	public function getAddonDetails()
68
	{
69
		$details = apply_filters( 'site-reviews/addon/system-info', [] );
70
		ksort( $details );
71
		return $details;
72
	}
73
74
	/**
75
	 * @return array
76
	 */
77
	public function getBrowserDetails()
78
	{
79
		$browser = new Browser;
80
		$name = esc_attr( $browser->getName() );
81
		$userAgent = esc_attr( $browser->getUserAgent()->getUserAgentString() );
82
		$version = esc_attr( $browser->getVersion() );
83
		return [
84
			'Browser Name' => sprintf( '%s %s', $name, $version ),
85
			'Browser UA' => $userAgent,
86
		];
87
	}
88
89
	/**
90
	 * @return array
91
	 */
92
	public function getInactivePluginDetails()
93
	{
94
		$activePlugins = (array)get_option( 'active_plugins', [] );
95
		return $this->normalizePluginList( array_diff_key( get_plugins(), array_flip( $activePlugins )));
96
	}
97
98
	/**
99
	 * @return void|array
100
	 */
101
	public function getMuPluginDetails()
102
	{
103
		$plugins = array_merge(
104
			get_mu_plugins(),
105
			get_plugins( '/../'.basename( WPMU_PLUGIN_DIR ))
106
		);
107
		if( empty( $plugins ))return;
108
		return $this->normalizePluginList( $plugins );
109
	}
110
111
	/**
112
	 * @return void|array
113
	 */
114
	public function getMultisitePluginDetails()
115
	{
116
		if( !is_multisite() || empty( get_site_option( 'active_sitewide_plugins', [] )))return;
117
		return $this->normalizePluginList( wp_get_active_network_plugins() );
118
	}
119
120
	/**
121
	 * @return array
122
	 */
123
	public function getPhpDetails()
124
	{
125
		$displayErrors = ini_get( 'display_errors' )
126
			? 'On ('.ini_get( 'display_errors' ).')'
127
			: 'N/A';
128
		$intlSupport = extension_loaded( 'intl' )
129
			? phpversion( 'intl' )
130
			: 'false';
131
		return [
132
			'cURL' => var_export( function_exists( 'curl_init' ), true ),
133
			'Default Charset' => ini_get( 'default_charset' ),
134
			'Display Errors' => $displayErrors,
135
			'fsockopen' => var_export( function_exists( 'fsockopen' ), true ),
136
			'Intl' => $intlSupport,
137
			'Max Execution Time' => ini_get( 'max_execution_time' ),
138
			'Max Input Nesting Level' => ini_get( 'max_input_nesting_level' ),
139
			'Max Input Vars' => ini_get( 'max_input_vars' ),
140
			'Memory Limit' => ini_get( 'memory_limit' ),
141
			'Post Max Size' => ini_get( 'post_max_size' ),
142
			'Session Cookie Path' => esc_html( ini_get( 'session.cookie_path' )),
143
			'Session Name' => esc_html( ini_get( 'session.name' )),
144
			'Session Save Path' => esc_html( ini_get( 'session.save_path' )),
145
			'Session Use Cookies' => var_export( wp_validate_boolean( ini_get( 'session.use_cookies' )), true ),
146
			'Session Use Only Cookies' => var_export( wp_validate_boolean( ini_get( 'session.use_only_cookies' )), true ),
147
			'Upload Max Filesize' => ini_get( 'upload_max_filesize' ),
148
		];
149
	}
150
151
	/**
152
	 * @return array
153
	 */
154
	public function getReviewsDetails()
155
	{
156
		$counts = glsr( CountsManager::class )->getCounts();
157
		$counts = glsr( Helper::class )->flattenArray( $counts );
158
		array_walk( $counts, function( &$ratings ) use( $counts ) {
159
			if( !is_array( $ratings )) {
160
				glsr_log()->error( 'System: ratings is not an array' )->debug( $ratings )->debug( $counts );
161
				return;
162
			}
163
			$ratings = array_sum( $ratings ).' ('.implode( ', ', $ratings ).')';
164
		});
165
		ksort( $counts );
166
		return $counts;
167
	}
168
169
	/**
170
	 * @return array
171
	 */
172
	public function getServerDetails()
173
	{
174
		global $wpdb;
175
		return [
176
			'Host Name' => $this->getHostName(),
177
			'MySQL Version' => $wpdb->db_version(),
178
			'PHP Version' => PHP_VERSION,
179
			'Server Software' => filter_input( INPUT_SERVER, 'SERVER_SOFTWARE' ),
180
		];
181
	}
182
183
	/**
184
	 * @return array
185
	 */
186
	public function getSettingDetails()
187
	{
188
		$helper = glsr( Helper::class );
189
		$settings = glsr( OptionManager::class )->get( 'settings', [] );
190
		$settings = $helper->flattenArray( $settings, true );
191
		$settings = $this->purgeSensitiveData( $settings );
192
		ksort( $settings );
193
		$details = [];
194
		foreach( $settings as $key => $value ) {
195
			if( $helper->startsWith( 'strings', $key ) && $helper->endsWith( 'id', $key ))continue;
196
			$value = htmlspecialchars( trim( preg_replace('/\s\s+/', '\\n', $value )), ENT_QUOTES, 'UTF-8' );
197
			$details[$key] = $value;
198
		}
199
		return $details;
200
	}
201
202
	/**
203
	 * @return array
204
	 */
205
	public function getPluginDetails()
206
	{
207
		return [
208
			'Current version' => glsr()->version,
209
			'Previous version' => glsr( OptionManager::class )->get( 'version_upgraded_from' ),
210
			'Console size' => glsr( Console::class )->humanSize( '0' ),
211
		];
212
	}
213
214
	/**
215
	 * @return array
216
	 */
217
	public function getWordpressDetails()
218
	{
219
		global $wpdb;
220
		$theme = wp_get_theme();
221
		return [
222
			'Active Theme' => sprintf( '%s v%s', (string)$theme->Name, (string)$theme->Version ),
223
			'Home URL' => home_url(),
224
			'Language' => get_locale(),
225
			'Memory Limit' => WP_MEMORY_LIMIT,
226
			'Multisite' => var_export( is_multisite(), true ),
227
			'Page For Posts ID' => get_option( 'page_for_posts' ),
228
			'Page On Front ID' => get_option( 'page_on_front' ),
229
			'Permalink Structure' => get_option( 'permalink_structure', 'default' ),
230
			'Post Stati' => implode( ', ', get_post_stati() ),
231
			'Remote Post' => glsr( Cache::class )->getRemotePostTest(),
232
			'Show On Front' => get_option( 'show_on_front' ),
233
			'Site URL' => site_url(),
234
			'Timezone' => get_option( 'timezone_string' ),
235
			'Version' => get_bloginfo( 'version' ),
236
			'WP Debug' => var_export( defined( 'WP_DEBUG' ), true ),
237
			'WP Max Upload Size' => size_format( wp_max_upload_size() ),
238
			'WP Memory Limit' => WP_MEMORY_LIMIT,
239
		];
240
	}
241
242
	/**
243
	 * @return string
244
	 */
245
	protected function detectWebhostProvider()
246
	{
247
		$checks = [
248
			'.accountservergroup.com' => 'Site5',
249
			'.gridserver.com' => 'MediaTemple Grid',
250
			'.inmotionhosting.com' => 'InMotion Hosting',
251
			'.ovh.net' => 'OVH',
252
			'.pair.com' => 'pair Networks',
253
			'.stabletransit.com' => 'Rackspace Cloud',
254
			'.stratoserver.net' => 'STRATO',
255
			'.sysfix.eu' => 'SysFix.eu Power Hosting',
256
			'bluehost.com' => 'Bluehost',
257
			'DH_USER' => 'DreamHost',
258
			'Flywheel' => 'Flywheel',
259
			'ipagemysql.com' => 'iPage',
260
			'ipowermysql.com' => 'IPower',
261
			'localhost:/tmp/mysql5.sock' => 'ICDSoft',
262
			'mysqlv5' => 'NetworkSolutions',
263
			'PAGELYBIN' => 'Pagely',
264
			'secureserver.net' => 'GoDaddy',
265
			'WPE_APIKEY' => 'WP Engine',
266
		];
267
		foreach( $checks as $key => $value ) {
268
			if( !$this->isWebhostCheckValid( $key ))continue;
269
			return $value;
270
		}
271
		return implode( ',', array_filter( [DB_HOST, filter_input( INPUT_SERVER, 'SERVER_NAME' )] ));
272
	}
273
274
	/**
275
	 * @return string
276
	 */
277
	protected function getHostName()
278
	{
279
		return sprintf( '%s (%s)',
280
			$this->detectWebhostProvider(),
281
			glsr( Helper::class )->getIpAddress()
282
		);
283
	}
284
285
	/**
286
	 * @return array
287
	 */
288
	protected function getWordpressPlugins()
289
	{
290
		$plugins = get_plugins();
291
		$activePlugins = (array)get_option( 'active_plugins', [] );
292
		$inactive = $this->normalizePluginList( array_diff_key( $plugins, array_flip( $activePlugins )));
293
		$active = $this->normalizePluginList( array_diff_key( $plugins, $inactive ));
294
		return $active + $inactive;
295
	}
296
297
	/**
298
	 * @param string $title
299
	 * @return string
300
	 */
301
	protected function implode( $title, array $details )
302
	{
303
		$strings = ['['.$title.']'];
304
		$padding = max( array_map( 'strlen', array_keys( $details )) );
305
		$padding = max( [$padding, static::PAD] );
306
		foreach( $details as $key => $value ) {
307
			$strings[] = is_string( $key )
308
				? sprintf( '%s : %s', str_pad( $key, $padding, '.' ), $value )
309
				: ' - '.$value;
310
		}
311
		return implode( PHP_EOL, $strings ).PHP_EOL.PHP_EOL;
312
	}
313
314
	/**
315
	 * @param string $key
316
	 * @return bool
317
	 */
318
	protected function isWebhostCheckValid( $key )
319
	{
320
		return defined( $key )
321
			|| filter_input( INPUT_SERVER, $key )
322
			|| strpos( filter_input( INPUT_SERVER, 'SERVER_NAME' ), $key ) !== false
323
			|| strpos( DB_HOST, $key ) !== false
324
			|| strpos( php_uname(), $key ) !== false;
325
	}
326
327
	/**
328
	 * @return array
329
	 */
330
	protected function normalizePluginList( array $plugins )
331
	{
332
		$plugins = array_map( function( $plugin ) {
333
			return sprintf( '%s v%s', $plugin['Name'], $plugin['Version'] );
334
		}, $plugins );
335
		natcasesort( $plugins );
336
		return array_flip( $plugins );
337
	}
338
339
	/**
340
	 * @return array
341
	 */
342
	protected function purgeSensitiveData( array $settings )
343
	{
344
		$keys = [
345
			'licenses.', 'submissions.recaptcha.key', 'submissions.recaptcha.secret',
346
		];
347
		array_walk( $settings, function( &$value, $setting ) use( $keys ) {
348
			foreach( $keys as $key ) {
349
				if( !glsr( Helper::class )->startsWith( $key, $setting ) || empty( $value ))continue;
350
				$value = str_repeat( '•', 13 );
351
				return;
352
			}
353
		});
354
		return $settings;
355
	}
356
}
357