PluginProbe ʕ •ᴥ•ʔ
WP STAGING – WordPress Backups, Restore, Migration & Clone / 4.11.0
WP STAGING – WordPress Backups, Restore, Migration & Clone v4.11.0
4.11.0 4.10.0 4.9.5 4.9.4 4.9.3 4.9.2 4.9.1 4.9.0 4.8.1 trunk 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.1.0 3.1.1 3.1.2 3.1.3 3.1.4 3.10.0 3.2.0 3.3.1 3.3.2 3.3.3 3.4.1 3.4.3 3.5.0 3.6.0 3.7.1 3.8.0 3.8.1 3.8.2 3.8.3 3.8.4 3.8.5 3.8.6 3.8.7 3.9.0 3.9.1 3.9.2 3.9.3 3.9.4 4.0.0 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4 4.2.0 4.2.1 4.3.0 4.3.1 4.3.2 4.4.0 4.5.0 4.6.0 4.7.0 4.7.1 4.7.2 4.7.3 4.8.0
wp-staging / Backend / Modules / SystemInfoParser.php
wp-staging / Backend / Modules Last commit date
Jobs 1 day ago Views 1 day ago SystemInfo.php 1 day ago SystemInfoParser.php 1 day ago
SystemInfoParser.php
539 lines
1 <?php
2
3 namespace WPStaging\Backend\Modules;
4
5 use WPStaging\Core\WPStaging;
6 use WPStaging\Framework\Traits\SerializeTrait;
7 use WPStaging\Backup\Storage\Providers;
8
9
10
11
12
13 class SystemInfoParser
14 {
15 use SerializeTrait;
16
17
18 const SECTION_STORAGE_PROVIDERS = 'WP Staging - Storage Providers';
19
20
21
22
23
24 const SECTIONS = [
25 'SERVER_AND_OS' => ['id' => 'server_and_os', 'name' => 'Server & Operating System', 'subtitle' => 'Server software and system architecture'],
26 'DATABASE_MYSQL_MARIADB' => ['id' => 'database_mysql_mariadb', 'name' => 'Database (MySQL / MariaDB)', 'subtitle' => 'Database configuration and connection details'],
27 'PHP_ENVIRONMENT' => ['id' => 'php_environment', 'name' => 'PHP Environment', 'subtitle' => 'PHP runtime and environment information'],
28 'PHP_LIMITS' => ['id' => 'php_limits', 'name' => 'PHP Limits', 'subtitle' => 'PHP resource limits and allocation'],
29 'WORDPRESS_ENVIRONMENT' => ['id' => 'wordpress_environment', 'name' => 'WordPress Environment', 'subtitle' => 'WordPress core and site configuration'],
30 'URLS_PATHS' => ['id' => 'urls_paths', 'name' => 'URLs & Paths', 'subtitle' => 'Site URLs and filesystem paths'],
31 'WORDPRESS_DIRECTORIES' => ['id' => 'wordpress_directories', 'name' => 'WordPress Directories', 'subtitle' => 'WordPress directory structure and locations'],
32 'MEDIA_UPLOADS' => ['id' => 'media_uploads', 'name' => 'Media & Uploads', 'subtitle' => 'Media upload paths and configuration'],
33 'WORDPRESS_MEMORY_SETTINGS' => ['id' => 'wordpress_memory_settings', 'name' => 'WordPress Memory Settings', 'subtitle' => 'WordPress memory allocation and limits'],
34 'FILESYSTEM_PERMISSIONS' => ['id' => 'filesystem_permissions', 'name' => 'Filesystem & Permissions', 'subtitle' => 'Filesystem access and permission settings'],
35 'THEME_PERMALINKS' => ['id' => 'theme_permalinks', 'name' => 'Theme & Permalinks', 'subtitle' => 'Active theme and permalink configuration'],
36 'WORDPRESS_CRON_JOBS' => ['id' => 'wordpress_cron_jobs', 'name' => 'WordPress Cron Jobs', 'subtitle' => 'Scheduled tasks and cron configuration'],
37 'WP_STAGING_PLUGIN_INFO' => ['id' => 'wp_staging_plugin_information', 'name' => 'WP Staging – Plugin Information', 'subtitle' => 'WP Staging plugin version and license details'],
38 'WP_STAGING_BACKUP_STATUS' => ['id' => 'wp_staging_backup_status_and_statistics', 'name' => 'WP Staging – Backup Status & Statistics', 'subtitle' => 'Backup status, storage usage, and processing metrics'],
39 'WP_STAGING_PERFORMANCE' => ['id' => 'wp_staging_performance_limits', 'name' => 'WP Staging – Performance & Limits', 'subtitle' => 'Performance settings and processing limits'],
40 'WP_STAGING_ACCESS' => ['id' => 'wp_staging_access_permissions', 'name' => 'WP Staging – Access & Permissions', 'subtitle' => 'User access rules and permission settings'],
41 'WP_STAGING_EXISTING_SITES' => ['id' => 'wp_staging_existing_staging_sites', 'name' => 'WP Staging – Existing Staging Sites', 'subtitle' => 'Configured staging sites and environments'],
42 'WP_STAGING_STORAGE_PROVIDER' => ['id' => 'wp_staging_storage_provider', 'name' => 'WP Staging - Storage Providers', 'subtitle' => 'Remote storage providers and configuration'],
43 'PLUGINS_OVERVIEW' => ['id' => 'plugins_overview', 'name' => 'Plugins Overview', 'subtitle' => 'Installed plugins and activation status'],
44 'CURL_ENVIRONMENT' => ['id' => 'curl_environment', 'name' => 'cURL Environment', 'subtitle' => 'cURL runtime, version, and SSL stack'],
45 'CURL_FEATURES' => ['id' => 'curl_features', 'name' => 'cURL Features', 'subtitle' => 'Enabled cURL features and capabilities'],
46 'SUPPORTED_PROTOCOLS' => ['id' => 'supported_protocols', 'name' => 'Supported Protocols', 'subtitle' => 'Protocols supported by the cURL library'],
47 'PHP_NETWORK_EXTENSIONS' => ['id' => 'php_network_extensions', 'name' => 'PHP Network Extensions', 'subtitle' => 'Installed PHP extensions for network communication'],
48 'CLIENT_BROWSER_INFO' => ['id' => 'client_browser_information', 'name' => 'Client / Browser Information', 'subtitle' => 'Client device and browser details'],
49 'MULTISITE' => ['id' => 'multisite', 'name' => 'Multisite', 'subtitle' => 'WordPress multisite network configuration'],
50 ];
51
52
53
54
55 public function isSerializedData($data): bool
56 {
57 return $this->isSerialized($data);
58 }
59
60
61
62
63
64
65 public function getStorageProvidersForSystemInfo(): array
66 {
67 if (!class_exists('WPStaging\Backup\Storage\Providers')) {
68 return [];
69 }
70
71 $providersInstance = WPStaging::make(Providers::class);
72 $storages = [];
73
74 foreach ($providersInstance->getStorages() as $storage) {
75 $optionName = 'wpstg_' . strtolower($storage['id']);
76
77 $storages[] = [
78 'id' => $storage['id'],
79 'name' => $storage['name'],
80 'optionName' => $optionName,
81 'title' => $storage['name'] . ' Settings',
82 ];
83 }
84
85 return $storages;
86 }
87
88
89
90
91
92
93
94 public function getStorageProviderIdByName($name): string
95 {
96 $providers = $this->getStorageProvidersForSystemInfo();
97 $found = array_filter($providers, function ($provider) use ($name) {
98 return $provider['name'] === $name;
99 });
100
101 return !empty($found) ? reset($found)['id'] : '';
102 }
103
104
105
106
107
108
109
110
111 public function getSectionId($sectionName, $navItems)
112 {
113 foreach ($navItems as $navItem) {
114 if (in_array($sectionName, $navItem['sections'])) {
115 return $navItem['id'];
116 }
117 }
118
119 return sanitize_title($sectionName);
120 }
121
122
123
124
125
126
127
128 public function getOrderedNavigationItems($sections): array
129 {
130 $allNavItems = $this->getAllNavigationItems();
131 $orderedNavItems = [];
132 $sectionOrder = array_keys($sections);
133
134
135 foreach ($sectionOrder as $sectionName) {
136 foreach ($allNavItems as $navItem) {
137 if (in_array($sectionName, $navItem['sections']) && !in_array($navItem['id'], array_column($orderedNavItems, 'id'))) {
138 $orderedNavItems[] = $navItem;
139 break;
140 }
141 }
142 }
143
144
145 foreach ($allNavItems as $navItem) {
146 if (!in_array($navItem['id'], array_column($orderedNavItems, 'id'))) {
147 $orderedNavItems[] = $navItem;
148 }
149 }
150
151 return $orderedNavItems;
152 }
153
154
155
156
157
158
159
160 public function getSectionSubtitle($sectionName): string
161 {
162
163 foreach (self::SECTIONS as $sectionId) {
164 if (self::getDisplayName($sectionId) === $sectionName) {
165 return self::getSubtitle($sectionId);
166 }
167 }
168
169 return '';
170 }
171
172
173
174
175
176
177
178 public function isStorageProvidersSection($sectionName): bool
179 {
180 return $sectionName === self::SECTION_STORAGE_PROVIDERS;
181 }
182
183
184
185
186
187
188
189 public function isStagingSitesLabel(string $label = ''): bool
190 {
191 $labelLower = strtolower(trim($label));
192 return strpos($labelLower, 'wpstg_staging_sites') !== false;
193 }
194
195
196
197
198
199
200
201 private function findStorageProviderByLabel(string $label)
202 {
203 $label = strtolower(trim($label));
204 $providers = $this->getStorageProvidersForSystemInfo();
205
206 foreach ($providers as $provider) {
207 if (strpos($label, strtolower($provider['name'] . ' settings')) !== false) {
208 return $provider;
209 }
210 }
211
212 return null;
213 }
214
215
216
217
218
219
220
221 public function isStorageProviderLabel($label): bool
222 {
223 return $this->findStorageProviderByLabel($label) !== null;
224 }
225
226
227
228
229
230
231
232 public function getStorageProviderName($label): string
233 {
234 $provider = $this->findStorageProviderByLabel($label);
235 return $provider !== null ? $provider['name'] : '';
236 }
237
238
239
240
241
242
243
244 public function processStructuredData($structuredData): array
245 {
246 $processedSections = [];
247
248 foreach ($structuredData as $sectionName => $sectionItems) {
249 if (empty($sectionItems)) {
250 continue;
251 }
252
253 $infoItems = [];
254 $stagingSites = [];
255 $processedStagingSites = [];
256 $storageProviders = [];
257 $storageProviderItems = [];
258 $isStorageProvidersSection = $this->isStorageProvidersSection($sectionName);
259
260
261 foreach ($sectionItems as $item) {
262 $processedItem = $this->processItem($item, $stagingSites, $processedStagingSites, $storageProviderItems, $isStorageProvidersSection);
263 if ($processedItem !== null) {
264 $infoItems[] = $processedItem;
265 }
266 }
267
268
269 if ($isStorageProvidersSection && !empty($storageProviderItems)) {
270 $storageProviders = $this->groupStorageProviders($storageProviderItems);
271 }
272
273 $processedSections[] = [
274 'sectionName' => $sectionName,
275 'infoItems' => array_values($infoItems),
276 'stagingSites' => $stagingSites,
277 'storageProviders' => $storageProviders,
278 ];
279 }
280
281 return $processedSections;
282 }
283
284
285
286
287
288
289 public function getStagingSiteFields(): array
290 {
291 return [
292 'prefix' => [
293 'label' => __('DB Prefix', 'wp-staging'),
294 'is_link' => false,
295 ],
296 'path' => [
297 'label' => __('Path', 'wp-staging'),
298 'is_link' => false,
299 ],
300 'url' => [
301 'label' => __('URL', 'wp-staging'),
302 'is_link' => true,
303 ],
304 'version' => [
305 'label' => __('Version', 'wp-staging'),
306 'is_link' => false,
307 ],
308 'wpVersion' => [
309 'label' => __('WP Version', 'wp-staging'),
310 'is_link' => false,
311 ],
312 ];
313 }
314
315 private function getAllNavigationItems(): array
316 {
317 return [
318 [
319 'id' => 'start-system-info',
320 'title' => __('Server Information', 'wp-staging'),
321 'icon' => 'nav-server',
322 'sections' => ['System Info', 'Server & Operating System', 'Database (MySQL / MariaDB)', 'PHP Environment', 'PHP Limits'],
323 ],
324 [
325 'id' => 'wordpress',
326 'title' => __('WordPress Info', 'wp-staging'),
327 'icon' => 'nav-wordpress',
328 'sections' => ['WordPress', 'WordPress Environment', 'URLs & Paths', 'WordPress Directories', 'Media & Uploads', 'WordPress Memory Settings', 'Filesystem & Permissions', 'Theme & Permalinks', 'WordPress Cron Jobs', 'Site Configuration'],
329 ],
330 [
331 'id' => 'wp-staging',
332 'title' => __('WP Staging Info', 'wp-staging'),
333 'icon' => 'nav-sync',
334 'sections' => ['WP Staging', 'WP Staging – Plugin Information', 'WP Staging – Backup Status & Statistics', 'WP Staging – Performance & Limits', 'WP Staging – Access & Permissions', 'WP Staging – Existing Staging Sites', 'WP Staging - Storage Providers'],
335 ],
336 [
337 'id' => 'plugins',
338 'title' => __('Plugins', 'wp-staging'),
339 'icon' => 'nav-plugins',
340 'sections' => ['Active Plugins', 'Active Plugins on this Site', 'Inactive Plugins', 'Inactive Plugins (Includes this and other sites in the same network)', 'Active Network Plugins (Includes this and other sites in the same network)', 'Must-Use Plugins', 'Drop-Ins', 'Plugins Overview', 'Network & cURL'],
341 ],
342 [
343 'id' => 'php-extensions',
344 'title' => __('Network & cURL', 'wp-staging'),
345 'icon' => 'nav-code',
346 'sections' => ['cURL Environment', 'cURL Features', 'Supported Protocols', 'PHP Network Extensions'],
347 ],
348 [
349 'id' => 'user-browser',
350 'title' => __('Browser Info', 'wp-staging'),
351 'icon' => 'nav-browser',
352 'sections' => ['Client / Browser Information'],
353 ],
354 [
355 'id' => 'logs',
356 'title' => __('Logs', 'wp-staging'),
357 'icon' => 'nav-logs',
358 'sections' => ['WP STAGING Logs', 'PHP debug.log'],
359 ],
360 ];
361 }
362
363
364 private function groupStorageProviders($storageProviderItems): array
365 {
366 $storageProviders = [];
367 $currentProvider = null;
368 $providerId = null;
369 $currentProviderData = [];
370 $processedProviders = [];
371 $hasCurrentProviderData = false;
372
373
374 $addProvider = function () use (&$storageProviders, &$currentProvider, &$providerId, &$currentProviderData, &$hasCurrentProviderData, &$processedProviders) {
375 if ($currentProvider === null || !$hasCurrentProviderData) {
376 return;
377 }
378
379 $providerKey = strtolower($currentProvider);
380 if (isset($processedProviders[$providerKey])) {
381 return;
382 }
383
384 $storageProviders[] = [
385 'id' => $providerId,
386 'name' => $currentProvider,
387 'settings' => $currentProviderData,
388 ];
389
390 $processedProviders[$providerKey] = true;
391 };
392
393 foreach ($storageProviderItems as $item) {
394 if ($this->isStorageProviderLabel($item['label'])) {
395 $addProvider();
396
397
398 $currentProvider = $this->getStorageProviderName($item['label']);
399 $providerId = $this->getStorageProviderIdByName($currentProvider);
400 $currentProviderData = [];
401 $hasCurrentProviderData = false;
402 } elseif ($currentProvider !== null) {
403
404 if ($item['value'] !== '') {
405 $hasCurrentProviderData = true;
406 $currentProviderData[] = [
407 'label' => $item['label'],
408 'value' => $item['value'],
409 ];
410 }
411 }
412 }
413
414
415 $addProvider();
416
417 return $storageProviders;
418 }
419
420
421
422
423
424
425
426
427
428
429
430 private function processItem($item, &$stagingSites, &$processedStagingSites, &$storageProviderItems, $isStorageProvidersSection = false)
431 {
432 $label = $item['label'];
433 $value = $item['value'];
434
435
436 if (is_string($value) && $this->isSerializedData($value)) {
437 $unserialized = @unserialize($value);
438 if ($unserialized === false || !is_array($unserialized)) {
439 return ['type' => 'regular', 'label' => $label, 'value' => $value];
440 }
441
442
443 if ($this->isStagingSitesLabel($label)) {
444 $stagingSites = array_merge($stagingSites, $this->processStagingSites($unserialized, $processedStagingSites));
445 return null;
446 }
447
448 return ['type' => 'serialized', 'label' => $label, 'value' => $unserialized];
449 }
450
451
452
453
454 if ($isStorageProvidersSection) {
455 $storageProviderItems[] = $item;
456 return null;
457 }
458
459 return ['type' => 'regular', 'label' => $label, 'value' => $value];
460 }
461
462
463
464
465
466
467
468
469 private function processStagingSites($unserialized, &$processedStagingSites): array
470 {
471 $stagingSites = [];
472 foreach ($unserialized as $siteData) {
473 if (!is_array($siteData)) {
474 continue;
475 }
476
477
478 if (!empty($siteData['directoryName']) && !isset($processedStagingSites[$siteData['directoryName']])) {
479 $stagingSites[] = $siteData;
480 $processedStagingSites[$siteData['directoryName']] = true;
481 }
482 }
483
484 return $stagingSites;
485 }
486
487
488
489
490
491
492
493 public static function getSectionMetadata(string $sectionId): array
494 {
495 foreach (self::SECTIONS as $section) {
496 if ($section['id'] === $sectionId) {
497 return [
498 'name' => __($section['name'], 'wp-staging'),
499 'subtitle' => __($section['subtitle'], 'wp-staging'),
500 ];
501 }
502 }
503
504 return ['name' => $sectionId, 'subtitle' => ''];
505 }
506
507
508
509
510
511
512
513 public static function getDisplayName($section): string
514 {
515 if (is_array($section)) {
516 return __($section['name'], 'wp-staging');
517 }
518
519 $metadata = self::getSectionMetadata($section);
520 return $metadata['name'];
521 }
522
523
524
525
526
527
528
529 public static function getSubtitle($section): string
530 {
531 if (is_array($section)) {
532 return __($section['subtitle'], 'wp-staging');
533 }
534
535 $metadata = self::getSectionMetadata($section);
536 return $metadata['subtitle'];
537 }
538 }
539