MainWP Child - Version 4.1.7

Version Description

  • 6-29-21 =
  • Added: Support for the new Vulnerability Checker API
Download this release

Release Info

Developer mainwp
Plugin Icon 128x128 MainWP Child
Version 4.1.7
Comparing to
See all releases

Code changes from version 4.1.6.1 to 4.1.7

class/class-mainwp-child-callable.php CHANGED
@@ -1,1010 +1,1011 @@
1
- <?php
2
- /**
3
- * MainWP Callable Functions
4
- *
5
- * Manage functions that can be executed on the child site.
6
- *
7
- * @package MainWP\Child
8
- */
9
-
10
- namespace MainWP\Child;
11
-
12
- // phpcs:disable WordPress.WP.AlternativeFunctions -- to use external code, third party credit.
13
-
14
- /**
15
- * Class MainWP_Child_Callable
16
- *
17
- * Manage functions that can be executed on the child site.
18
- */
19
- class MainWP_Child_Callable {
20
-
21
- /**
22
- * Public static variable to hold the single instance of the class.
23
- *
24
- * @var mixed Default null
25
- */
26
- protected static $instance = null;
27
-
28
- /**
29
- * Private variable to hold the array of all callable functions.
30
- *
31
- * @var array Callable functions.
32
- */
33
- private $callableFunctions = array(
34
- 'stats' => 'get_site_stats',
35
- 'upgrade' => 'upgrade_wp',
36
- 'newpost' => 'new_post',
37
- 'deactivate' => 'deactivate',
38
- 'newuser' => 'new_user',
39
- 'newadminpassword' => 'new_admin_password',
40
- 'installplugintheme' => 'install_plugin_theme',
41
- 'upgradeplugintheme' => 'upgrade_plugin_theme',
42
- 'upgradetranslation' => 'upgrade_translation',
43
- 'backup' => 'backup',
44
- 'backup_checkpid' => 'backup_checkpid',
45
- 'cloneinfo' => 'cloneinfo',
46
- 'security' => 'get_security_stats',
47
- 'securityFix' => 'do_security_fix',
48
- 'securityUnFix' => 'do_security_un_fix',
49
- 'post_action' => 'post_action',
50
- 'get_all_posts' => 'get_all_posts',
51
- 'comment_action' => 'comment_action',
52
- 'comment_bulk_action' => 'comment_bulk_action',
53
- 'get_all_comments' => 'get_all_comments',
54
- 'get_all_themes' => 'get_all_themes',
55
- 'theme_action' => 'theme_action',
56
- 'get_all_plugins' => 'get_all_plugins',
57
- 'plugin_action' => 'plugin_action',
58
- 'get_all_pages' => 'get_all_pages',
59
- 'get_all_users' => 'get_all_users',
60
- 'user_action' => 'user_action',
61
- 'search_users' => 'search_users',
62
- 'maintenance_site' => 'maintenance_site',
63
- 'branding_child_plugin' => 'branding_child_plugin',
64
- 'code_snippet' => 'code_snippet',
65
- 'uploader_action' => 'uploader_action',
66
- 'wordpress_seo' => 'wordpress_seo',
67
- 'client_report' => 'client_report',
68
- 'createBackupPoll' => 'backup_poll',
69
- 'page_speed' => 'page_speed',
70
- 'woo_com_status' => 'woo_com_status',
71
- 'links_checker' => 'links_checker',
72
- 'wordfence' => 'wordfence',
73
- 'delete_backup' => 'delete_backup',
74
- 'update_values' => 'update_child_values',
75
- 'ithemes' => 'ithemes',
76
- 'updraftplus' => 'updraftplus',
77
- 'backup_wp' => 'backup_wp',
78
- 'backwpup' => 'backwpup',
79
- 'wp_rocket' => 'wp_rocket',
80
- 'settings_tools' => 'settings_tools',
81
- 'skeleton_key' => 'bulk_settings_manager', // deprecated.
82
- 'bulk_settings_manager' => 'bulk_settings_manager',
83
- 'custom_post_type' => 'custom_post_type',
84
- 'backup_buddy' => 'backup_buddy',
85
- 'get_site_icon' => 'get_site_icon',
86
- 'vulner_checker' => 'vulner_checker',
87
- 'wp_staging' => 'wp_staging',
88
- 'disconnect' => 'disconnect',
89
- 'time_capsule' => 'time_capsule',
90
- 'extra_excution' => 'extra_execution', // deprecated!
91
- 'extra_execution' => 'extra_execution',
92
- 'wpvivid_backuprestore' => 'wpvivid_backuprestore',
93
- 'check_abandoned' => 'check_abandoned',
94
- );
95
-
96
- /**
97
- * Private variable to hold the array of all callable functions that don't require regularl authentication.
98
- *
99
- * @var array Callable functions.
100
- */
101
- private $callableFunctionsNoAuth = array(
102
- 'stats' => 'get_site_stats_no_auth',
103
- );
104
-
105
- /**
106
- * Method get_class_name()
107
- *
108
- * Get class name.
109
- *
110
- * @return string __CLASS__ Class name.
111
- */
112
- public static function get_class_name() {
113
- return __CLASS__;
114
- }
115
-
116
- /**
117
- * MainWP_Child_Callable constructor.
118
- *
119
- * Run any time class is called.
120
- */
121
- public function __construct() {
122
- }
123
-
124
- /**
125
- * Method instance()
126
- *
127
- * Create a public static instance.
128
- *
129
- * @return mixed Class instance.
130
- */
131
- public static function get_instance() {
132
- if ( null === self::$instance ) {
133
- self::$instance = new self();
134
- }
135
- return self::$instance;
136
- }
137
-
138
- /**
139
- * Method init_call_functions()
140
- *
141
- * Initiate callable functions.
142
- *
143
- * @param bool $auth If true, regular authentication is required.
144
- *
145
- * @uses \MainWP\Child\MainWP_Helper::instance()->error()
146
- * @uses \MainWP\Child\MainWP_Utility::handle_fatal_error()
147
- * @uses \MainWP\Child\MainWP_Utility::fix_for_custom_themes()
148
- */
149
- public function init_call_functions( $auth = false ) {
150
- $callable = false;
151
- $callable_no_auth = false;
152
- $call_func = false;
153
-
154
- // check if function is callable.
155
- if ( isset( $_POST['function'] ) ) {
156
- $call_func = isset( $_POST['function'] ) ? sanitize_text_field( wp_unslash( $_POST['function'] ) ) : '';
157
- $callable = $this->is_callable_function( $call_func ); // check callable func.
158
- $callable_no_auth = $this->is_callable_function_no_auth( $call_func ); // check callable no auth func.
159
- }
160
-
161
- // Fire off the called function.
162
- if ( $auth && isset( $_POST['function'] ) && $callable ) {
163
-
164
- /**
165
- * Checks whether cron is in progress.
166
- *
167
- * @const ( bool ) Default: true
168
- * @source https://code-reference.mainwp.com/classes/MainWP.Child.MainWP_Child_Callable.html
169
- */
170
- define( 'DOING_CRON', true );
171
-
172
- MainWP_Utility::handle_fatal_error();
173
- MainWP_Utility::fix_for_custom_themes();
174
- $this->call_function( $call_func );
175
- } elseif ( isset( $_POST['function'] ) && $callable_no_auth ) {
176
-
177
- /**
178
- * Checks whether cron is in progress.
179
- *
180
- * @const ( bool ) Default: true
181
- * @source https://code-reference.mainwp.com/classes/MainWP.Child.MainWP_Child_Callable.html
182
- */
183
- define( 'DOING_CRON', true );
184
-
185
- MainWP_Utility::fix_for_custom_themes();
186
- $this->call_function_no_auth( $call_func );
187
- } elseif ( isset( $_POST['function'] ) && isset( $_POST['mainwpsignature'] ) && ! $callable && ! $callable_no_auth ) {
188
- MainWP_Helper::instance()->error( __( 'Required version has not been detected. Please, make sure that you are using the latest version of the MainWP Child plugin on your site.', 'mainwp-child' ) );
189
- }
190
- }
191
-
192
- /**
193
- * Method is_callable_function()
194
- *
195
- * Check if the function is the list of callable functions.
196
- *
197
- * @param string $func Contains the name of the function to check.
198
- *
199
- * @return bool If callable, return true, if not, return false.
200
- */
201
- public function is_callable_function( $func ) {
202
- if ( isset( $this->callableFunctions[ $func ] ) ) {
203
- return true;
204
- }
205
- return false;
206
- }
207
-
208
- /**
209
- * Method is_callable_function_no_auth()
210
- *
211
- * Check if the function is the list of callable functions that don't require regular authentication.
212
- *
213
- * @param string $func Contains the name of the function to check.
214
- *
215
- * @return bool If callable, return true, if not, return false.
216
- */
217
- public function is_callable_function_no_auth( $func ) {
218
- if ( isset( $this->callableFunctionsNoAuth[ $func ] ) ) {
219
- return true;
220
- }
221
- return false;
222
- }
223
-
224
- /**
225
- * Method call_function()
226
- *
227
- * Call ceratin function.
228
- *
229
- * @param string $func Contains the name of the function to call.
230
- */
231
- public function call_function( $func ) {
232
- if ( $this->is_callable_function( $func ) ) {
233
- call_user_func( array( $this, $this->callableFunctions[ $func ] ) );
234
- }
235
- }
236
-
237
- /**
238
- * Method call_function_no_auth()
239
- *
240
- * Call ceratin function without regular authentication if the function is in the $callableFunctionsNoAuth list.
241
- *
242
- * @param string $func Contains the name of the function to call.
243
- */
244
- public function call_function_no_auth( $func ) {
245
- if ( $this->is_callable_function_no_auth( $func ) ) {
246
- call_user_func( array( $this, $this->callableFunctionsNoAuth[ $func ] ) );
247
- }
248
- }
249
-
250
- /**
251
- * Method get_site_stats()
252
- *
253
- * Fire off the get_site_stats() function.
254
- *
255
- * @uses \MainWP\Child\MainWP_Child_Stats::get_site_stats()
256
- */
257
- public function get_site_stats() {
258
- MainWP_Child_Stats::get_instance()->get_site_stats();
259
- }
260
-
261
- /**
262
- * Method get_site_stats_no_auth()
263
- *
264
- * Fire off the get_site_stats_no_auth() function.
265
- *
266
- * @uses \MainWP\Child\MainWP_Child_Stats::get_site_stats_no_auth()
267
- */
268
- public function get_site_stats_no_auth() {
269
- MainWP_Child_Stats::get_instance()->get_site_stats_no_auth();
270
- }
271
-
272
- /**
273
- * Method install_plugin_theme()
274
- *
275
- * Fire off the install_plugin_theme() function.
276
- *
277
- * @uses \MainWP\Child\MainWP_Child_Install::install_plugin_theme()
278
- */
279
- public function install_plugin_theme() {
280
- MainWP_Child_Install::get_instance()->install_plugin_theme();
281
- }
282
-
283
- /**
284
- * Method upgrade_wp()
285
- *
286
- * Fire off the upgrade_wp() function.
287
- *
288
- * @uses \MainWP\Child\MainWP_Child_Updates::upgrade_wp()
289
- */
290
- public function upgrade_wp() {
291
- MainWP_Child_Updates::get_instance()->upgrade_wp();
292
- }
293
-
294
- /**
295
- * Method upgrade_translation()
296
- *
297
- * Fire off the upgrade_translation() function.
298
- *
299
- * @uses \MainWP\Child\MainWP_Child_Updates::upgrade_translation()
300
- */
301
- public function upgrade_translation() {
302
- MainWP_Child_Updates::get_instance()->upgrade_translation();
303
- }
304
-
305
- /**
306
- * Method upgrade_plugin_theme()
307
- *
308
- * Fire off the upgrade_plugin_theme() function.
309
- *
310
- * @uses \MainWP\Child\MainWP_Child_Updates::upgrade_plugin_theme()
311
- */
312
- public function upgrade_plugin_theme() {
313
- MainWP_Child_Updates::get_instance()->upgrade_plugin_theme();
314
- }
315
-
316
- /**
317
- * Method theme_action()
318
- *
319
- * Fire off the theme_action() function.
320
- *
321
- * @uses \MainWP\Child\MainWP_Child_Install::theme_action()
322
- */
323
- public function theme_action() {
324
- MainWP_Child_Install::get_instance()->theme_action();
325
- }
326
-
327
- /**
328
- * Method plugin_action()
329
- *
330
- * Fire off the plugin_action() function.
331
- *
332
- * @uses \MainWP\Child\MainWP_Child_Install::plugin_action()
333
- */
334
- public function plugin_action() {
335
- MainWP_Child_Install::get_instance()->plugin_action();
336
- }
337
-
338
- /**
339
- * Method get_all_plugins()
340
- *
341
- * Fire off the get_all_plugins() function.
342
- *
343
- * @uses \MainWP\Child\MainWP_Child_Stats::get_all_plugins()
344
- */
345
- public function get_all_plugins() {
346
- MainWP_Child_Stats::get_instance()->get_all_plugins();
347
- }
348
-
349
- /**
350
- * Method get_all_themes()
351
- *
352
- * Fire off the get_all_themes() function.
353
- *
354
- * @uses \MainWP\Child\MainWP_Child_Stats::get_all_themes()
355
- */
356
- public function get_all_themes() {
357
- MainWP_Child_Stats::get_instance()->get_all_themes();
358
- }
359
-
360
- /**
361
- * Method get_all_users()
362
- *
363
- * Fire off the get_all_users() function.
364
- *
365
- * @uses \MainWP\Child\MainWP_Child_Users::get_all_users()
366
- */
367
- public function get_all_users() {
368
- MainWP_Child_Users::get_instance()->get_all_users();
369
- }
370
-
371
- /**
372
- * Method user_action()
373
- *
374
- * Fire off the user_action() function.
375
- *
376
- * @uses \MainWP\Child\MainWP_Child_Users::user_action()
377
- */
378
- public function user_action() {
379
- MainWP_Child_Users::get_instance()->user_action();
380
- }
381
-
382
- /**
383
- * Method search_users()
384
- *
385
- * Fire off the search_users() function.
386
- *
387
- * @uses \MainWP\Child\MainWP_Child_Users::search_users()
388
- */
389
- public function search_users() {
390
- MainWP_Child_Users::get_instance()->search_users();
391
- }
392
-
393
- /**
394
- * Method get_all_posts()
395
- *
396
- * Fire off the get_all_posts() function.
397
- *
398
- * @uses \MainWP\Child\MainWP_Child_Posts::get_all_posts()
399
- */
400
- public function get_all_posts() {
401
- MainWP_Child_Posts::get_instance()->get_all_posts();
402
- }
403
-
404
- /**
405
- * Method get_all_pages()
406
- *
407
- * Fire off the get_all_pages() function.
408
- *
409
- * @uses \MainWP\Child\MainWP_Child_Posts::get_all_pages()
410
- */
411
- public function get_all_pages() {
412
- MainWP_Child_Posts::get_instance()->get_all_pages();
413
- }
414
-
415
- /**
416
- * Method comment_action()
417
- *
418
- * Fire off the comment_action() function.
419
- *
420
- * @uses \MainWP\Child\MainWP_Child_Comments::comment_action()
421
- */
422
- public function comment_action() {
423
- MainWP_Child_Comments::get_instance()->comment_action();
424
- }
425
-
426
- /**
427
- * Method get_all_comments()
428
- *
429
- * Fire off the get_all_comments() function.
430
- *
431
- * @uses \MainWP\Child\MainWP_Child_Comments::get_all_comments()
432
- */
433
- public function get_all_comments() {
434
- MainWP_Child_Comments::get_instance()->get_all_comments();
435
- }
436
-
437
- /**
438
- * Method comment_bulk_action()
439
- *
440
- * Fire off the comment_bulk_action() function.
441
- *
442
- * @uses \MainWP\Child\MainWP_Child_Comments::comment_bulk_action()
443
- */
444
- public function comment_bulk_action() {
445
- MainWP_Child_Comments::get_instance()->comment_bulk_action();
446
- }
447
-
448
- /**
449
- * Method maintenance_site()
450
- *
451
- * Fire off the maintenance_site() function.
452
- *
453
- * @uses \MainWP\Child\MainWP_Child_Maintenance::maintenance_site()
454
- */
455
- public function maintenance_site() {
456
- MainWP_Child_Maintenance::get_instance()->maintenance_site();
457
- }
458
-
459
- /**
460
- * Method new_post()
461
- *
462
- * Fire off the new_post() function.
463
- *
464
- * @uses \MainWP\Child\MainWP_Child_Posts::new_post()
465
- */
466
- public function new_post() {
467
- MainWP_Child_Posts::get_instance()->new_post();
468
- }
469
-
470
- /**
471
- * Method post_action()
472
- *
473
- * Fire off the post_action() function.
474
- *
475
- * @uses \MainWP\Child\MainWP_Child_Posts::post_action()
476
- */
477
- public function post_action() {
478
- MainWP_Child_Posts::get_instance()->post_action();
479
- }
480
-
481
- /**
482
- * Method new_admin_password()
483
- *
484
- * Fire off the new_admin_password() function.
485
- *
486
- * @uses \MainWP\Child\MainWP_Child_Users::new_admin_password()
487
- */
488
- public function new_admin_password() {
489
- MainWP_Child_Users::get_instance()->new_admin_password();
490
- }
491
-
492
- /**
493
- * Method new_user()
494
- *
495
- * Fire off the new_user() function.
496
- *
497
- * @uses \MainWP\Child\MainWP_Child_Users::new_user()
498
- */
499
- public function new_user() {
500
- MainWP_Child_Users::get_instance()->new_user();
501
- }
502
-
503
- /**
504
- * Method cloneinfo()
505
- *
506
- * Fire off the cloneinfo() function.
507
- *
508
- * @uses \MainWP\Child\MainWP_Helper::write()
509
- */
510
- public function cloneinfo() {
511
-
512
- /**
513
- * WordPress DB Table Prefix.
514
- *
515
- * @global string
516
- */
517
- global $table_prefix;
518
-
519
- $information['dbCharset'] = DB_CHARSET;
520
- $information['dbCollate'] = DB_COLLATE;
521
- $information['table_prefix'] = $table_prefix;
522
- $information['site_url'] = get_option( 'site_url' );
523
- $information['home'] = get_option( 'home' );
524
-
525
- MainWP_Helper::write( $information );
526
- }
527
-
528
- /**
529
- * Method backup_poll()
530
- *
531
- * Fire off the backup_poll() function.
532
- *
533
- * @uses \MainWP\Child\MainWP_Backup::backup_poll()
534
- */
535
- public function backup_poll() {
536
- MainWP_Backup::get()->backup_poll();
537
- }
538
-
539
- /**
540
- * Method backup_checkpid()
541
- *
542
- * Fire off the backup_checkpid() function.
543
- *
544
- * @uses \MainWP\Child\MainWP_Backup::backup_checkpid()
545
- */
546
- public function backup_checkpid() {
547
- MainWP_Backup::get()->backup_checkpid();
548
- }
549
-
550
- /**
551
- * Method backup()
552
- *
553
- * Fire off the backup() function.
554
- *
555
- * @param bool $write Whether or not to execute MainWP_Helper::write(), Default: true.
556
- *
557
- * @return array Action result.
558
- *
559
- * @uses \MainWP\Child\MainWP_Backup::backup()
560
- */
561
- public function backup( $write = true ) {
562
- return MainWP_Backup::get()->backup( $write );
563
- }
564
-
565
- /**
566
- * Method backup_full()
567
- *
568
- * Fire off the backup_full() function.
569
- *
570
- * @param string $file_name Contains the backup file name.
571
- *
572
- * @return array Action result.
573
- *
574
- * @uses \MainWP\Child\MainWP_Backup::backup_full()
575
- */
576
- protected function backup_full( $file_name ) {
577
- return MainWP_Backup::get()->backup_full( $file_name );
578
- }
579
-
580
- /**
581
- * Method backup_db()
582
- *
583
- * Fire off the backup_db() function.
584
- *
585
- * @param string $file_name Contains the backup file name.
586
- * @param string $file_extension Contains the backup file extension.
587
- *
588
- * @return array Action result.
589
- *
590
- * @uses \MainWP\Child\MainWP_Backup::backup_db()
591
- */
592
- protected function backup_db( $file_name = '', $file_extension = 'zip' ) {
593
- return MainWP_Backup::get()->backup_db( $file_name, $file_extension );
594
- }
595
-
596
- /**
597
- * Method get_site_icon()
598
- *
599
- * Fire off the get_site_icon() function.
600
- *
601
- * @uses \MainWP\Child\MainWP_Child_Misc::get_site_icon()
602
- */
603
- public function get_site_icon() {
604
- MainWP_Child_Misc::get_instance()->get_site_icon();
605
- }
606
-
607
- /**
608
- * Method check_abandoned()
609
- *
610
- * Fire off the check_abandoned() function.
611
- */
612
- public function check_abandoned() {
613
- $which = sanitize_text_field( wp_unslash( $_POST['which'] ) );
614
- $infor = array();
615
- if ( 'plugin' == $which ) {
616
- MainWP_Child_Plugins_Check::instance()->run_check();
617
- $infor['success'] = 1;
618
- } else {
619
- MainWP_Child_Themes_Check::instance()->run_check();
620
- $infor['success'] = 1;
621
- }
622
- MainWP_Helper::write( $infor );
623
- }
624
-
625
- /**
626
- * Method get_security_stats()
627
- *
628
- * Fire off the get_security_stats() function.
629
- *
630
- * @uses \MainWP\Child\MainWP_Child_Misc::get_security_stats()
631
- */
632
- public function get_security_stats() {
633
- MainWP_Child_Misc::get_instance()->get_security_stats();
634
- }
635
-
636
- /**
637
- * Method do_security_fix()
638
- *
639
- * Fire off the do_security_fix() function.
640
- *
641
- * @uses \MainWP\Child\MainWP_Child_Misc::do_security_fix()
642
- */
643
- public function do_security_fix() {
644
- MainWP_Child_Misc::get_instance()->do_security_fix();
645
- }
646
-
647
- /**
648
- * Method do_security_un_fix()
649
- *
650
- * Fire off the do_security_un_fix() function.
651
- *
652
- * @uses \MainWP\Child\MainWP_Child_Misc::do_security_un_fix()
653
- */
654
- public function do_security_un_fix() {
655
- MainWP_Child_Misc::get_instance()->do_security_un_fix();
656
- }
657
-
658
- /**
659
- * Method settings_tools()
660
- *
661
- * Fire off the settings_tools() function.
662
- *
663
- * @uses \MainWP\Child\MainWP_Child_Misc::do_security_un_fix()
664
- */
665
- public function settings_tools() {
666
- MainWP_Child_Misc::get_instance()->do_security_un_fix();
667
- }
668
-
669
- /**
670
- * Method bulk_settings_manager()
671
- *
672
- * Fire off the action() function.
673
- *
674
- * @uses \MainWP\Child\MainWP_Child_Bulk_Settings_Manager::action()
675
- */
676
- public function bulk_settings_manager() {
677
- MainWP_Child_Bulk_Settings_Manager::instance()->action();
678
- }
679
-
680
- /**
681
- * Method custom_post_type()
682
- *
683
- * Fire off the action() function.
684
- *
685
- * @uses \MainWP\Child\MainWP_Custom_Post_Type::action()
686
- */
687
- public function custom_post_type() {
688
- MainWP_Custom_Post_Type::instance()->action();
689
- }
690
-
691
- /**
692
- * Method backup_buddy()
693
- *
694
- * Fire off the action() function.
695
- *
696
- * @uses \MainWP\Child\MainWP_Child_Back_Up_Buddy::action()
697
- */
698
- public function backup_buddy() {
699
- MainWP_Child_Back_Up_Buddy::instance()->action();
700
- }
701
-
702
- /**
703
- * Method vulner_checker()
704
- *
705
- * Fire off the action() function.
706
- *
707
- * @uses \MainWP\Child\MainWP_Child_Vulnerability_Checker::action()
708
- */
709
- public function vulner_checker() {
710
- MainWP_Child_Vulnerability_Checker::instance()->action();
711
- }
712
-
713
- /**
714
- * Method time_capsule()
715
- *
716
- * Fire off the action() function.
717
- *
718
- * @uses \MainWP\Child\MainWP_Child_Timecapsule::action()
719
- */
720
- public function time_capsule() {
721
- MainWP_Child_Timecapsule::instance()->action();
722
- }
723
-
724
- /**
725
- * Method wp_staging()
726
- *
727
- * Fire off the action() function.
728
- *
729
- * @uses \MainWP\Child\MainWP_Child_Staging::action()
730
- */
731
- public function wp_staging() {
732
- MainWP_Child_Staging::instance()->action();
733
- }
734
-
735
- /**
736
- * Method extra_execution()
737
- *
738
- * Additional functions to execute.
739
- *
740
- * @uses \MainWP\Child\MainWP_Helper::write()
741
- */
742
- public function extra_execution() {
743
- $post = $_POST;
744
- $information = array();
745
- /**
746
- * Filter 'mainwp_child_extra_execution'
747
- *
748
- * Additional functions to execute through the filter.
749
- *
750
- * @param array $information An array containing the synchronization information.
751
- * @param mixed $post Contains the POST request.
752
- *
753
- * @since 4.0
754
- */
755
- $information = apply_filters( 'mainwp_child_extra_execution', $information, $post );
756
- MainWP_Helper::write( $information );
757
- }
758
-
759
- /**
760
- * Method uploader_action()
761
- *
762
- * Fire off the uploader_action() function.
763
- *
764
- * @uses \MainWP\Child\MainWP_Child_Misc::uploader_action()
765
- */
766
- public function uploader_action() {
767
- MainWP_Child_Misc::get_instance()->uploader_action();
768
- }
769
-
770
- /**
771
- * Method wordpress_seo()
772
- *
773
- * Fire off the action() function.
774
- */
775
- public function wordpress_seo() {
776
- MainWP_WordPress_SEO::instance()->action();
777
- }
778
-
779
- /**
780
- * Method client_report()
781
- *
782
- * Fire off the action() function.
783
- *
784
- * @uses \MainWP\Child\MainWP_Client_Report::action()
785
- */
786
- public function client_report() {
787
- MainWP_Client_Report::instance()->action();
788
- }
789
-
790
- /**
791
- * Method page_speed()
792
- *
793
- * Fire off the action() function.
794
- *
795
- * @uses \MainWP\Child\MainWP_Child_Pagespeed::action()
796
- */
797
- public function page_speed() {
798
- MainWP_Child_Pagespeed::instance()->action();
799
- }
800
-
801
- /**
802
- * Method woo_com_status()
803
- *
804
- * Fire off the action() function.
805
- *
806
- * @uses \MainWP\Child\MainWP_Child_WooCommerce_Status::action()
807
- */
808
- public function woo_com_status() {
809
- MainWP_Child_WooCommerce_Status::instance()->action();
810
- }
811
-
812
- /**
813
- * Method links_checker()
814
- *
815
- * Fire off the action() function.
816
- *
817
- * @uses \MainWP\Child\MainWP_Child_Links_Checker::action()
818
- */
819
- public function links_checker() {
820
- MainWP_Child_Links_Checker::instance()->action();
821
- }
822
-
823
- /**
824
- * Method wordfence()
825
- *
826
- * Fire off the action() function.
827
- *
828
- * @uses \MainWP\Child\MainWP_Child_Wordfence::action()
829
- */
830
- public function wordfence() {
831
- MainWP_Child_Wordfence::instance()->action();
832
- }
833
-
834
- /**
835
- * Method ithemes()
836
- *
837
- * Fire off the action() function.
838
- *
839
- * @uses \MainWP\Child\MainWP_Child_IThemes_Security::action()
840
- */
841
- public function ithemes() {
842
- MainWP_Child_IThemes_Security::instance()->action();
843
- }
844
-
845
- /**
846
- * Method updraftplus()
847
- *
848
- * Fire off the action() function.
849
- *
850
- * @uses \MainWP\Child\MainWP_Child_Updraft_Plus_Backups::action()
851
- */
852
- public function updraftplus() {
853
- MainWP_Child_Updraft_Plus_Backups::instance()->action();
854
- }
855
-
856
- /**
857
- * Method wpvivid_backuprestore()
858
- *
859
- * Fire off the action() function.
860
- *
861
- * @uses \MainWP\Child\MainWP_Child_WPvivid_BackupRestore::action()
862
- */
863
- public function wpvivid_backuprestore() {
864
- MainWP_Child_WPvivid_BackupRestore::instance()->action();
865
- }
866
-
867
- /**
868
- * Method backup_wp()
869
- *
870
- * Fire off the action() function.
871
- *
872
- * @uses \MainWP\Child\MainWP_Child_Back_Up_WordPress::action()
873
- * @uses \MainWP\Child\MainWP_Helper::write()
874
- */
875
- public function backup_wp() {
876
- if ( ! version_compare( phpversion(), '5.3', '>=' ) ) {
877
- $error = sprintf( __( 'PHP Version %s is unsupported.', 'mainwp-child' ), phpversion() );
878
- MainWP_Helper::write( array( 'error' => $error ) );
879
- }
880
- MainWP_Child_Back_Up_WordPress::instance()->action();
881
- }
882
-
883
- /**
884
- * Method wp_rocket()
885
- *
886
- * Fire off the action() function.
887
- *
888
- * @uses \MainWP\Child\MainWP_Child_WP_Rocket::action()
889
- */
890
- public function wp_rocket() {
891
- MainWP_Child_WP_Rocket::instance()->action();
892
- }
893
-
894
- /**
895
- * Method backwpup()
896
- *
897
- * Fire off the action() function.
898
- *
899
- * @uses \MainWP\Child\MainWP_Child_Back_WP_Up::action()
900
- */
901
- public function backwpup() {
902
- MainWP_Child_Back_WP_Up::instance()->action();
903
- }
904
-
905
- /**
906
- * Method delete_backup()
907
- *
908
- * Delete backup.
909
- *
910
- * @uses \MainWP\Child\MainWP_Helper::get_mainwp_dir()
911
- * @uses \MainWP\Child\MainWP_Helper::write()
912
- */
913
- public function delete_backup() {
914
- $dirs = MainWP_Helper::get_mainwp_dir( 'backup' );
915
- $backupdir = $dirs[0];
916
-
917
- $file = isset( $_REQUEST['del'] ) ? wp_unslash( $_REQUEST['del'] ) : '';
918
-
919
- if ( file_exists( $backupdir . $file ) ) {
920
- unlink( $backupdir . $file );
921
- }
922
-
923
- MainWP_Helper::write( array( 'result' => 'ok' ) );
924
- }
925
-
926
- /**
927
- * Method update_child_values()
928
- *
929
- * Update the MainWP Child site options.
930
- *
931
- * @uses \MainWP\Child\MainWP_Helper::update_option()
932
- * @uses \MainWP\Child\MainWP_Helper::write()
933
- */
934
- public function update_child_values() {
935
- $unique_id = isset( $_POST['uniqueId'] ) ? sanitize_text_field( wp_unslash( $_POST['uniqueId'] ) ) : '';
936
- MainWP_Helper::update_option( 'mainwp_child_uniqueId', $unique_id );
937
- MainWP_Helper::write( array( 'result' => 'ok' ) );
938
- }
939
-
940
- /**
941
- * Method branding_child_plugin()
942
- *
943
- * Fire off the action() function.
944
- *
945
- * @uses \MainWP\Child\MainWP_Child_Branding::action()
946
- */
947
- public function branding_child_plugin() {
948
- MainWP_Child_Branding::instance()->action();
949
- }
950
-
951
- /**
952
- * Method code_snippet()
953
- *
954
- * Fire off the code_snippet() function.
955
- *
956
- * @uses MainWP_Child_Misc::code_snippet()
957
- */
958
- public function code_snippet() {
959
- MainWP_Child_Misc::get_instance()->code_snippet();
960
- }
961
-
962
- /**
963
- * Method disconnect()
964
- *
965
- * Disconnect the child site from the current MainWP Dashboard.
966
- *
967
- * @uses \MainWP\Child\MainWP_Helper::write()
968
- */
969
- public function disconnect() {
970
-
971
- /**
972
- * MainWP Child instance.
973
- *
974
- * @global object
975
- */
976
- global $mainWPChild;
977
-
978
- $mainWPChild->deactivation( false );
979
- MainWP_Helper::write( array( 'result' => 'success' ) );
980
- }
981
-
982
-
983
- /**
984
- * Method deactivate()
985
- *
986
- * Deactivate the MainWP Child plugin in the site.
987
- *
988
- * @uses \MainWP\Child\MainWP_Helper::errpr()
989
- * @uses \MainWP\Child\MainWP_Helper::write()
990
- */
991
- public function deactivate() {
992
-
993
- /**
994
- * MainWP Child instance.
995
- *
996
- * @global object
997
- */
998
- global $mainWPChild;
999
-
1000
- include_once ABSPATH . 'wp-admin/includes/plugin.php';
1001
- deactivate_plugins( $mainWPChild->plugin_slug, true );
1002
- $information = array();
1003
- if ( is_plugin_active( $mainWPChild->plugin_slug ) ) {
1004
- MainWP_Helper::instance()->error( 'Plugin still active' );
1005
- }
1006
- $information['deactivated'] = true;
1007
- MainWP_Helper::write( $information );
1008
- }
1009
-
1010
- }
 
1
+ <?php
2
+ /**
3
+ * MainWP Callable Functions
4
+ *
5
+ * Manage functions that can be executed on the child site.
6
+ *
7
+ * @package MainWP\Child
8
+ */
9
+
10
+ namespace MainWP\Child;
11
+
12
+ // phpcs:disable WordPress.WP.AlternativeFunctions -- to use external code, third party credit.
13
+
14
+ /**
15
+ * Class MainWP_Child_Callable
16
+ *
17
+ * Manage functions that can be executed on the child site.
18
+ */
19
+ class MainWP_Child_Callable {
20
+
21
+ /**
22
+ * Public static variable to hold the single instance of the class.
23
+ *
24
+ * @var mixed Default null
25
+ */
26
+ protected static $instance = null;
27
+
28
+ /**
29
+ * Private variable to hold the array of all callable functions.
30
+ *
31
+ * @var array Callable functions.
32
+ */
33
+ private $callableFunctions = array(
34
+ 'stats' => 'get_site_stats',
35
+ 'upgrade' => 'upgrade_wp',
36
+ 'newpost' => 'new_post',
37
+ 'deactivate' => 'deactivate',
38
+ 'newuser' => 'new_user',
39
+ 'newadminpassword' => 'new_admin_password',
40
+ 'installplugintheme' => 'install_plugin_theme',
41
+ 'upgradeplugintheme' => 'upgrade_plugin_theme',
42
+ 'upgradetranslation' => 'upgrade_translation',
43
+ 'backup' => 'backup',
44
+ 'backup_checkpid' => 'backup_checkpid',
45
+ 'cloneinfo' => 'cloneinfo',
46
+ 'security' => 'get_security_stats',
47
+ 'securityFix' => 'do_security_fix',
48
+ 'securityUnFix' => 'do_security_un_fix',
49
+ 'post_action' => 'post_action',
50
+ 'get_all_posts' => 'get_all_posts',
51
+ 'comment_action' => 'comment_action',
52
+ 'comment_bulk_action' => 'comment_bulk_action',
53
+ 'get_all_comments' => 'get_all_comments',
54
+ 'get_all_themes' => 'get_all_themes',
55
+ 'theme_action' => 'theme_action',
56
+ 'get_all_plugins' => 'get_all_plugins',
57
+ 'plugin_action' => 'plugin_action',
58
+ 'get_all_pages' => 'get_all_pages',
59
+ 'get_all_users' => 'get_all_users',
60
+ 'user_action' => 'user_action',
61
+ 'search_users' => 'search_users',
62
+ 'maintenance_site' => 'maintenance_site',
63
+ 'branding_child_plugin' => 'branding_child_plugin',
64
+ 'code_snippet' => 'code_snippet',
65
+ 'uploader_action' => 'uploader_action',
66
+ 'wordpress_seo' => 'wordpress_seo',
67
+ 'client_report' => 'client_report',
68
+ 'createBackupPoll' => 'backup_poll',
69
+ 'page_speed' => 'page_speed',
70
+ 'woo_com_status' => 'woo_com_status',
71
+ 'links_checker' => 'links_checker',
72
+ 'wordfence' => 'wordfence',
73
+ 'delete_backup' => 'delete_backup',
74
+ 'update_values' => 'update_child_values',
75
+ 'ithemes' => 'ithemes',
76
+ 'updraftplus' => 'updraftplus',
77
+ 'backup_wp' => 'backup_wp',
78
+ 'backwpup' => 'backwpup',
79
+ 'wp_rocket' => 'wp_rocket',
80
+ 'settings_tools' => 'settings_tools',
81
+ 'skeleton_key' => 'bulk_settings_manager', // deprecated.
82
+ 'bulk_settings_manager' => 'bulk_settings_manager',
83
+ 'custom_post_type' => 'custom_post_type',
84
+ 'backup_buddy' => 'backup_buddy',
85
+ 'get_site_icon' => 'get_site_icon',
86
+ 'vulner_checker' => 'vulner_checker',
87
+ 'wp_staging' => 'wp_staging',
88
+ 'disconnect' => 'disconnect',
89
+ 'time_capsule' => 'time_capsule',
90
+ 'extra_excution' => 'extra_execution', // deprecated!
91
+ 'extra_execution' => 'extra_execution',
92
+ 'wpvivid_backuprestore' => 'wpvivid_backuprestore',
93
+ 'check_abandoned' => 'check_abandoned',
94
+ );
95
+
96
+ /**
97
+ * Private variable to hold the array of all callable functions that don't require regularl authentication.
98
+ *
99
+ * @var array Callable functions.
100
+ */
101
+ private $callableFunctionsNoAuth = array(
102
+ 'stats' => 'get_site_stats_no_auth',
103
+ );
104
+
105
+ /**
106
+ * Method get_class_name()
107
+ *
108
+ * Get class name.
109
+ *
110
+ * @return string __CLASS__ Class name.
111
+ */
112
+ public static function get_class_name() {
113
+ return __CLASS__;
114
+ }
115
+
116
+ /**
117
+ * MainWP_Child_Callable constructor.
118
+ *
119
+ * Run any time class is called.
120
+ */
121
+ public function __construct() {
122
+ }
123
+
124
+ /**
125
+ * Method instance()
126
+ *
127
+ * Create a public static instance.
128
+ *
129
+ * @return mixed Class instance.
130
+ */
131
+ public static function get_instance() {
132
+ if ( null === self::$instance ) {
133
+ self::$instance = new self();
134
+ }
135
+ return self::$instance;
136
+ }
137
+
138
+ /**
139
+ * Method init_call_functions()
140
+ *
141
+ * Initiate callable functions.
142
+ *
143
+ * @param bool $auth If true, regular authentication is required.
144
+ *
145
+ * @uses \MainWP\Child\MainWP_Helper::instance()->error()
146
+ * @uses \MainWP\Child\MainWP_Utility::handle_fatal_error()
147
+ * @uses \MainWP\Child\MainWP_Utility::fix_for_custom_themes()
148
+ */
149
+ public function init_call_functions( $auth = false ) {
150
+ $callable = false;
151
+ $callable_no_auth = false;
152
+ $call_func = false;
153
+
154
+ // check if function is callable.
155
+ if ( isset( $_POST['function'] ) ) {
156
+ $call_func = isset( $_POST['function'] ) ? sanitize_text_field( wp_unslash( $_POST['function'] ) ) : '';
157
+ $callable = $this->is_callable_function( $call_func ); // check callable func.
158
+ $callable_no_auth = $this->is_callable_function_no_auth( $call_func ); // check callable no auth func.
159
+ }
160
+
161
+ // Fire off the called function.
162
+ if ( $auth && isset( $_POST['function'] ) && $callable ) {
163
+
164
+ /**
165
+ * Checks whether cron is in progress.
166
+ *
167
+ * @const ( bool ) Default: true
168
+ * @source https://code-reference.mainwp.com/classes/MainWP.Child.MainWP_Child_Callable.html
169
+ */
170
+ define( 'DOING_CRON', true );
171
+
172
+ MainWP_Utility::handle_fatal_error();
173
+ MainWP_Utility::fix_for_custom_themes();
174
+ $this->call_function( $call_func );
175
+ } elseif ( isset( $_POST['function'] ) && $callable_no_auth ) {
176
+
177
+ /**
178
+ * Checks whether cron is in progress.
179
+ *
180
+ * @const ( bool ) Default: true
181
+ * @source https://code-reference.mainwp.com/classes/MainWP.Child.MainWP_Child_Callable.html
182
+ */
183
+ define( 'DOING_CRON', true );
184
+
185
+ MainWP_Utility::fix_for_custom_themes();
186
+ $this->call_function_no_auth( $call_func );
187
+ } elseif ( isset( $_POST['function'] ) && isset( $_POST['mainwpsignature'] ) && ! $callable && ! $callable_no_auth ) {
188
+ MainWP_Helper::instance()->error( __( 'Required version has not been detected. Please, make sure that you are using the latest version of the MainWP Child plugin on your site.', 'mainwp-child' ) );
189
+ }
190
+ }
191
+
192
+ /**
193
+ * Method is_callable_function()
194
+ *
195
+ * Check if the function is the list of callable functions.
196
+ *
197
+ * @param string $func Contains the name of the function to check.
198
+ *
199
+ * @return bool If callable, return true, if not, return false.
200
+ */
201
+ public function is_callable_function( $func ) {
202
+ if ( isset( $this->callableFunctions[ $func ] ) ) {
203
+ return true;
204
+ }
205
+ return false;
206
+ }
207
+
208
+ /**
209
+ * Method is_callable_function_no_auth()
210
+ *
211
+ * Check if the function is the list of callable functions that don't require regular authentication.
212
+ *
213
+ * @param string $func Contains the name of the function to check.
214
+ *
215
+ * @return bool If callable, return true, if not, return false.
216
+ */
217
+ public function is_callable_function_no_auth( $func ) {
218
+ if ( isset( $this->callableFunctionsNoAuth[ $func ] ) ) {
219
+ return true;
220
+ }
221
+ return false;
222
+ }
223
+
224
+ /**
225
+ * Method call_function()
226
+ *
227
+ * Call ceratin function.
228
+ *
229
+ * @param string $func Contains the name of the function to call.
230
+ */
231
+ public function call_function( $func ) {
232
+ if ( $this->is_callable_function( $func ) ) {
233
+ call_user_func( array( $this, $this->callableFunctions[ $func ] ) );
234
+ }
235
+ }
236
+
237
+ /**
238
+ * Method call_function_no_auth()
239
+ *
240
+ * Call ceratin function without regular authentication if the function is in the $callableFunctionsNoAuth list.
241
+ *
242
+ * @param string $func Contains the name of the function to call.
243
+ */
244
+ public function call_function_no_auth( $func ) {
245
+ if ( $this->is_callable_function_no_auth( $func ) ) {
246
+ call_user_func( array( $this, $this->callableFunctionsNoAuth[ $func ] ) );
247
+ }
248
+ }
249
+
250
+ /**
251
+ * Method get_site_stats()
252
+ *
253
+ * Fire off the get_site_stats() function.
254
+ *
255
+ * @uses \MainWP\Child\MainWP_Child_Stats::get_site_stats()
256
+ */
257
+ public function get_site_stats() {
258
+ MainWP_Child_Stats::get_instance()->get_site_stats();
259
+ }
260
+
261
+ /**
262
+ * Method get_site_stats_no_auth()
263
+ *
264
+ * Fire off the get_site_stats_no_auth() function.
265
+ *
266
+ * @uses \MainWP\Child\MainWP_Child_Stats::get_site_stats_no_auth()
267
+ */
268
+ public function get_site_stats_no_auth() {
269
+ MainWP_Child_Stats::get_instance()->get_site_stats_no_auth();
270
+ }
271
+
272
+ /**
273
+ * Method install_plugin_theme()
274
+ *
275
+ * Fire off the install_plugin_theme() function.
276
+ *
277
+ * @uses \MainWP\Child\MainWP_Child_Install::install_plugin_theme()
278
+ */
279
+ public function install_plugin_theme() {
280
+ MainWP_Child_Install::get_instance()->install_plugin_theme();
281
+ }
282
+
283
+ /**
284
+ * Method upgrade_wp()
285
+ *
286
+ * Fire off the upgrade_wp() function.
287
+ *
288
+ * @uses \MainWP\Child\MainWP_Child_Updates::upgrade_wp()
289
+ */
290
+ public function upgrade_wp() {
291
+ MainWP_Child_Updates::get_instance()->upgrade_wp();
292
+ }
293
+
294
+ /**
295
+ * Method upgrade_translation()
296
+ *
297
+ * Fire off the upgrade_translation() function.
298
+ *
299
+ * @uses \MainWP\Child\MainWP_Child_Updates::upgrade_translation()
300
+ */
301
+ public function upgrade_translation() {
302
+ MainWP_Child_Updates::get_instance()->upgrade_translation();
303
+ }
304
+
305
+ /**
306
+ * Method upgrade_plugin_theme()
307
+ *
308
+ * Fire off the upgrade_plugin_theme() function.
309
+ *
310
+ * @uses \MainWP\Child\MainWP_Child_Updates::upgrade_plugin_theme()
311
+ */
312
+ public function upgrade_plugin_theme() {
313
+ MainWP_Child_Updates::get_instance()->upgrade_plugin_theme();
314
+ }
315
+
316
+ /**
317
+ * Method theme_action()
318
+ *
319
+ * Fire off the theme_action() function.
320
+ *
321
+ * @uses \MainWP\Child\MainWP_Child_Install::theme_action()
322
+ */
323
+ public function theme_action() {
324
+ MainWP_Child_Install::get_instance()->theme_action();
325
+ }
326
+
327
+ /**
328
+ * Method plugin_action()
329
+ *
330
+ * Fire off the plugin_action() function.
331
+ *
332
+ * @uses \MainWP\Child\MainWP_Child_Install::plugin_action()
333
+ */
334
+ public function plugin_action() {
335
+ MainWP_Child_Install::get_instance()->plugin_action();
336
+ }
337
+
338
+ /**
339
+ * Method get_all_plugins()
340
+ *
341
+ * Fire off the get_all_plugins() function.
342
+ *
343
+ * @uses \MainWP\Child\MainWP_Child_Stats::get_all_plugins()
344
+ */
345
+ public function get_all_plugins() {
346
+ MainWP_Child_Stats::get_instance()->get_all_plugins();
347
+ }
348
+
349
+ /**
350
+ * Method get_all_themes()
351
+ *
352
+ * Fire off the get_all_themes() function.
353
+ *
354
+ * @uses \MainWP\Child\MainWP_Child_Stats::get_all_themes()
355
+ */
356
+ public function get_all_themes() {
357
+ MainWP_Child_Stats::get_instance()->get_all_themes();
358
+ }
359
+
360
+ /**
361
+ * Method get_all_users()
362
+ *
363
+ * Fire off the get_all_users() function.
364
+ *
365
+ * @uses \MainWP\Child\MainWP_Child_Users::get_all_users()
366
+ */
367
+ public function get_all_users() {
368
+ MainWP_Child_Users::get_instance()->get_all_users();
369
+ }
370
+
371
+ /**
372
+ * Method user_action()
373
+ *
374
+ * Fire off the user_action() function.
375
+ *
376
+ * @uses \MainWP\Child\MainWP_Child_Users::user_action()
377
+ */
378
+ public function user_action() {
379
+ MainWP_Child_Users::get_instance()->user_action();
380
+ }
381
+
382
+ /**
383
+ * Method search_users()
384
+ *
385
+ * Fire off the search_users() function.
386
+ *
387
+ * @uses \MainWP\Child\MainWP_Child_Users::search_users()
388
+ */
389
+ public function search_users() {
390
+ MainWP_Child_Users::get_instance()->search_users();
391
+ }
392
+
393
+ /**
394
+ * Method get_all_posts()
395
+ *
396
+ * Fire off the get_all_posts() function.
397
+ *
398
+ * @uses \MainWP\Child\MainWP_Child_Posts::get_all_posts()
399
+ */
400
+ public function get_all_posts() {
401
+ MainWP_Child_Posts::get_instance()->get_all_posts();
402
+ }
403
+
404
+ /**
405
+ * Method get_all_pages()
406
+ *
407
+ * Fire off the get_all_pages() function.
408
+ *
409
+ * @uses \MainWP\Child\MainWP_Child_Posts::get_all_pages()
410
+ */
411
+ public function get_all_pages() {
412
+ MainWP_Child_Posts::get_instance()->get_all_pages();
413
+ }
414
+
415
+ /**
416
+ * Method comment_action()
417
+ *
418
+ * Fire off the comment_action() function.
419
+ *
420
+ * @uses \MainWP\Child\MainWP_Child_Comments::comment_action()
421
+ */
422
+ public function comment_action() {
423
+ MainWP_Child_Comments::get_instance()->comment_action();
424
+ }
425
+
426
+ /**
427
+ * Method get_all_comments()
428
+ *
429
+ * Fire off the get_all_comments() function.
430
+ *
431
+ * @uses \MainWP\Child\MainWP_Child_Comments::get_all_comments()
432
+ */
433
+ public function get_all_comments() {
434
+ MainWP_Child_Comments::get_instance()->get_all_comments();
435
+ }
436
+
437
+ /**
438
+ * Method comment_bulk_action()
439
+ *
440
+ * Fire off the comment_bulk_action() function.
441
+ *
442
+ * @uses \MainWP\Child\MainWP_Child_Comments::comment_bulk_action()
443
+ */
444
+ public function comment_bulk_action() {
445
+ MainWP_Child_Comments::get_instance()->comment_bulk_action();
446
+ }
447
+
448
+ /**
449
+ * Method maintenance_site()
450
+ *
451
+ * Fire off the maintenance_site() function.
452
+ *
453
+ * @uses \MainWP\Child\MainWP_Child_Maintenance::maintenance_site()
454
+ */
455
+ public function maintenance_site() {
456
+ MainWP_Child_Maintenance::get_instance()->maintenance_site();
457
+ }
458
+
459
+ /**
460
+ * Method new_post()
461
+ *
462
+ * Fire off the new_post() function.
463
+ *
464
+ * @uses \MainWP\Child\MainWP_Child_Posts::new_post()
465
+ */
466
+ public function new_post() {
467
+ MainWP_Child_Posts::get_instance()->new_post();
468
+ }
469
+
470
+ /**
471
+ * Method post_action()
472
+ *
473
+ * Fire off the post_action() function.
474
+ *
475
+ * @uses \MainWP\Child\MainWP_Child_Posts::post_action()
476
+ */
477
+ public function post_action() {
478
+ MainWP_Child_Posts::get_instance()->post_action();
479
+ }
480
+
481
+ /**
482
+ * Method new_admin_password()
483
+ *
484
+ * Fire off the new_admin_password() function.
485
+ *
486
+ * @uses \MainWP\Child\MainWP_Child_Users::new_admin_password()
487
+ */
488
+ public function new_admin_password() {
489
+ MainWP_Child_Users::get_instance()->new_admin_password();
490
+ }
491
+
492
+ /**
493
+ * Method new_user()
494
+ *
495
+ * Fire off the new_user() function.
496
+ *
497
+ * @uses \MainWP\Child\MainWP_Child_Users::new_user()
498
+ */
499
+ public function new_user() {
500
+ MainWP_Child_Users::get_instance()->new_user();
501
+ }
502
+
503
+ /**
504
+ * Method cloneinfo()
505
+ *
506
+ * Fire off the cloneinfo() function.
507
+ *
508
+ * @uses \MainWP\Child\MainWP_Helper::write()
509
+ */
510
+ public function cloneinfo() {
511
+
512
+ /**
513
+ * WordPress DB Table Prefix.
514
+ *
515
+ * @global string
516
+ */
517
+ global $table_prefix;
518
+
519
+ $information['dbCharset'] = DB_CHARSET;
520
+ $information['dbCollate'] = DB_COLLATE;
521
+ $information['table_prefix'] = $table_prefix;
522
+ $information['site_url'] = get_option( 'site_url' );
523
+ $information['home'] = get_option( 'home' );
524
+
525
+ MainWP_Helper::write( $information );
526
+ }
527
+
528
+ /**
529
+ * Method backup_poll()
530
+ *
531
+ * Fire off the backup_poll() function.
532
+ *
533
+ * @uses \MainWP\Child\MainWP_Backup::backup_poll()
534
+ */
535
+ public function backup_poll() {
536
+ MainWP_Backup::get()->backup_poll();
537
+ }
538
+
539
+ /**
540
+ * Method backup_checkpid()
541
+ *
542
+ * Fire off the backup_checkpid() function.
543
+ *
544
+ * @uses \MainWP\Child\MainWP_Backup::backup_checkpid()
545
+ */
546
+ public function backup_checkpid() {
547
+ MainWP_Backup::get()->backup_checkpid();
548
+ }
549
+
550
+ /**
551
+ * Method backup()
552
+ *
553
+ * Fire off the backup() function.
554
+ *
555
+ * @param bool $write Whether or not to execute MainWP_Helper::write(), Default: true.
556
+ *
557
+ * @return array Action result.
558
+ *
559
+ * @uses \MainWP\Child\MainWP_Backup::backup()
560
+ */
561
+ public function backup( $write = true ) {
562
+ return MainWP_Backup::get()->backup( $write );
563
+ }
564
+
565
+ /**
566
+ * Method backup_full()
567
+ *
568
+ * Fire off the backup_full() function.
569
+ *
570
+ * @param string $file_name Contains the backup file name.
571
+ *
572
+ * @return array Action result.
573
+ *
574
+ * @uses \MainWP\Child\MainWP_Backup::backup_full()
575
+ */
576
+ protected function backup_full( $file_name ) {
577
+ return MainWP_Backup::get()->backup_full( $file_name );
578
+ }
579
+
580
+ /**
581
+ * Method backup_db()
582
+ *
583
+ * Fire off the backup_db() function.
584
+ *
585
+ * @param string $file_name Contains the backup file name.
586
+ * @param string $file_extension Contains the backup file extension.
587
+ *
588
+ * @return array Action result.
589
+ *
590
+ * @uses \MainWP\Child\MainWP_Backup::backup_db()
591
+ */
592
+ protected function backup_db( $file_name = '', $file_extension = 'zip' ) {
593
+ return MainWP_Backup::get()->backup_db( $file_name, $file_extension );
594
+ }
595
+
596
+ /**
597
+ * Method get_site_icon()
598
+ *
599
+ * Fire off the get_site_icon() function.
600
+ *
601
+ * @uses \MainWP\Child\MainWP_Child_Misc::get_site_icon()
602
+ */
603
+ public function get_site_icon() {
604
+ MainWP_Child_Misc::get_instance()->get_site_icon();
605
+ }
606
+
607
+ /**
608
+ * Method check_abandoned()
609
+ *
610
+ * Fire off the check_abandoned() function.
611
+ */
612
+ public function check_abandoned() {
613
+ $which = sanitize_text_field( wp_unslash( $_POST['which'] ) );
614
+ $infor = array();
615
+ if ( 'plugin' == $which ) {
616
+ MainWP_Child_Plugins_Check::instance()->run_check();
617
+ $infor['success'] = 1;
618
+ } else {
619
+ MainWP_Child_Themes_Check::instance()->run_check();
620
+ $infor['success'] = 1;
621
+ }
622
+ $infor['sync'] = MainWP_Child_Stats::get_instance()->get_site_stats( array(), false );
623
+ MainWP_Helper::write( $infor );
624
+ }
625
+
626
+ /**
627
+ * Method get_security_stats()
628
+ *
629
+ * Fire off the get_security_stats() function.
630
+ *
631
+ * @uses \MainWP\Child\MainWP_Child_Misc::get_security_stats()
632
+ */
633
+ public function get_security_stats() {
634
+ MainWP_Child_Misc::get_instance()->get_security_stats();
635
+ }
636
+
637
+ /**
638
+ * Method do_security_fix()
639
+ *
640
+ * Fire off the do_security_fix() function.
641
+ *
642
+ * @uses \MainWP\Child\MainWP_Child_Misc::do_security_fix()
643
+ */
644
+ public function do_security_fix() {
645
+ MainWP_Child_Misc::get_instance()->do_security_fix();
646
+ }
647
+
648
+ /**
649
+ * Method do_security_un_fix()
650
+ *
651
+ * Fire off the do_security_un_fix() function.
652
+ *
653
+ * @uses \MainWP\Child\MainWP_Child_Misc::do_security_un_fix()
654
+ */
655
+ public function do_security_un_fix() {
656
+ MainWP_Child_Misc::get_instance()->do_security_un_fix();
657
+ }
658
+
659
+ /**
660
+ * Method settings_tools()
661
+ *
662
+ * Fire off the settings_tools() function.
663
+ *
664
+ * @uses \MainWP\Child\MainWP_Child_Misc::do_security_un_fix()
665
+ */
666
+ public function settings_tools() {
667
+ MainWP_Child_Misc::get_instance()->do_security_un_fix();
668
+ }
669
+
670
+ /**
671
+ * Method bulk_settings_manager()
672
+ *
673
+ * Fire off the action() function.
674
+ *
675
+ * @uses \MainWP\Child\MainWP_Child_Bulk_Settings_Manager::action()
676
+ */
677
+ public function bulk_settings_manager() {
678
+ MainWP_Child_Bulk_Settings_Manager::instance()->action();
679
+ }
680
+
681
+ /**
682
+ * Method custom_post_type()
683
+ *
684
+ * Fire off the action() function.
685
+ *
686
+ * @uses \MainWP\Child\MainWP_Custom_Post_Type::action()
687
+ */
688
+ public function custom_post_type() {
689
+ MainWP_Custom_Post_Type::instance()->action();
690
+ }
691
+
692
+ /**
693
+ * Method backup_buddy()
694
+ *
695
+ * Fire off the action() function.
696
+ *
697
+ * @uses \MainWP\Child\MainWP_Child_Back_Up_Buddy::action()
698
+ */
699
+ public function backup_buddy() {
700
+ MainWP_Child_Back_Up_Buddy::instance()->action();
701
+ }
702
+
703
+ /**
704
+ * Method vulner_checker()
705
+ *
706
+ * Fire off the action() function.
707
+ *
708
+ * @uses \MainWP\Child\MainWP_Child_Vulnerability_Checker::action()
709
+ */
710
+ public function vulner_checker() {
711
+ MainWP_Child_Vulnerability_Checker::instance()->action();
712
+ }
713
+
714
+ /**
715
+ * Method time_capsule()
716
+ *
717
+ * Fire off the action() function.
718
+ *
719
+ * @uses \MainWP\Child\MainWP_Child_Timecapsule::action()
720
+ */
721
+ public function time_capsule() {
722
+ MainWP_Child_Timecapsule::instance()->action();
723
+ }
724
+
725
+ /**
726
+ * Method wp_staging()
727
+ *
728
+ * Fire off the action() function.
729
+ *
730
+ * @uses \MainWP\Child\MainWP_Child_Staging::action()
731
+ */
732
+ public function wp_staging() {
733
+ MainWP_Child_Staging::instance()->action();
734
+ }
735
+
736
+ /**
737
+ * Method extra_execution()
738
+ *
739
+ * Additional functions to execute.
740
+ *
741
+ * @uses \MainWP\Child\MainWP_Helper::write()
742
+ */
743
+ public function extra_execution() {
744
+ $post = $_POST;
745
+ $information = array();
746
+ /**
747
+ * Filter 'mainwp_child_extra_execution'
748
+ *
749
+ * Additional functions to execute through the filter.
750
+ *
751
+ * @param array $information An array containing the synchronization information.
752
+ * @param mixed $post Contains the POST request.
753
+ *
754
+ * @since 4.0
755
+ */
756
+ $information = apply_filters( 'mainwp_child_extra_execution', $information, $post );
757
+ MainWP_Helper::write( $information );
758
+ }
759
+
760
+ /**
761
+ * Method uploader_action()
762
+ *
763
+ * Fire off the uploader_action() function.
764
+ *
765
+ * @uses \MainWP\Child\MainWP_Child_Misc::uploader_action()
766
+ */
767
+ public function uploader_action() {
768
+ MainWP_Child_Misc::get_instance()->uploader_action();
769
+ }
770
+
771
+ /**
772
+ * Method wordpress_seo()
773
+ *
774
+ * Fire off the action() function.
775
+ */
776
+ public function wordpress_seo() {
777
+ MainWP_WordPress_SEO::instance()->action();
778
+ }
779
+
780
+ /**
781
+ * Method client_report()
782
+ *
783
+ * Fire off the action() function.
784
+ *
785
+ * @uses \MainWP\Child\MainWP_Client_Report::action()
786
+ */
787
+ public function client_report() {
788
+ MainWP_Client_Report::instance()->action();
789
+ }
790
+
791
+ /**
792
+ * Method page_speed()
793
+ *
794
+ * Fire off the action() function.
795
+ *
796
+ * @uses \MainWP\Child\MainWP_Child_Pagespeed::action()
797
+ */
798
+ public function page_speed() {
799
+ MainWP_Child_Pagespeed::instance()->action();
800
+ }
801
+
802
+ /**
803
+ * Method woo_com_status()
804
+ *
805
+ * Fire off the action() function.
806
+ *
807
+ * @uses \MainWP\Child\MainWP_Child_WooCommerce_Status::action()
808
+ */
809
+ public function woo_com_status() {
810
+ MainWP_Child_WooCommerce_Status::instance()->action();
811
+ }
812
+
813
+ /**
814
+ * Method links_checker()
815
+ *
816
+ * Fire off the action() function.
817
+ *
818
+ * @uses \MainWP\Child\MainWP_Child_Links_Checker::action()
819
+ */
820
+ public function links_checker() {
821
+ MainWP_Child_Links_Checker::instance()->action();
822
+ }
823
+
824
+ /**
825
+ * Method wordfence()
826
+ *
827
+ * Fire off the action() function.
828
+ *
829
+ * @uses \MainWP\Child\MainWP_Child_Wordfence::action()
830
+ */
831
+ public function wordfence() {
832
+ MainWP_Child_Wordfence::instance()->action();
833
+ }
834
+
835
+ /**
836
+ * Method ithemes()
837
+ *
838
+ * Fire off the action() function.
839
+ *
840
+ * @uses \MainWP\Child\MainWP_Child_IThemes_Security::action()
841
+ */
842
+ public function ithemes() {
843
+ MainWP_Child_IThemes_Security::instance()->action();
844
+ }
845
+
846
+ /**
847
+ * Method updraftplus()
848
+ *
849
+ * Fire off the action() function.
850
+ *
851
+ * @uses \MainWP\Child\MainWP_Child_Updraft_Plus_Backups::action()
852
+ */
853
+ public function updraftplus() {
854
+ MainWP_Child_Updraft_Plus_Backups::instance()->action();
855
+ }
856
+
857
+ /**
858
+ * Method wpvivid_backuprestore()
859
+ *
860
+ * Fire off the action() function.
861
+ *
862
+ * @uses \MainWP\Child\MainWP_Child_WPvivid_BackupRestore::action()
863
+ */
864
+ public function wpvivid_backuprestore() {
865
+ MainWP_Child_WPvivid_BackupRestore::instance()->action();
866
+ }
867
+
868
+ /**
869
+ * Method backup_wp()
870
+ *
871
+ * Fire off the action() function.
872
+ *
873
+ * @uses \MainWP\Child\MainWP_Child_Back_Up_WordPress::action()
874
+ * @uses \MainWP\Child\MainWP_Helper::write()
875
+ */
876
+ public function backup_wp() {
877
+ if ( ! version_compare( phpversion(), '5.3', '>=' ) ) {
878
+ $error = sprintf( __( 'PHP Version %s is unsupported.', 'mainwp-child' ), phpversion() );
879
+ MainWP_Helper::write( array( 'error' => $error ) );
880
+ }
881
+ MainWP_Child_Back_Up_WordPress::instance()->action();
882
+ }
883
+
884
+ /**
885
+ * Method wp_rocket()
886
+ *
887
+ * Fire off the action() function.
888
+ *
889
+ * @uses \MainWP\Child\MainWP_Child_WP_Rocket::action()
890
+ */
891
+ public function wp_rocket() {
892
+ MainWP_Child_WP_Rocket::instance()->action();
893
+ }
894
+
895
+ /**
896
+ * Method backwpup()
897
+ *
898
+ * Fire off the action() function.
899
+ *
900
+ * @uses \MainWP\Child\MainWP_Child_Back_WP_Up::action()
901
+ */
902
+ public function backwpup() {
903
+ MainWP_Child_Back_WP_Up::instance()->action();
904
+ }
905
+
906
+ /**
907
+ * Method delete_backup()
908
+ *
909
+ * Delete backup.
910
+ *
911
+ * @uses \MainWP\Child\MainWP_Helper::get_mainwp_dir()
912
+ * @uses \MainWP\Child\MainWP_Helper::write()
913
+ */
914
+ public function delete_backup() {
915
+ $dirs = MainWP_Helper::get_mainwp_dir( 'backup' );
916
+ $backupdir = $dirs[0];
917
+
918
+ $file = isset( $_REQUEST['del'] ) ? wp_unslash( $_REQUEST['del'] ) : '';
919
+
920
+ if ( file_exists( $backupdir . $file ) ) {
921
+ unlink( $backupdir . $file );
922
+ }
923
+
924
+ MainWP_Helper::write( array( 'result' => 'ok' ) );
925
+ }
926
+
927
+ /**
928
+ * Method update_child_values()
929
+ *
930
+ * Update the MainWP Child site options.
931
+ *
932
+ * @uses \MainWP\Child\MainWP_Helper::update_option()
933
+ * @uses \MainWP\Child\MainWP_Helper::write()
934
+ */
935
+ public function update_child_values() {
936
+ $unique_id = isset( $_POST['uniqueId'] ) ? sanitize_text_field( wp_unslash( $_POST['uniqueId'] ) ) : '';
937
+ MainWP_Helper::update_option( 'mainwp_child_uniqueId', $unique_id );
938
+ MainWP_Helper::write( array( 'result' => 'ok' ) );
939
+ }
940
+
941
+ /**
942
+ * Method branding_child_plugin()
943
+ *
944
+ * Fire off the action() function.
945
+ *
946
+ * @uses \MainWP\Child\MainWP_Child_Branding::action()
947
+ */
948
+ public function branding_child_plugin() {
949
+ MainWP_Child_Branding::instance()->action();
950
+ }
951
+
952
+ /**
953
+ * Method code_snippet()
954
+ *
955
+ * Fire off the code_snippet() function.
956
+ *
957
+ * @uses MainWP_Child_Misc::code_snippet()
958
+ */
959
+ public function code_snippet() {
960
+ MainWP_Child_Misc::get_instance()->code_snippet();
961
+ }
962
+
963
+ /**
964
+ * Method disconnect()
965
+ *
966
+ * Disconnect the child site from the current MainWP Dashboard.
967
+ *
968
+ * @uses \MainWP\Child\MainWP_Helper::write()
969
+ */
970
+ public function disconnect() {
971
+
972
+ /**
973
+ * MainWP Child instance.
974
+ *
975
+ * @global object
976
+ */
977
+ global $mainWPChild;
978
+
979
+ $mainWPChild->deactivation( false );
980
+ MainWP_Helper::write( array( 'result' => 'success' ) );
981
+ }
982
+
983
+
984
+ /**
985
+ * Method deactivate()
986
+ *
987
+ * Deactivate the MainWP Child plugin in the site.
988
+ *
989
+ * @uses \MainWP\Child\MainWP_Helper::errpr()
990
+ * @uses \MainWP\Child\MainWP_Helper::write()
991
+ */
992
+ public function deactivate() {
993
+
994
+ /**
995
+ * MainWP Child instance.
996
+ *
997
+ * @global object
998
+ */
999
+ global $mainWPChild;
1000
+
1001
+ include_once ABSPATH . 'wp-admin/includes/plugin.php';
1002
+ deactivate_plugins( $mainWPChild->plugin_slug, true );
1003
+ $information = array();
1004
+ if ( is_plugin_active( $mainWPChild->plugin_slug ) ) {
1005
+ MainWP_Helper::instance()->error( 'Plugin still active' );
1006
+ }
1007
+ $information['deactivated'] = true;
1008
+ MainWP_Helper::write( $information );
1009
+ }
1010
+
1011
+ }
class/class-mainwp-child-ithemes-security.php CHANGED
@@ -322,7 +322,7 @@ class MainWP_Child_IThemes_Security {
322
  if ( 'wordpress-salts' == $module ) {
323
  $settings['last_generated'] = \ITSEC_Modules::get_setting( $module, 'last_generated' );
324
  } elseif ( 'global' == $module ) {
325
- $keep_olds = array( 'did_upgrade', 'log_info', 'show_new_dashboard_notice', 'show_security_check', 'nginx_file' );
326
  foreach ( $keep_olds as $key ) {
327
  $settings[ $key ] = \ITSEC_Modules::get_setting( $module, $key );
328
  }
@@ -897,10 +897,16 @@ class MainWP_Child_IThemes_Security {
897
  if ( ! class_exists( '\ITSEC_File_Change_Scanner' ) ) {
898
  require_once $mainwp_itsec_modules_path . 'file-change/scanner.php';
899
  }
900
- $result = \ITSEC_File_Change_Scanner::run_scan( false );
901
- if ( false === $result || true === $result || -1 === $result ) {
 
 
 
 
 
 
902
  $return['result'] = 'success';
903
- $return['scan_result'] = $result;
904
  }
905
  return $return;
906
  }
322
  if ( 'wordpress-salts' == $module ) {
323
  $settings['last_generated'] = \ITSEC_Modules::get_setting( $module, 'last_generated' );
324
  } elseif ( 'global' == $module ) {
325
+ $keep_olds = array( 'did_upgrade', 'log_info', 'show_new_dashboard_notice', 'show_security_check', 'nginx_file', 'manage_group' );
326
  foreach ( $keep_olds as $key ) {
327
  $settings[ $key ] = \ITSEC_Modules::get_setting( $module, $key );
328
  }
897
  if ( ! class_exists( '\ITSEC_File_Change_Scanner' ) ) {
898
  require_once $mainwp_itsec_modules_path . 'file-change/scanner.php';
899
  }
900
+
901
+ $results = \ITSEC_File_Change_Scanner::schedule_start();
902
+
903
+ if ( is_wp_error( $results ) ) {
904
+ $error = $results->get_error_message();
905
+ $return['result'] = 'failed';
906
+ $return['scan_error'] = $error;
907
+ } else {
908
  $return['result'] = 'success';
909
+ $return['scan_result'] = $results;
910
  }
911
  return $return;
912
  }
class/class-mainwp-child-stats.php CHANGED
@@ -698,12 +698,13 @@ class MainWP_Child_Stats {
698
  private function stats_get_total_size() {
699
  $total = null;
700
 
701
- $get_file_size = apply_filters_deprecated( 'mainwp-child-get-total-size', array( true ), '4.0.7.1', 'mainwp_child_get_total_size' );
702
- $get_file_size = apply_filters( 'mainwp_child_get_total_size', $get_file_size );
 
703
 
704
- if ( $get_file_size && isset( $_POST['cloneSites'] ) && ( '0' !== $_POST['cloneSites'] ) ) {
705
  $max_exe = ini_get( 'max_execution_time' );
706
- if ( $max_exe > 20 ) {
707
  $total = $this->get_total_file_size();
708
  }
709
  }
698
  private function stats_get_total_size() {
699
  $total = null;
700
 
701
+ $get_file_size = apply_filters_deprecated( 'mainwp-child-get-total-size', array( true ), '4.0.7.1', 'mainwp_child_get_total_size' );
702
+ $get_file_size = apply_filters( 'mainwp_child_get_total_size', $get_file_size );
703
+ $forced_get_file_size = apply_filters( 'mainwp_child_forced_get_total_size', false );
704
 
705
+ if ( $forced_get_file_size || ( $get_file_size && isset( $_POST['cloneSites'] ) && ( '0' !== $_POST['cloneSites'] ) ) ) {
706
  $max_exe = ini_get( 'max_execution_time' );
707
+ if ( $forced_get_file_size || $max_exe > 20 ) {
708
  $total = $this->get_total_file_size();
709
  }
710
  }
class/class-mainwp-child-vulnerability-checker.php CHANGED
@@ -41,6 +41,13 @@ class MainWP_Child_Vulnerability_Checker {
41
  */
42
  private $wpvulndb_api = 'https://wpvulndb.com/api/v3/';
43
 
 
 
 
 
 
 
 
44
  /**
45
  * Whether or not to use wpvulndb_token. Default: false.
46
  *
@@ -57,9 +64,9 @@ class MainWP_Child_Vulnerability_Checker {
57
  */
58
  public static function instance() {
59
  if ( null === self::$instance ) {
60
- self::$instance = new self();
61
  }
62
- return self::$instance;
63
  }
64
 
65
  /**
@@ -100,9 +107,10 @@ class MainWP_Child_Vulnerability_Checker {
100
  public function vulner_recheck() {
101
  $result = array();
102
  $force = ( isset( $_POST['force'] ) && ! empty( $_POST['force'] ) ) ? true : false;
103
- $result['plugin'] = $this->check_plugins( $force );
104
- $result['wp'] = $this->check_wp( $force );
105
- $result['theme'] = $this->check_themes( $force );
 
106
  $information = array(
107
  'result' => $result,
108
  'ok' => 1,
@@ -114,9 +122,11 @@ class MainWP_Child_Vulnerability_Checker {
114
  * Check for plugin vulnerabilities.
115
  *
116
  * @param bool $force Whether or not to force check. Default: false.
 
 
117
  * @return array Return $result array.
118
  */
119
- public function check_plugins( $force = false ) {
120
  $result = array();
121
  $active_plugins = get_option( 'active_plugins' );
122
 
@@ -129,31 +139,45 @@ class MainWP_Child_Vulnerability_Checker {
129
  $string = explode( '/', $plug );
130
  $plug_vuln = get_transient( 'mainwp_vulnche_trans_plug_' . $string[0] );
131
  if ( false === $plug_vuln || $force ) {
132
- $plug_vuln = $this->vulnche_get_content( $this->wpvulndb_api . 'plugins/' . $string[0] );
 
 
 
 
 
 
 
 
 
133
  set_transient( 'mainwp_vulnche_trans_plug_' . $string[0], $plug_vuln, 1 * DAY_IN_SECONDS );
134
  }
135
  if ( $plug_vuln ) {
136
- $plug_vuln = json_decode( $plug_vuln, true );
137
- $plug_vuln_filter = $plug_vuln;
138
- foreach ( $plug_vuln as $slug => $pl_data ) {
139
- if ( isset( $pl_data['vulnerabilities'] ) && count( $pl_data['vulnerabilities'] ) > 0 ) {
140
- $plug_vulner_data = array();
141
- foreach ( $pl_data['vulnerabilities'] as $vuln_data ) {
142
- if ( isset( $vuln_data['fixed_in'] ) && version_compare( $plugin_version, $vuln_data['fixed_in'] ) >= 0 ) {
143
- continue;
 
 
 
 
 
 
144
  }
145
- $plug_vulner_data[] = $vuln_data;
146
- }
147
 
148
- if ( 0 == count( $plug_vulner_data ) ) {
149
- unset( $plug_vuln_filter[ $slug ] );
 
 
 
 
 
150
  } else {
151
- $plug_vuln_filter[ $slug ]['vulnerabilities'] = $plug_vulner_data;
152
- $plug_vuln_filter[ $slug ]['detected_version'] = $plugin_version;
153
- $plug_vuln_filter[ $slug ]['plugin_slug'] = $plug;
154
  }
155
- } else {
156
- unset( $plug_vuln_filter[ $slug ] );
157
  }
158
  }
159
 
@@ -174,13 +198,25 @@ class MainWP_Child_Vulnerability_Checker {
174
  * Check for WP vulnerabilities.
175
  *
176
  * @param bool $force Whether or not to force check. Default: false.
 
177
  * @return bool|string|null
178
  */
179
- public function check_wp( $force = false ) {
180
- $wp_vuln = get_transient( 'mainwp_vulnche_trans_wp_json' );
181
- $wp_version = str_replace( '.', '', get_bloginfo( 'version' ) );
 
182
  if ( false === $wp_vuln || $force ) {
183
- $wp_vuln = $this->vulnche_get_content( $this->wpvulndb_api . 'wordpresses/' . $wp_version );
 
 
 
 
 
 
 
 
 
 
184
  set_transient( 'mainwp_vulnche_trans_wp_json', $wp_vuln, 1 * DAY_IN_SECONDS );
185
  }
186
  return $wp_vuln;
@@ -190,9 +226,11 @@ class MainWP_Child_Vulnerability_Checker {
190
  * Check if themes have vunerabilities.
191
  *
192
  * @param bool $force Whether or not to force check. Default: false.
 
 
193
  * @return array Return $result array.
194
  */
195
- public function check_themes( $force = false ) {
196
 
197
  include_once ABSPATH . '/wp-admin/includes/update.php';
198
  require_once ABSPATH . 'wp-admin/includes/misc.php';
@@ -210,38 +248,51 @@ class MainWP_Child_Vulnerability_Checker {
210
  if ( empty( $th['parent'] ) ) {
211
  $th_vuln = get_transient( 'mainwp_vulnche_trans_theme_' . $th['id'] );
212
  if ( false === $th_vuln || $force ) {
213
- $th_vuln = $this->vulnche_get_content( $this->wpvulndb_api . 'themes/' . $th['id'] );
 
 
 
 
 
 
 
214
  set_transient( 'mainwp_vulnche_trans_theme_' . $th['id'], $th_vuln, 1 * DAY_IN_SECONDS );
215
  }
216
 
217
  if ( $th_vuln ) {
218
- $th_vuln = json_decode( $th_vuln, true );
219
- $th_vuln_filter = $th_vuln;
220
- foreach ( $th_vuln as $slug => $th_data ) {
221
- if ( isset( $th_data['vulnerabilities'] ) && count( $th_data['vulnerabilities'] ) > 0 ) {
222
- $th_vulner_data = array();
223
- foreach ( $th_data['vulnerabilities'] as $vuln_data ) {
224
- if ( empty( $vuln_data ) ) {
225
- continue;
 
 
 
 
 
 
 
 
226
  }
227
- if ( isset( $vuln_data['fixed_in'] ) && version_compare( $th['version'], $vuln_data['fixed_in'] ) >= 0 ) {
228
- continue;
 
 
229
  }
230
- $th_vulner_data[] = $vuln_data;
231
- }
232
- if ( 0 == count( $th_vulner_data ) ) {
233
- unset( $th_vuln_filter[ $slug ] );
234
  } else {
235
- $th_vuln_filter[ $slug ]['vulnerabilities'] = $th_vulner_data;
236
  }
237
- } else {
238
- unset( $th_vuln_filter[ $slug ] );
239
  }
240
  }
 
241
  if ( 0 == count( $th_vuln_filter ) ) {
242
  continue;
243
  }
244
  $th_vuln = wp_json_encode( $th_vuln_filter );
 
245
  } else {
246
  continue;
247
  }
@@ -255,20 +306,187 @@ class MainWP_Child_Vulnerability_Checker {
255
  return $result;
256
  }
257
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
258
  /**
259
  * Check if content is vulnerable.
260
  *
261
  * @param string $url URL to check.
 
262
  *
263
  * @return bool|string|null
264
  */
265
- public function vulnche_get_content( $url ) {
266
 
267
  // phpcs:disable WordPress.WP.AlternativeFunctions -- Required to achieve desired results, pull request solutions appreciated.
268
  $ch = curl_init();
269
  curl_setopt( $ch, CURLOPT_URL, $url );
270
  curl_setopt( $ch, CURLOPT_HEADER, 0 );
271
- curl_setopt( $ch, CURLOPT_HTTPHEADER, array( 'Authorization: Token token=' . $this->wpvulndb_token ) );
 
 
272
  curl_setopt( $ch, CURLOPT_USERAGENT, $this->get_random_user_agent() );
273
  curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
274
 
41
  */
42
  private $wpvulndb_api = 'https://wpvulndb.com/api/v3/';
43
 
44
+ /**
45
+ * Nvd.nist.gov API URL
46
+ *
47
+ * @var string
48
+ */
49
+ private $wpvulndb_nvd_api = 'https://services.nvd.nist.gov/rest/json/cves/1.0';
50
+
51
  /**
52
  * Whether or not to use wpvulndb_token. Default: false.
53
  *
64
  */
65
  public static function instance() {
66
  if ( null === self::$instance ) {
67
+ self::$instance = new self();
68
  }
69
+ return self::$instance;
70
  }
71
 
72
  /**
107
  public function vulner_recheck() {
108
  $result = array();
109
  $force = ( isset( $_POST['force'] ) && ! empty( $_POST['force'] ) ) ? true : false;
110
+ $service = ( isset( $_POST['service'] ) && 'nvd_nist' == $_POST['service'] ) ? 'nvd_nist' : 'wpvulndb';
111
+ $result['plugin'] = $this->check_plugins( $force, $service );
112
+ $result['wp'] = $this->check_wp( $force, $service );
113
+ $result['theme'] = $this->check_themes( $force, $service );
114
  $information = array(
115
  'result' => $result,
116
  'ok' => 1,
122
  * Check for plugin vulnerabilities.
123
  *
124
  * @param bool $force Whether or not to force check. Default: false.
125
+ * @param bool $service Selected service.
126
+ *
127
  * @return array Return $result array.
128
  */
129
+ public function check_plugins( $force = false, $service ) {
130
  $result = array();
131
  $active_plugins = get_option( 'active_plugins' );
132
 
139
  $string = explode( '/', $plug );
140
  $plug_vuln = get_transient( 'mainwp_vulnche_trans_plug_' . $string[0] );
141
  if ( false === $plug_vuln || $force ) {
142
+
143
+ if ( 'nvd_nist' == $service ) {
144
+ if ( 'wordfence' == strtolower( $string[0] ) ) {
145
+ continue;
146
+ }
147
+ $url = $this->wpvulndb_nvd_api . '?keyword=' . $string[0];
148
+ } else {
149
+ $url = $this->wpvulndb_api . 'plugins/' . $string[0];
150
+ }
151
+ $plug_vuln = $this->vulnche_get_content( $url, $service );
152
  set_transient( 'mainwp_vulnche_trans_plug_' . $string[0], $plug_vuln, 1 * DAY_IN_SECONDS );
153
  }
154
  if ( $plug_vuln ) {
155
+ $plug_vuln_filter = array();
156
+ if ( 'nvd_nist' == $service ) {
157
+ $plug_vuln_filter = $this->get_vuln_nvd_nist_info( $plug_vuln, $string[0], $plugin_version );
158
+ } else {
159
+ $plug_vuln = json_decode( $plug_vuln, true );
160
+ $plug_vuln_filter = $plug_vuln;
161
+ foreach ( $plug_vuln as $slug => $pl_data ) {
162
+ if ( isset( $pl_data['vulnerabilities'] ) && count( $pl_data['vulnerabilities'] ) > 0 ) {
163
+ $plug_vulner_data = array();
164
+ foreach ( $pl_data['vulnerabilities'] as $vuln_data ) {
165
+ if ( isset( $vuln_data['fixed_in'] ) && version_compare( $plugin_version, $vuln_data['fixed_in'] ) >= 0 ) {
166
+ continue;
167
+ }
168
+ $plug_vulner_data[] = $vuln_data;
169
  }
 
 
170
 
171
+ if ( 0 == count( $plug_vulner_data ) ) {
172
+ unset( $plug_vuln_filter[ $slug ] );
173
+ } else {
174
+ $plug_vuln_filter[ $slug ]['vulnerabilities'] = $plug_vulner_data;
175
+ $plug_vuln_filter[ $slug ]['detected_version'] = $plugin_version;
176
+ $plug_vuln_filter[ $slug ]['plugin_slug'] = $plug;
177
+ }
178
  } else {
179
+ unset( $plug_vuln_filter[ $slug ] );
 
 
180
  }
 
 
181
  }
182
  }
183
 
198
  * Check for WP vulnerabilities.
199
  *
200
  * @param bool $force Whether or not to force check. Default: false.
201
+ * @param bool $service Selected service.
202
  * @return bool|string|null
203
  */
204
+ public function check_wp( $force = false, $service ) {
205
+ $wp_vuln = get_transient( 'mainwp_vulnche_trans_wp_json' );
206
+ $wp_version = get_bloginfo( 'version' );
207
+ $number_version = str_replace( '.', '', $wp_version );
208
  if ( false === $wp_vuln || $force ) {
209
+ if ( 'nvd_nist' == $service ) {
210
+ $url = $this->wpvulndb_nvd_api . '?cpeMatchString=cpe:2.3:a:WordPress:WordPress';
211
+ } else {
212
+ $url = $this->wpvulndb_api . 'wordpresses/' . $number_version;
213
+ }
214
+ $wp_vuln = $this->vulnche_get_content( $url, $service );
215
+
216
+ if ( 'nvd_nist' == $service ) {
217
+ $wp_vuln = $this->get_vuln_nvd_nist_info( $wp_vuln, 'WordPress', $wp_version );
218
+ $wp_vuln = wp_json_encode( $wp_vuln );
219
+ }
220
  set_transient( 'mainwp_vulnche_trans_wp_json', $wp_vuln, 1 * DAY_IN_SECONDS );
221
  }
222
  return $wp_vuln;
226
  * Check if themes have vunerabilities.
227
  *
228
  * @param bool $force Whether or not to force check. Default: false.
229
+ * @param bool $service Selected service.
230
+ *
231
  * @return array Return $result array.
232
  */
233
+ public function check_themes( $force = false, $service ) { // phpcs:ignore -- ignore complex method notice.
234
 
235
  include_once ABSPATH . '/wp-admin/includes/update.php';
236
  require_once ABSPATH . 'wp-admin/includes/misc.php';
248
  if ( empty( $th['parent'] ) ) {
249
  $th_vuln = get_transient( 'mainwp_vulnche_trans_theme_' . $th['id'] );
250
  if ( false === $th_vuln || $force ) {
251
+
252
+ if ( 'nvd_nist' == $service ) {
253
+ $url = $this->wpvulndb_nvd_api . '?keyword=' . $th['id'];
254
+ } else {
255
+ $url = $this->wpvulndb_api . 'themes/' . $th['id'];
256
+ }
257
+
258
+ $th_vuln = $this->vulnche_get_content( $url, $service );
259
  set_transient( 'mainwp_vulnche_trans_theme_' . $th['id'], $th_vuln, 1 * DAY_IN_SECONDS );
260
  }
261
 
262
  if ( $th_vuln ) {
263
+ if ( 'nvd_nist' == $service ) {
264
+ $th_vuln_filter = $this->get_vuln_nvd_nist_info( $th_vuln, $th['id'], $th['version'] );
265
+ } else {
266
+ $th_vuln = json_decode( $th_vuln, true );
267
+ $th_vuln_filter = $th_vuln;
268
+ foreach ( $th_vuln as $slug => $th_data ) {
269
+ if ( isset( $th_data['vulnerabilities'] ) && count( $th_data['vulnerabilities'] ) > 0 ) {
270
+ $th_vulner_data = array();
271
+ foreach ( $th_data['vulnerabilities'] as $vuln_data ) {
272
+ if ( empty( $vuln_data ) ) {
273
+ continue;
274
+ }
275
+ if ( isset( $vuln_data['fixed_in'] ) && version_compare( $th['version'], $vuln_data['fixed_in'] ) >= 0 ) {
276
+ continue;
277
+ }
278
+ $th_vulner_data[] = $vuln_data;
279
  }
280
+ if ( 0 == count( $th_vulner_data ) ) {
281
+ unset( $th_vuln_filter[ $slug ] );
282
+ } else {
283
+ $th_vuln_filter[ $slug ]['vulnerabilities'] = $th_vulner_data;
284
  }
 
 
 
 
285
  } else {
286
+ unset( $th_vuln_filter[ $slug ] );
287
  }
 
 
288
  }
289
  }
290
+
291
  if ( 0 == count( $th_vuln_filter ) ) {
292
  continue;
293
  }
294
  $th_vuln = wp_json_encode( $th_vuln_filter );
295
+
296
  } else {
297
  continue;
298
  }
306
  return $result;
307
  }
308
 
309
+ /**
310
+ * Check if content is vulnerable.
311
+ *
312
+ * @param mixed $data data of check.
313
+ * @param string $slug slug.
314
+ * @param string $version Current version.
315
+ *
316
+ * @return bool|string|null
317
+ */
318
+ public function get_vuln_nvd_nist_info( $data, $slug, $version ) { // phpcs:ignore -- ignore complex method notice.
319
+ $data = json_decode( $data, true );
320
+
321
+ $filtered_data = array();
322
+ if ( is_array( $data ) && isset( $data['result'] ) && isset( $data['result']['CVE_Items'] ) ) {
323
+ $vulns = array();
324
+
325
+ foreach ( $data['result']['CVE_Items'] as $item ) {
326
+ $info = array();
327
+
328
+ if ( isset( $item['publishedDate'] ) ) {
329
+ $info['date'] = $item['publishedDate'];
330
+ }
331
+
332
+ if ( isset( $item['cve']['description']['description_data'][0]['value'] ) ) {
333
+ $info['detail'] = $item['cve']['description']['description_data'][0]['value'];
334
+ }
335
+
336
+ $version_missed = true;
337
+ if ( ! empty( $info ) ) {
338
+ $info['cve_id'] = $item['cve']['CVE_data_meta']['ID'];
339
+ $info['slug'] = $slug;
340
+
341
+ $fixed = false;
342
+ if ( 'WordPress' == $slug ) {
343
+ $founded = false;
344
+ if ( isset( $item['configurations'] ) && isset( $item['configurations']['nodes'] ) ) {
345
+ foreach ( $item['configurations']['nodes'] as $conf_node ) {
346
+ if ( isset( $conf_node['cpe_match'] ) ) {
347
+ foreach ( $conf_node['cpe_match'] as $cpe_match ) {
348
+ if ( ! isset( $cpe_match['cpe23Uri'] ) || false === strpos( $cpe_match['cpe23Uri'], 'cpe:2.3:a:WordPress:WordPress' ) ) {
349
+ continue;
350
+ }
351
+ $founded = true;
352
+ if ( isset( $cpe_match['versionEndExcluding'] ) ) {
353
+ $version_end_excluding = $cpe_match['versionEndExcluding'];
354
+ if ( version_compare( $version, $version_end_excluding ) >= 0 ) {
355
+ $fixed = true; // to continue.
356
+ }
357
+ $version_missed = false;
358
+ } elseif ( isset( $cpe_match['versionEndIncluding'] ) ) {
359
+ $version_end_including = $cpe_match['versionEndIncluding'];
360
+ if ( version_compare( $version, $version_end_including ) >= 0 ) {
361
+ $fixed = true; // to continue.
362
+ }
363
+ $version_missed = false;
364
+ }
365
+ if ( $fixed ) {
366
+ break;
367
+ }
368
+ }
369
+ }
370
+
371
+ if ( ! $fixed && isset( $conf_node['children'] ) ) {
372
+ foreach ( $conf_node['children'] as $child_node ) {
373
+ if ( isset( $child_node['cpe_match'] ) ) {
374
+ foreach ( $child_node['cpe_match'] as $cpe_match ) {
375
+ if ( ! isset( $cpe_match['cpe23Uri'] ) || false === strpos( $cpe_match['cpe23Uri'], 'cpe:2.3:a:WordPress:WordPress' ) ) {
376
+ continue;
377
+ }
378
+ $founded = true;
379
+ if ( isset( $cpe_match['versionEndExcluding'] ) ) {
380
+ $version_end_excluding = $cpe_match['versionEndExcluding'];
381
+ if ( version_compare( $version, $version_end_excluding ) >= 0 ) {
382
+ $fixed = true; // to continue.
383
+ }
384
+ $version_missed = false;
385
+ } elseif ( isset( $cpe_match['versionEndIncluding'] ) ) {
386
+ $version_end_including = $cpe_match['versionEndIncluding'];
387
+ if ( version_compare( $version, $version_end_including ) >= 0 ) {
388
+ $fixed = true; // to continue.
389
+ }
390
+ $version_missed = false;
391
+ }
392
+ if ( $fixed ) {
393
+ break;
394
+ }
395
+ }
396
+ }
397
+ }
398
+ }
399
+ }
400
+ }
401
+ if ( ! $founded ) {
402
+ continue;
403
+ }
404
+ } else {
405
+ if ( isset( $item['configurations'] ) && isset( $item['configurations']['nodes'] ) ) {
406
+ foreach ( $item['configurations']['nodes'] as $conf_node ) {
407
+ if ( isset( $conf_node['cpe_match'] ) ) {
408
+ foreach ( $conf_node['cpe_match'] as $cpe_match ) {
409
+
410
+ if ( isset( $cpe_match['versionEndExcluding'] ) ) {
411
+ $version_end_excluding = $cpe_match['versionEndExcluding'];
412
+ if ( version_compare( $version, $version_end_excluding ) >= 0 ) {
413
+ $fixed = true; // to continue.
414
+ }
415
+ $version_missed = false;
416
+ } elseif ( isset( $cpe_match['versionEndIncluding'] ) ) {
417
+ $version_end_including = $cpe_match['versionEndIncluding'];
418
+ if ( version_compare( $version, $version_end_including ) >= 0 ) {
419
+ $fixed = true; // to continue.
420
+ }
421
+ $version_missed = false;
422
+ }
423
+ if ( $fixed ) {
424
+ break;
425
+ }
426
+ }
427
+ }
428
+
429
+ if ( ! $fixed && isset( $conf_node['children'] ) ) {
430
+ foreach ( $conf_node['children'] as $child_node ) {
431
+ if ( isset( $child_node['cpe_match'] ) ) {
432
+ foreach ( $child_node['cpe_match'] as $cpe_match ) {
433
+ if ( isset( $cpe_match['versionEndExcluding'] ) ) {
434
+ $version_end_excluding = $cpe_match['versionEndExcluding'];
435
+ if ( version_compare( $version, $version_end_excluding ) >= 0 ) {
436
+ $fixed = true; // to continue.
437
+ }
438
+ $version_missed = false;
439
+ } elseif ( isset( $cpe_match['versionEndIncluding'] ) ) {
440
+ $version_end_including = $cpe_match['versionEndIncluding'];
441
+ if ( version_compare( $version, $version_end_including ) >= 0 ) {
442
+ $fixed = true; // to continue.
443
+ }
444
+ $version_missed = false;
445
+ }
446
+ if ( $fixed ) {
447
+ break;
448
+ }
449
+ }
450
+ }
451
+ }
452
+ }
453
+ }
454
+ }
455
+ }
456
+
457
+ // put here.
458
+ if ( $fixed ) {
459
+ continue;
460
+ }
461
+ if ( $version_missed ) {
462
+ $info['missed_version'] = 1;
463
+ }
464
+ $vulns[] = $info;
465
+ }
466
+ }
467
+ $filtered_data[ $slug ]['vulnerabilities'] = $vulns;
468
+ }
469
+
470
+ return $filtered_data;
471
+ }
472
+
473
  /**
474
  * Check if content is vulnerable.
475
  *
476
  * @param string $url URL to check.
477
+ * @param string $service service to check.
478
  *
479
  * @return bool|string|null
480
  */
481
+ public function vulnche_get_content( $url, $service ) {
482
 
483
  // phpcs:disable WordPress.WP.AlternativeFunctions -- Required to achieve desired results, pull request solutions appreciated.
484
  $ch = curl_init();
485
  curl_setopt( $ch, CURLOPT_URL, $url );
486
  curl_setopt( $ch, CURLOPT_HEADER, 0 );
487
+ if ( 'nvd_nist' !== $service ) {
488
+ curl_setopt( $ch, CURLOPT_HTTPHEADER, array( 'Authorization: Token token=' . $this->wpvulndb_token ) );
489
+ }
490
  curl_setopt( $ch, CURLOPT_USERAGENT, $this->get_random_user_agent() );
491
  curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
492
 
class/class-mainwp-child-woocommerce-status.php CHANGED
@@ -1,493 +1,493 @@
1
- <?php
2
- /**
3
- * MainWP Child Woocomerce Status
4
- *
5
- * MainWP WooCommerce Status Extension handler.
6
- *
7
- * @link https://mainwp.com/extension/woocommerce-status/
8
- *
9
- * @package MainWP\Child
10
- *
11
- * Credits
12
- *
13
- * Plugin-Name: WooCommerce
14
- * Plugin URI: https://woocommerce.com/
15
- * Author: Automattic
16
- * Author URI: https://woocommerce.com
17
- */
18
-
19
- namespace MainWP\Child;
20
-
21
- // phpcs:disable PSR1.Classes.ClassDeclaration, WordPress.WP.AlternativeFunctions -- Required to achieve desired results, pull request solutions appreciated.
22
-
23
- /**
24
- * Class MainWP_Child_WooCommerce_Status
25
- *
26
- * MainWP WooCommerce Status Extension handler.
27
- */
28
- class MainWP_Child_WooCommerce_Status {
29
-
30
- /**
31
- * Public static variable to hold the single instance of the class.
32
- *
33
- * @var mixed Default null
34
- */
35
- public static $instance = null;
36
-
37
- /**
38
- * Method instance()
39
- *
40
- * Create a public static instance.
41
- *
42
- * @return mixed Class instance.
43
- */
44
- public static function instance() {
45
- if ( null === self::$instance ) {
46
- self::$instance = new self();
47
- }
48
-
49
- return self::$instance;
50
- }
51
-
52
- /**
53
- * MainWP_Child_WooCommerce_Status constructor.
54
- *
55
- * Run any time class is called.
56
- */
57
- public function __construct() {
58
- add_action( 'mainwp_child_deactivation', array( $this, 'child_deactivation' ) );
59
- }
60
-
61
- /**
62
- * MainWP Child Plugin deactivation hooks.
63
- */
64
- public function child_deactivation() {
65
- }
66
-
67
- /**
68
- * MainWP Child Woocommerce actions: sync_data, report_data, update_wc_db.
69
- *
70
- * @uses \MainWP\Child\MainWP_Helper::write()
71
- */
72
- public function action() {
73
- $information = array();
74
- if ( ! class_exists( '\WooCommerce' ) || ! defined( 'WC_VERSION' ) ) {
75
- $information['error'] = 'NO_WOOCOMMERCE';
76
- MainWP_Helper::write( $information );
77
- }
78
-
79
- $is_ver220 = $this->is_version_220();
80
- if ( isset( $_POST['mwp_action'] ) ) {
81
- $mwp_action = ! empty( $_POST['mwp_action'] ) ? sanitize_text_field( wp_unslash( $_POST['mwp_action'] ) ) : '';
82
- switch ( $mwp_action ) {
83
- case 'sync_data':
84
- $information = ! $is_ver220 ? $this->sync_data() : $this->sync_data_two();
85
- break;
86
- case 'report_data':
87
- $information = ! $is_ver220 ? $this->report_data() : $this->report_data_two();
88
- break;
89
- case 'update_wc_db':
90
- $information = $this->update_wc_db();
91
- break;
92
- }
93
- }
94
- MainWP_Helper::write( $information );
95
- }
96
-
97
- /**
98
- * Compare woocommerce versions.
99
- *
100
- * By default, version_compare returns -1 if the first version is lower than the second,
101
- * 0 if they are equal, and 1 if the second is lower.
102
- * When using the optional operator argument, the function will return true if the relationship is
103
- * the one specified by the operator, false otherwise.
104
- *
105
- * @return bool|int Comparison response.
106
- */
107
- public function is_version_220() {
108
- return version_compare( WC()->version, '2.2.0', '>=' );
109
- }
110
-
111
- /**
112
- * Sync Woocommerce data.
113
- *
114
- * @return array $information Woocommerce data grabed.
115
- */
116
- public function sync_data() {
117
-
118
- /**
119
- * Object, providing access to the WordPress database.
120
- *
121
- * @global object $wpdb WordPress Database instance.
122
- */
123
- global $wpdb;
124
-
125
- $file = WP_PLUGIN_DIR . '/woocommerce/includes/admin/reports/class-wc-admin-report.php';
126
- if ( file_exists( $file ) ) {
127
- include_once $file;
128
- } else {
129
- return false;
130
- }
131
-
132
- // Get sales.
133
- $sales = $wpdb->get_var(
134
- $wpdb->prepare(
135
- "SELECT SUM( postmeta.meta_value ) FROM {$wpdb->posts} as posts
136
- LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID=rel.object_ID
137
- LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id )
138
- LEFT JOIN {$wpdb->terms} AS term USING( term_id )
139
- LEFT JOIN {$wpdb->postmeta} AS postmeta ON posts.ID = postmeta.post_id
140
- WHERE posts.post_type = 'shop_order'
141
- AND posts.post_status = 'publish'
142
- AND tax.taxonomy = 'shop_order_status'
143
- AND term.slug IN ( '" . implode( "','", apply_filters( 'woocommerce_reports_order_statuses', array( 'completed', 'processing', 'on-hold' ) ) ) . "' ) " . // phpcs:ignore -- safe query.
144
- " AND postmeta.meta_key = '_order_total'
145
- AND posts.post_date >= %s
146
- AND posts.post_date <= %s",
147
- date( 'Y-m-01' ), // phpcs:ignore -- local time.
148
- date( 'Y-m-d H:i:s' ) // phpcs:ignore -- local time.
149
- )
150
- );
151
-
152
- // Get top seller.
153
- $top_seller = $wpdb->get_row(
154
- $wpdb->prepare( // phpcs:ignore -- safe query.
155
- "SELECT SUM( order_item_meta.meta_value ) as qty, order_item_meta_2.meta_value as product_id
156
- FROM {$wpdb->posts} as posts
157
- LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID=rel.object_ID
158
- LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id )
159
- LEFT JOIN {$wpdb->terms} AS term USING( term_id )
160
- LEFT JOIN {$wpdb->prefix}woocommerce_order_items AS order_items ON posts.ID = order_id
161
- LEFT JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS order_item_meta ON order_items.order_item_id = order_item_meta.order_item_id
162
- LEFT JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS order_item_meta_2 ON order_items.order_item_id = order_item_meta_2.order_item_id
163
- WHERE posts.post_type = 'shop_order'
164
- AND posts.post_status = 'publish'
165
- AND tax.taxonomy = 'shop_order_status'
166
- AND term.slug IN ( '" . implode( "','", apply_filters( 'woocommerce_reports_order_statuses', array( 'completed', 'processing', 'on-hold' ) ) ) . "' ) " . // phpcs:ignore -- safe query.
167
- " AND order_item_meta.meta_key = '_qty'
168
- AND order_item_meta_2.meta_key = '_product_id'
169
- AND posts.post_date >= %s
170
- AND posts.post_date <= %s
171
- GROUP BY product_id
172
- ORDER BY qty DESC
173
- LIMIT 1",
174
- date( 'Y-m-01' ), // phpcs:ignore -- local time.
175
- date( 'Y-m-d H:i:s' ) // phpcs:ignore -- local time.
176
- )
177
- );
178
-
179
- if ( ! empty( $top_seller ) ) {
180
- $top_seller->name = get_the_title( $top_seller->product_id );
181
- }
182
-
183
- // Counts.
184
- $on_hold_count = get_term_by( 'slug', 'on-hold', 'shop_order_status' )->count;
185
- $processing_count = get_term_by( 'slug', 'processing', 'shop_order_status' )->count;
186
-
187
- // Get products using a query.
188
- $stock = absint( max( get_option( 'woocommerce_notify_low_stock_amount' ), 1 ) );
189
- $nostock = absint( max( get_option( 'woocommerce_notify_no_stock_amount' ), 0 ) );
190
-
191
- $query_from = "FROM {$wpdb->posts} as posts INNER JOIN {$wpdb->postmeta} AS postmeta ON posts.ID = postmeta.post_id INNER JOIN {$wpdb->postmeta} AS postmeta2 ON posts.ID = postmeta2.post_id WHERE 1=1 AND posts.post_type IN ('product', 'product_variation') AND posts.post_status = 'publish' AND ( postmeta.meta_key = '_stock' AND CAST(postmeta.meta_value AS SIGNED) <= '{$stock}' AND CAST(postmeta.meta_value AS SIGNED) > '{$nostock}' AND postmeta.meta_value != '' ) AND ( ( postmeta2.meta_key = '_manage_stock' AND postmeta2.meta_value = 'yes' ) OR ( posts.post_type = 'product_variation' ) )";
192
-
193
- $lowinstock_count = absint( $wpdb->get_var( "SELECT COUNT( DISTINCT posts.ID ) {$query_from};" ) ); //phpcs:ignore -- safe query.
194
-
195
- $query_from = "FROM {$wpdb->posts} as posts INNER JOIN {$wpdb->postmeta} AS postmeta ON posts.ID = postmeta.post_id INNER JOIN {$wpdb->postmeta} AS postmeta2 ON posts.ID = postmeta2.post_id WHERE 1=1 AND posts.post_type IN ('product', 'product_variation') AND posts.post_status = 'publish' AND ( postmeta.meta_key = '_stock' AND CAST(postmeta.meta_value AS SIGNED) <= '{$nostock}' AND postmeta.meta_value != '' ) AND ( ( postmeta2.meta_key = '_manage_stock' AND postmeta2.meta_value = 'yes' ) OR ( posts.post_type = 'product_variation' ) )";
196
-
197
- $outofstock_count = absint( $wpdb->get_var( "SELECT COUNT( DISTINCT posts.ID ) {$query_from};" ) ); //phpcs:ignore -- safe query.
198
-
199
- $data = array(
200
- 'sales' => $sales,
201
- 'formated_sales' => wc_price( $sales ),
202
- 'top_seller' => $top_seller,
203
- 'onhold' => $on_hold_count,
204
- 'awaiting' => $processing_count,
205
- 'stock' => $stock,
206
- 'nostock' => $nostock,
207
- 'lowstock' => $lowinstock_count,
208
- 'outstock' => $outofstock_count,
209
- );
210
-
211
- $data = apply_filters( 'mainwp_child_woocom_sync_data', $data );
212
-
213
- $information['data'] = $data;
214
-
215
- return $information;
216
- }
217
-
218
- /**
219
- * Woocommerce report data.
220
- *
221
- * @return array $information Woocommerce data grabed.
222
- */
223
- public function report_data() {
224
-
225
- /**
226
- * Object, providing access to the WordPress database.
227
- *
228
- * @global object $wpdb WordPress Database instance.
229
- */
230
- global $wpdb;
231
-
232
- $file = WP_PLUGIN_DIR . '/woocommerce/includes/admin/reports/class-wc-admin-report.php';
233
- if ( file_exists( $file ) ) {
234
- include_once $file;
235
- } else {
236
- return false;
237
- }
238
-
239
- $start_date = isset( $_POST['start_date'] ) ? sanitize_text_field( wp_unslash( $_POST['start_date'] ) ) : '';
240
- $end_date = isset( $_POST['end_date'] ) ? sanitize_text_field( wp_unslash( $_POST['end_date'] ) ) : '';
241
-
242
- $start_date = date( 'Y-m-d H:i:s', $start_date ); // phpcs:ignore -- local time.
243
- $end_date = date( 'Y-m-d H:i:s', $end_date ); // phpcs:ignore -- local time.
244
-
245
- // Get sales.
246
- $sales = $wpdb->get_var(
247
- "SELECT SUM( postmeta.meta_value ) FROM {$wpdb->posts} as posts
248
- LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID=rel.object_ID
249
- LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id )
250
- LEFT JOIN {$wpdb->terms} AS term USING( term_id )
251
- LEFT JOIN {$wpdb->postmeta} AS postmeta ON posts.ID = postmeta.post_id
252
- WHERE posts.post_type = 'shop_order'
253
- AND posts.post_status = 'publish'
254
- AND tax.taxonomy = 'shop_order_status'
255
- AND term.slug IN ( '" . implode( "','", apply_filters( 'woocommerce_reports_order_statuses', array( 'completed', 'processing', 'on-hold' ) ) ) . "' ) " . // phpcs:ignore -- safe query.
256
- " AND postmeta.meta_key = '_order_total'
257
- AND posts.post_date >= STR_TO_DATE(" . $wpdb->prepare( '%s', $start_date ) . ", '%Y-%m-%d %H:%i:%s')
258
- AND posts.post_date <= STR_TO_DATE(" . $wpdb->prepare( '%s', $end_date ) . ", '%Y-%m-%d %H:%i:%s')"
259
- );
260
-
261
- // Get top seller.
262
- $top_seller = $wpdb->get_row(
263
- "SELECT SUM( order_item_meta.meta_value ) as qty, order_item_meta_2.meta_value as product_id
264
- FROM {$wpdb->posts} as posts
265
- LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID=rel.object_ID
266
- LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id )
267
- LEFT JOIN {$wpdb->terms} AS term USING( term_id )
268
- LEFT JOIN {$wpdb->prefix}woocommerce_order_items AS order_items ON posts.ID = order_id
269
- LEFT JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS order_item_meta ON order_items.order_item_id = order_item_meta.order_item_id
270
- LEFT JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS order_item_meta_2 ON order_items.order_item_id = order_item_meta_2.order_item_id
271
- WHERE posts.post_type = 'shop_order'
272
- AND posts.post_status = 'publish'
273
- AND tax.taxonomy = 'shop_order_status'
274
- AND term.slug IN ( '" . implode( "','", apply_filters( 'woocommerce_reports_order_statuses', array( 'completed', 'processing', 'on-hold' ) ) ) . "' ) " . // phpcs:ignore -- safe query.
275
- " AND order_item_meta.meta_key = '_qty'
276
- AND order_item_meta_2.meta_key = '_product_id'
277
- AND posts.post_date >= STR_TO_DATE(" . $wpdb->prepare( '%s', $start_date ) . ", '%Y-%m-%d %H:%i:%s' )
278
- AND posts.post_date <= STR_TO_DATE(" . $wpdb->prepare( '%s', $end_date ) . ", '%Y-%m-%d %H:%i:%s' )
279
- GROUP BY product_id
280
- ORDER BY qty DESC
281
- LIMIT 1"
282
- );
283
-
284
- if ( ! empty( $top_seller ) ) {
285
- $top_seller->name = get_the_title( $top_seller->product_id );
286
- }
287
-
288
- // Counts.
289
- $on_hold_count = get_term_by( 'slug', 'on-hold', 'shop_order_status' )->count;
290
- $processing_count = get_term_by( 'slug', 'processing', 'shop_order_status' )->count;
291
-
292
- // Get products using a query.
293
- $stock = absint( max( get_option( 'woocommerce_notify_low_stock_amount' ), 1 ) );
294
- $nostock = absint( max( get_option( 'woocommerce_notify_no_stock_amount' ), 0 ) );
295
-
296
- $query_from = "FROM {$wpdb->posts} as posts INNER JOIN {$wpdb->postmeta} AS postmeta ON posts.ID = postmeta.post_id INNER JOIN {$wpdb->postmeta} AS postmeta2 ON posts.ID = postmeta2.post_id WHERE 1=1 AND posts.post_type IN ('product', 'product_variation') AND posts.post_status = 'publish' AND ( postmeta.meta_key = '_stock' AND CAST(postmeta.meta_value AS SIGNED) <= '{$stock}' AND CAST(postmeta.meta_value AS SIGNED) > '{$nostock}' AND postmeta.meta_value != '' ) AND ( ( postmeta2.meta_key = '_manage_stock' AND postmeta2.meta_value = 'yes' ) OR ( posts.post_type = 'product_variation' ) )";
297
-
298
- $lowinstock_count = absint( $wpdb->get_var( "SELECT COUNT( DISTINCT posts.ID ) {$query_from};" ) ); //phpcs:ignore -- safe query.
299
-
300
- $query_from = "FROM {$wpdb->posts} as posts INNER JOIN {$wpdb->postmeta} AS postmeta ON posts.ID = postmeta.post_id INNER JOIN {$wpdb->postmeta} AS postmeta2 ON posts.ID = postmeta2.post_id WHERE 1=1 AND posts.post_type IN ('product', 'product_variation') AND posts.post_status = 'publish' AND ( postmeta.meta_key = '_stock' AND CAST(postmeta.meta_value AS SIGNED) <= '{$nostock}' AND postmeta.meta_value != '' ) AND ( ( postmeta2.meta_key = '_manage_stock' AND postmeta2.meta_value = 'yes' ) OR ( posts.post_type = 'product_variation' ) )";
301
-
302
- $outofstock_count = absint( $wpdb->get_var( "SELECT COUNT( DISTINCT posts.ID ) {$query_from};" ) ); //phpcs:ignore -- safe query.
303
-
304
- $data = array(
305
- 'sales' => $sales,
306
- 'formated_sales' => wc_price( $sales ),
307
- 'top_seller' => $top_seller,
308
- 'onhold' => $on_hold_count,
309
- 'awaiting' => $processing_count,
310
- 'stock' => $stock,
311
- 'nostock' => $nostock,
312
- 'lowstock' => $lowinstock_count,
313
- 'outstock' => $outofstock_count,
314
- );
315
-
316
- $data = apply_filters( 'mainwp_child_woocom_report_data', $data );
317
-
318
- $information['data'] = $data;
319
-
320
- return $information;
321
- }
322
-
323
- /**
324
- * Sync Woocommerce data for current month.
325
- */
326
- public function sync_data_two() {
327
- $start_date = date( 'Y-m-01 00:00:00', time() ); // phpcs:ignore -- local time.
328
- $end_date = date( 'Y-m-d H:i:s', time() ); // phpcs:ignore -- local time.
329
-
330
- $start_date = strtotime( $start_date );
331
- $end_date = strtotime( $end_date );
332
-
333
- return $this->get_woocom_data( $start_date, $end_date );
334
- }
335
-
336
- /**
337
- * Sync Woocomerce data for specific date range.
338
- */
339
- public function report_data_two() {
340
- $start_date = isset( $_POST['start_date'] ) ? sanitize_text_field( wp_unslash( $_POST['start_date'] ) ) : '';
341
- $end_date = isset( $_POST['end_date'] ) ? sanitize_text_field( wp_unslash( $_POST['end_date'] ) ) : '';
342
-
343
- return $this->get_woocom_data( $start_date, $end_date );
344
- }
345
-
346
- /**
347
- * Check if woocomerce DB needs to be updated.
348
- *
349
- * @return bool true|false.
350
- */
351
- public function check_db_update() {
352
- if ( version_compare( get_option( 'woocommerce_db_version' ), WC_VERSION, '<' ) ) {
353
- return true;
354
- }
355
- return false;
356
- }
357
-
358
- /**
359
- * Get Woocommerce data.
360
- *
361
- * @param string $start_date Start Date.
362
- * @param string $end_date End Date.
363
- *
364
- * @return array $information Woocommerce data grabed.
365
- */
366
- public function get_woocom_data( $start_date, $end_date ) {
367
-
368
- /**
369
- * Object, providing access to the WordPress database.
370
- *
371
- * @global object $wpdb WordPress Database instance.
372
- */
373
- global $wpdb;
374
-
375
- $file = WP_PLUGIN_DIR . '/woocommerce/includes/admin/reports/class-wc-admin-report.php';
376
- if ( file_exists( $file ) ) {
377
- include_once $file;
378
- } else {
379
- return false;
380
- }
381
-
382
- $start_date = date( 'Y-m-d H:i:s', $start_date ); // phpcs:ignore -- local time. Required to achieve desired results, pull request solutions appreciated.
383
- $end_date = date( 'Y-m-d H:i:s', $end_date ); // phpcs:ignore -- local time. Required to achieve desired results, pull request solutions appreciated.
384
-
385
- // Sales.
386
- $query = array();
387
- $query['fields'] = "SELECT SUM( postmeta.meta_value ) FROM {$wpdb->posts} as posts";
388
- $query['join'] = "INNER JOIN {$wpdb->postmeta} AS postmeta ON posts.ID = postmeta.post_id ";
389
- $query['where'] = "WHERE posts.post_type IN ( '" . implode( "','", wc_get_order_types( 'reports' ) ) . "' ) ";
390
- $query['where'] .= "AND posts.post_status IN ( 'wc-" . implode( "','wc-", apply_filters( 'woocommerce_reports_order_statuses', array( 'completed', 'processing', 'on-hold' ) ) ) . "' ) ";
391
- $query['where'] .= "AND postmeta.meta_key = '_order_total' ";
392
- $query['where'] .= 'AND posts.post_date >= STR_TO_DATE(' . $wpdb->prepare( '%s', $start_date ) . ", '%Y-%m-%d %H:%i:%s' ) ";
393
- $query['where'] .= 'AND posts.post_date <= STR_TO_DATE(' . $wpdb->prepare( '%s', $end_date ) . ", '%Y-%m-%d %H:%i:%s' ) ";
394
-
395
- $sales = $wpdb->get_var( implode( ' ', apply_filters( 'woocommerce_dashboard_status_widget_sales_query', $query ) ) ); // phpcs:ignore -- safe query.
396
-
397
- // Get top seller.
398
- $query = array();
399
- $query['fields'] = "SELECT SUM( order_item_meta.meta_value ) as qty, order_item_meta_2.meta_value as product_id FROM {$wpdb->posts} as posts";
400
- $query['join'] = "INNER JOIN {$wpdb->prefix}woocommerce_order_items AS order_items ON posts.ID = order_id ";
401
- $query['join'] .= "INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS order_item_meta ON order_items.order_item_id = order_item_meta.order_item_id ";
402
- $query['join'] .= "INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS order_item_meta_2 ON order_items.order_item_id = order_item_meta_2.order_item_id ";
403
- $query['where'] = "WHERE posts.post_type IN ( '" . implode( "','", wc_get_order_types( 'order-count' ) ) . "' ) ";
404
- $query['where'] .= "AND posts.post_status IN ( 'wc-" . implode( "','wc-", apply_filters( 'woocommerce_reports_order_statuses', array( 'completed', 'processing', 'on-hold' ) ) ) . "' ) ";
405
- $query['where'] .= "AND order_item_meta.meta_key = '_qty' ";
406
- $query['where'] .= "AND order_item_meta_2.meta_key = '_product_id' ";
407
- $query['where'] .= 'AND posts.post_date >= STR_TO_DATE(' . $wpdb->prepare( '%s', $start_date ) . ", '%Y-%m-%d %H:%i:%s') ";
408
- $query['where'] .= 'AND posts.post_date <= STR_TO_DATE(' . $wpdb->prepare( '%s', $end_date ) . ", '%Y-%m-%d %H:%i:%s') ";
409
- $query['groupby'] = 'GROUP BY product_id';
410
- $query['orderby'] = 'ORDER BY qty DESC';
411
- $query['limits'] = 'LIMIT 1';
412
-
413
- $top_seller = $wpdb->get_row( implode( ' ', $query ) ); // phpcs:ignore -- safe query.
414
-
415
- if ( ! empty( $top_seller ) ) {
416
- $top_seller->name = get_the_title( $top_seller->product_id );
417
- }
418
-
419
- // Counts.
420
- $on_hold_count = 0;
421
- $processing_count = 0;
422
-
423
- foreach ( wc_get_order_types( 'order-count' ) as $type ) {
424
- $counts = (array) wp_count_posts( $type );
425
- $on_hold_count += isset( $counts['wc-on-hold'] ) ? $counts['wc-on-hold'] : 0;
426
- $processing_count += isset( $counts['wc-processing'] ) ? $counts['wc-processing'] : 0;
427
- }
428
-
429
- // Get products using a query.
430
- $stock = absint( max( get_option( 'woocommerce_notify_low_stock_amount' ), 1 ) );
431
- $nostock = absint( max( get_option( 'woocommerce_notify_no_stock_amount' ), 0 ) );
432
-
433
- $query_from = "FROM {$wpdb->posts} as posts INNER JOIN {$wpdb->postmeta} AS postmeta ON posts.ID = postmeta.post_id INNER JOIN {$wpdb->postmeta} AS postmeta2 ON posts.ID = postmeta2.post_id WHERE 1=1 AND posts.post_type IN ('product', 'product_variation') AND posts.post_status = 'publish' AND ( postmeta.meta_key = '_stock' AND CAST(postmeta.meta_value AS SIGNED) <= '{$stock}' AND CAST(postmeta.meta_value AS SIGNED) > '{$nostock}' AND postmeta.meta_value != '' ) AND ( ( postmeta2.meta_key = '_manage_stock' AND postmeta2.meta_value = 'yes' ) OR ( posts.post_type = 'product_variation' ) )";
434
-
435
- $lowinstock_count = absint( $wpdb->get_var( "SELECT COUNT( DISTINCT posts.ID ) {$query_from};" ) ); //phpcs:ignore -- safe query.
436
-
437
- $query_from = "FROM {$wpdb->posts} as posts INNER JOIN {$wpdb->postmeta} AS postmeta ON posts.ID = postmeta.post_id INNER JOIN {$wpdb->postmeta} AS postmeta2 ON posts.ID = postmeta2.post_id WHERE 1=1 AND posts.post_type IN ('product', 'product_variation') AND posts.post_status = 'publish' AND ( postmeta.meta_key = '_stock' AND CAST(postmeta.meta_value AS SIGNED) <= '{$nostock}' AND postmeta.meta_value != '' ) AND ( ( postmeta2.meta_key = '_manage_stock' AND postmeta2.meta_value = 'yes' ) OR ( posts.post_type = 'product_variation' ) ) ";
438
-
439
- $outofstock_count = absint( $wpdb->get_var( "SELECT COUNT( DISTINCT posts.ID ) {$query_from};" ) ); //phpcs:ignore -- safe query.
440
-
441
- $data = array(
442
- 'sales' => $sales,
443
- 'formated_sales' => wc_price( $sales ),
444
- 'top_seller' => $top_seller,
445
- 'onhold' => $on_hold_count,
446
- 'awaiting' => $processing_count,
447
- 'stock' => $stock,
448
- 'nostock' => $nostock,
449
- 'lowstock' => $lowinstock_count,
450
- 'outstock' => $outofstock_count,
451
- );
452
-
453
- $data = apply_filters( 'mainwp_child_woocom_get_data', $data );
454
-
455
- $information['data'] = $data;
456
- $information['need_db_update'] = $this->check_db_update();
457
- return $information;
458
- }
459
-
460
- /**
461
- * Update Woocommerce Database.
462
- *
463
- * @return string[] Success.
464
- */
465
- private static function update_wc_db() {
466
- include_once WC()->plugin_path() . '/includes/class-wc-background-updater.php';
467
- $background_updater = new \WC_Background_Updater();
468
-
469
- $current_db_version = get_option( 'woocommerce_db_version' );
470
- $logger = wc_get_logger();
471
- $update_queued = false;
472
-
473
- foreach ( \WC_Install::get_db_update_callbacks() as $version => $update_callbacks ) {
474
- if ( version_compare( $current_db_version, $version, '<' ) ) {
475
- foreach ( $update_callbacks as $update_callback ) {
476
- $logger->info(
477
- sprintf( 'Queuing %s - %s', $version, $update_callback ),
478
- array( 'source' => 'wc_db_updates' )
479
- );
480
- $background_updater->push_to_queue( $update_callback );
481
- $update_queued = true;
482
- }
483
- }
484
- }
485
-
486
- if ( $update_queued ) {
487
- $background_updater->save()->dispatch();
488
- }
489
-
490
- return array( 'result' => 'success' );
491
- }
492
-
493
- }
1
+ <?php
2
+ /**
3
+ * MainWP Child Woocomerce Status
4
+ *
5
+ * MainWP WooCommerce Status Extension handler.
6
+ *
7
+ * @link https://mainwp.com/extension/woocommerce-status/
8
+ *
9
+ * @package MainWP\Child
10
+ *
11
+ * Credits
12
+ *
13
+ * Plugin-Name: WooCommerce
14
+ * Plugin URI: https://woocommerce.com/
15
+ * Author: Automattic
16
+ * Author URI: https://woocommerce.com
17
+ */
18
+
19
+ namespace MainWP\Child;
20
+
21
+ // phpcs:disable PSR1.Classes.ClassDeclaration, WordPress.WP.AlternativeFunctions -- Required to achieve desired results, pull request solutions appreciated.
22
+
23
+ /**
24
+ * Class MainWP_Child_WooCommerce_Status
25
+ *
26
+ * MainWP WooCommerce Status Extension handler.
27
+ */
28
+ class MainWP_Child_WooCommerce_Status {
29
+
30
+ /**
31
+ * Public static variable to hold the single instance of the class.
32
+ *
33
+ * @var mixed Default null
34
+ */
35
+ public static $instance = null;
36
+
37
+ /**
38
+ * Method instance()
39
+ *
40
+ * Create a public static instance.
41
+ *
42
+ * @return mixed Class instance.
43
+ */
44
+ public static function instance() {
45
+ if ( null === self::$instance ) {
46
+ self::$instance = new self();
47
+ }
48
+
49
+ return self::$instance;
50
+ }
51
+
52
+ /**
53
+ * MainWP_Child_WooCommerce_Status constructor.
54
+ *
55
+ * Run any time class is called.
56
+ */
57
+ public function __construct() {
58
+ add_action( 'mainwp_child_deactivation', array( $this, 'child_deactivation' ) );
59
+ }
60
+
61
+ /**
62
+ * MainWP Child Plugin deactivation hooks.
63
+ */
64
+ public function child_deactivation() {
65
+ }
66
+
67
+ /**
68
+ * MainWP Child Woocommerce actions: sync_data, report_data, update_wc_db.
69
+ *
70
+ * @uses \MainWP\Child\MainWP_Helper::write()
71
+ */
72
+ public function action() {
73
+ $information = array();
74
+ if ( ! class_exists( '\WooCommerce' ) || ! defined( 'WC_VERSION' ) ) {
75
+ $information['error'] = 'NO_WOOCOMMERCE';
76
+ MainWP_Helper::write( $information );
77
+ }
78
+
79
+ $is_ver220 = $this->is_version_220();
80
+ if ( isset( $_POST['mwp_action'] ) ) {
81
+ $mwp_action = ! empty( $_POST['mwp_action'] ) ? sanitize_text_field( wp_unslash( $_POST['mwp_action'] ) ) : '';
82
+ switch ( $mwp_action ) {
83
+ case 'sync_data':
84
+ $information = ! $is_ver220 ? $this->sync_data() : $this->sync_data_two();
85
+ break;
86
+ case 'report_data':
87
+ $information = ! $is_ver220 ? $this->report_data() : $this->report_data_two();
88
+ break;
89
+ case 'update_wc_db':
90
+ $information = $this->update_wc_db();
91
+ break;
92
+ }
93
+ }
94
+ MainWP_Helper::write( $information );
95
+ }
96
+
97
+ /**
98
+ * Compare woocommerce versions.
99
+ *
100
+ * By default, version_compare returns -1 if the first version is lower than the second,
101
+ * 0 if they are equal, and 1 if the second is lower.
102
+ * When using the optional operator argument, the function will return true if the relationship is
103
+ * the one specified by the operator, false otherwise.
104
+ *
105
+ * @return bool|int Comparison response.
106
+ */
107
+ public function is_version_220() {
108
+ return version_compare( WC()->version, '2.2.0', '>=' );
109
+ }
110
+
111
+ /**
112
+ * Sync Woocommerce data.
113
+ *
114
+ * @return array $information Woocommerce data grabed.
115
+ */
116
+ public function sync_data() {
117
+
118
+ /**
119
+ * Object, providing access to the WordPress database.
120
+ *
121
+ * @global object $wpdb WordPress Database instance.
122
+ */
123
+ global $wpdb;
124
+
125
+ $file = WP_PLUGIN_DIR . '/woocommerce/includes/admin/reports/class-wc-admin-report.php';
126
+ if ( file_exists( $file ) ) {
127
+ include_once $file;
128
+ } else {
129
+ return false;
130
+ }
131
+
132
+ // Get sales.
133
+ $sales = $wpdb->get_var(
134
+ $wpdb->prepare(
135
+ "SELECT SUM( postmeta.meta_value ) FROM {$wpdb->posts} as posts
136
+ LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID=rel.object_ID
137
+ LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id )
138
+ LEFT JOIN {$wpdb->terms} AS term USING( term_id )
139
+ LEFT JOIN {$wpdb->postmeta} AS postmeta ON posts.ID = postmeta.post_id
140
+ WHERE posts.post_type = 'shop_order'
141
+ AND posts.post_status = 'publish'
142
+ AND tax.taxonomy = 'shop_order_status'
143
+ AND term.slug IN ( '" . implode( "','", apply_filters( 'woocommerce_reports_order_statuses', array( 'completed', 'processing', 'on-hold' ) ) ) . "' ) " . // phpcs:ignore -- safe query.
144
+ " AND postmeta.meta_key = '_order_total'
145
+ AND posts.post_date >= %s
146
+ AND posts.post_date <= %s",
147
+ date( 'Y-m-01' ), // phpcs:ignore -- local time.
148
+ date( 'Y-m-d H:i:s' ) // phpcs:ignore -- local time.
149
+ )
150
+ );
151
+
152
+ // Get top seller.
153
+ $top_seller = $wpdb->get_row(
154
+ $wpdb->prepare( // phpcs:ignore -- safe query.
155
+ "SELECT SUM( order_item_meta.meta_value ) as qty, order_item_meta_2.meta_value as product_id
156
+ FROM {$wpdb->posts} as posts
157
+ LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID=rel.object_ID
158
+ LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id )
159
+ LEFT JOIN {$wpdb->terms} AS term USING( term_id )
160
+ LEFT JOIN {$wpdb->prefix}woocommerce_order_items AS order_items ON posts.ID = order_id
161
+ LEFT JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS order_item_meta ON order_items.order_item_id = order_item_meta.order_item_id
162
+ LEFT JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS order_item_meta_2 ON order_items.order_item_id = order_item_meta_2.order_item_id
163
+ WHERE posts.post_type = 'shop_order'
164
+ AND posts.post_status = 'publish'
165
+ AND tax.taxonomy = 'shop_order_status'
166
+ AND term.slug IN ( '" . implode( "','", apply_filters( 'woocommerce_reports_order_statuses', array( 'completed', 'processing', 'on-hold' ) ) ) . "' ) " . // phpcs:ignore -- safe query.
167
+ " AND order_item_meta.meta_key = '_qty'
168
+ AND order_item_meta_2.meta_key = '_product_id'
169
+ AND posts.post_date >= %s
170
+ AND posts.post_date <= %s
171
+ GROUP BY product_id
172
+ ORDER BY qty DESC
173
+ LIMIT 1",
174
+ date( 'Y-m-01' ), // phpcs:ignore -- local time.
175
+ date( 'Y-m-d H:i:s' ) // phpcs:ignore -- local time.
176
+ )
177
+ );
178
+
179
+ if ( ! empty( $top_seller ) ) {
180
+ $top_seller->name = get_the_title( $top_seller->product_id );
181
+ }
182
+
183
+ // Counts.
184
+ $on_hold_count = get_term_by( 'slug', 'on-hold', 'shop_order_status' )->count;
185
+ $processing_count = get_term_by( 'slug', 'processing', 'shop_order_status' )->count;
186
+
187
+ // Get products using a query.
188
+ $stock = absint( max( get_option( 'woocommerce_notify_low_stock_amount' ), 1 ) );
189
+ $nostock = absint( max( get_option( 'woocommerce_notify_no_stock_amount' ), 0 ) );
190
+
191
+ $query_from = "FROM {$wpdb->posts} as posts INNER JOIN {$wpdb->postmeta} AS postmeta ON posts.ID = postmeta.post_id INNER JOIN {$wpdb->postmeta} AS postmeta2 ON posts.ID = postmeta2.post_id WHERE 1=1 AND posts.post_type IN ('product', 'product_variation') AND posts.post_status = 'publish' AND ( postmeta.meta_key = '_stock' AND CAST(postmeta.meta_value AS SIGNED) <= '{$stock}' AND CAST(postmeta.meta_value AS SIGNED) > '{$nostock}' AND postmeta.meta_value != '' ) AND ( ( postmeta2.meta_key = '_manage_stock' AND postmeta2.meta_value = 'yes' ) OR ( posts.post_type = 'product_variation' ) )";
192
+
193
+ $lowinstock_count = absint( $wpdb->get_var( "SELECT COUNT( DISTINCT posts.ID ) {$query_from};" ) ); //phpcs:ignore -- safe query.
194
+
195
+ $query_from = "FROM {$wpdb->posts} as posts INNER JOIN {$wpdb->postmeta} AS postmeta ON posts.ID = postmeta.post_id INNER JOIN {$wpdb->postmeta} AS postmeta2 ON posts.ID = postmeta2.post_id WHERE 1=1 AND posts.post_type IN ('product', 'product_variation') AND posts.post_status = 'publish' AND ( postmeta.meta_key = '_stock' AND CAST(postmeta.meta_value AS SIGNED) <= '{$nostock}' AND postmeta.meta_value != '' ) AND ( ( postmeta2.meta_key = '_manage_stock' AND postmeta2.meta_value = 'yes' ) OR ( posts.post_type = 'product_variation' ) )";
196
+
197
+ $outofstock_count = absint( $wpdb->get_var( "SELECT COUNT( DISTINCT posts.ID ) {$query_from};" ) ); //phpcs:ignore -- safe query.
198
+
199
+ $data = array(
200
+ 'sales' => $sales,
201
+ 'formated_sales' => wc_price( $sales ),
202
+ 'top_seller' => $top_seller,
203
+ 'onhold' => $on_hold_count,
204
+ 'awaiting' => $processing_count,
205
+ 'stock' => $stock,
206
+ 'nostock' => $nostock,
207
+ 'lowstock' => $lowinstock_count,
208
+ 'outstock' => $outofstock_count,
209
+ );
210
+
211
+ $data = apply_filters( 'mainwp_child_woocom_sync_data', $data );
212
+
213
+ $information['data'] = $data;
214
+
215
+ return $information;
216
+ }
217
+
218
+ /**
219
+ * Woocommerce report data.
220
+ *
221
+ * @return array $information Woocommerce data grabed.
222
+ */
223
+ public function report_data() {
224
+
225
+ /**
226
+ * Object, providing access to the WordPress database.
227
+ *
228
+ * @global object $wpdb WordPress Database instance.
229
+ */
230
+ global $wpdb;
231
+
232
+ $file = WP_PLUGIN_DIR . '/woocommerce/includes/admin/reports/class-wc-admin-report.php';
233
+ if ( file_exists( $file ) ) {
234
+ include_once $file;
235
+ } else {
236
+ return false;
237
+ }
238
+
239
+ $start_date = isset( $_POST['start_date'] ) ? sanitize_text_field( wp_unslash( $_POST['start_date'] ) ) : '';
240
+ $end_date = isset( $_POST['end_date'] ) ? sanitize_text_field( wp_unslash( $_POST['end_date'] ) ) : '';
241
+
242
+ $start_date = date( 'Y-m-d H:i:s', $start_date ); // phpcs:ignore -- local time.
243
+ $end_date = date( 'Y-m-d H:i:s', $end_date ); // phpcs:ignore -- local time.
244
+
245
+ // Get sales.
246
+ $sales = $wpdb->get_var(
247
+ "SELECT SUM( postmeta.meta_value ) FROM {$wpdb->posts} as posts
248
+ LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID=rel.object_ID
249
+ LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id )
250
+ LEFT JOIN {$wpdb->terms} AS term USING( term_id )
251
+ LEFT JOIN {$wpdb->postmeta} AS postmeta ON posts.ID = postmeta.post_id
252
+ WHERE posts.post_type = 'shop_order'
253
+ AND posts.post_status = 'publish'
254
+ AND tax.taxonomy = 'shop_order_status'
255
+ AND term.slug IN ( '" . implode( "','", apply_filters( 'woocommerce_reports_order_statuses', array( 'completed', 'processing', 'on-hold' ) ) ) . "' ) " . // phpcs:ignore -- safe query.
256
+ " AND postmeta.meta_key = '_order_total'
257
+ AND posts.post_date >= STR_TO_DATE(" . $wpdb->prepare( '%s', $start_date ) . ", '%Y-%m-%d %H:%i:%s')
258
+ AND posts.post_date <= STR_TO_DATE(" . $wpdb->prepare( '%s', $end_date ) . ", '%Y-%m-%d %H:%i:%s')"
259
+ );
260
+
261
+ // Get top seller.
262
+ $top_seller = $wpdb->get_row(
263
+ "SELECT SUM( order_item_meta.meta_value ) as qty, order_item_meta_2.meta_value as product_id
264
+ FROM {$wpdb->posts} as posts
265
+ LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID=rel.object_ID
266
+ LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id )
267
+ LEFT JOIN {$wpdb->terms} AS term USING( term_id )
268
+ LEFT JOIN {$wpdb->prefix}woocommerce_order_items AS order_items ON posts.ID = order_id
269
+ LEFT JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS order_item_meta ON order_items.order_item_id = order_item_meta.order_item_id
270
+ LEFT JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS order_item_meta_2 ON order_items.order_item_id = order_item_meta_2.order_item_id
271
+ WHERE posts.post_type = 'shop_order'
272
+ AND posts.post_status = 'publish'
273
+ AND tax.taxonomy = 'shop_order_status'
274
+ AND term.slug IN ( '" . implode( "','", apply_filters( 'woocommerce_reports_order_statuses', array( 'completed', 'processing', 'on-hold' ) ) ) . "' ) " . // phpcs:ignore -- safe query.
275
+ " AND order_item_meta.meta_key = '_qty'
276
+ AND order_item_meta_2.meta_key = '_product_id'
277
+ AND posts.post_date >= STR_TO_DATE(" . $wpdb->prepare( '%s', $start_date ) . ", '%Y-%m-%d %H:%i:%s' )
278
+ AND posts.post_date <= STR_TO_DATE(" . $wpdb->prepare( '%s', $end_date ) . ", '%Y-%m-%d %H:%i:%s' )
279
+ GROUP BY product_id
280
+ ORDER BY qty DESC
281
+ LIMIT 1"
282
+ );
283
+
284
+ if ( ! empty( $top_seller ) ) {
285
+ $top_seller->name = get_the_title( $top_seller->product_id );
286
+ }
287
+
288
+ // Counts.
289
+ $on_hold_count = get_term_by( 'slug', 'on-hold', 'shop_order_status' )->count;
290
+ $processing_count = get_term_by( 'slug', 'processing', 'shop_order_status' )->count;
291
+
292
+ // Get products using a query.
293
+ $stock = absint( max( get_option( 'woocommerce_notify_low_stock_amount' ), 1 ) );
294
+ $nostock = absint( max( get_option( 'woocommerce_notify_no_stock_amount' ), 0 ) );
295
+
296
+ $query_from = "FROM {$wpdb->posts} as posts INNER JOIN {$wpdb->postmeta} AS postmeta ON posts.ID = postmeta.post_id INNER JOIN {$wpdb->postmeta} AS postmeta2 ON posts.ID = postmeta2.post_id WHERE 1=1 AND posts.post_type IN ('product', 'product_variation') AND posts.post_status = 'publish' AND ( postmeta.meta_key = '_stock' AND CAST(postmeta.meta_value AS SIGNED) <= '{$stock}' AND CAST(postmeta.meta_value AS SIGNED) > '{$nostock}' AND postmeta.meta_value != '' ) AND ( ( postmeta2.meta_key = '_manage_stock' AND postmeta2.meta_value = 'yes' ) OR ( posts.post_type = 'product_variation' ) )";
297
+
298
+ $lowinstock_count = absint( $wpdb->get_var( "SELECT COUNT( DISTINCT posts.ID ) {$query_from};" ) ); //phpcs:ignore -- safe query.
299
+
300
+ $query_from = "FROM {$wpdb->posts} as posts INNER JOIN {$wpdb->postmeta} AS postmeta ON posts.ID = postmeta.post_id INNER JOIN {$wpdb->postmeta} AS postmeta2 ON posts.ID = postmeta2.post_id WHERE 1=1 AND posts.post_type IN ('product', 'product_variation') AND posts.post_status = 'publish' AND ( postmeta.meta_key = '_stock' AND CAST(postmeta.meta_value AS SIGNED) <= '{$nostock}' AND postmeta.meta_value != '' ) AND ( ( postmeta2.meta_key = '_manage_stock' AND postmeta2.meta_value = 'yes' ) OR ( posts.post_type = 'product_variation' ) )";
301
+
302
+ $outofstock_count = absint( $wpdb->get_var( "SELECT COUNT( DISTINCT posts.ID ) {$query_from};" ) ); //phpcs:ignore -- safe query.
303
+
304
+ $data = array(
305
+ 'sales' => $sales,
306
+ 'formated_sales' => wc_price( $sales ),
307
+ 'top_seller' => $top_seller,
308
+ 'onhold' => $on_hold_count,
309
+ 'awaiting' => $processing_count,
310
+ 'stock' => $stock,
311
+ 'nostock' => $nostock,
312
+ 'lowstock' => $lowinstock_count,
313
+ 'outstock' => $outofstock_count,
314
+ );
315
+
316
+ $data = apply_filters( 'mainwp_child_woocom_report_data', $data );
317
+
318
+ $information['data'] = $data;
319
+
320
+ return $information;
321
+ }
322
+
323
+ /**
324
+ * Sync Woocommerce data for current month.
325
+ */
326
+ public function sync_data_two() {
327
+ $start_date = date( 'Y-m-01 00:00:00', time() ); // phpcs:ignore -- local time.
328
+ $end_date = date( 'Y-m-d H:i:s', time() ); // phpcs:ignore -- local time.
329
+
330
+ $start_date = strtotime( $start_date );
331
+ $end_date = strtotime( $end_date );
332
+
333
+ return $this->get_woocom_data( $start_date, $end_date );
334
+ }
335
+
336
+ /**
337
+ * Sync Woocomerce data for specific date range.
338
+ */
339
+ public function report_data_two() {
340
+ $start_date = isset( $_POST['start_date'] ) ? sanitize_text_field( wp_unslash( $_POST['start_date'] ) ) : '';
341
+ $end_date = isset( $_POST['end_date'] ) ? sanitize_text_field( wp_unslash( $_POST['end_date'] ) ) : '';
342
+
343
+ return $this->get_woocom_data( $start_date, $end_date );
344
+ }
345
+
346
+ /**
347
+ * Check if woocomerce DB needs to be updated.
348
+ *
349
+ * @return bool true|false.
350
+ */
351
+ public function check_db_update() {
352
+ if ( version_compare( get_option( 'woocommerce_db_version' ), WC_VERSION, '<' ) ) {
353
+ return true;
354
+ }
355
+ return false;
356
+ }
357
+
358
+ /**
359
+ * Get Woocommerce data.
360
+ *
361
+ * @param string $start_date Start Date.
362
+ * @param string $end_date End Date.
363
+ *
364
+ * @return array $information Woocommerce data grabed.
365
+ */
366
+ public function get_woocom_data( $start_date, $end_date ) {
367
+
368
+ /**
369
+ * Object, providing access to the WordPress database.
370
+ *
371
+ * @global object $wpdb WordPress Database instance.
372
+ */
373
+ global $wpdb;
374
+
375
+ $file = WP_PLUGIN_DIR . '/woocommerce/includes/admin/reports/class-wc-admin-report.php';
376
+ if ( file_exists( $file ) ) {
377
+ include_once $file;
378
+ } else {
379
+ return false;
380
+ }
381
+
382
+ $start_date = date( 'Y-m-d H:i:s', $start_date ); // phpcs:ignore -- local time. Required to achieve desired results, pull request solutions appreciated.
383
+ $end_date = date( 'Y-m-d H:i:s', $end_date ); // phpcs:ignore -- local time. Required to achieve desired results, pull request solutions appreciated.
384
+
385
+ // Sales.
386
+ $query = array();
387
+ $query['fields'] = "SELECT SUM( postmeta.meta_value ) FROM {$wpdb->posts} as posts";
388
+ $query['join'] = "INNER JOIN {$wpdb->postmeta} AS postmeta ON posts.ID = postmeta.post_id ";
389
+ $query['where'] = "WHERE posts.post_type IN ( '" . implode( "','", wc_get_order_types( 'reports' ) ) . "' ) ";
390
+ $query['where'] .= "AND posts.post_status IN ( 'wc-" . implode( "','wc-", apply_filters( 'woocommerce_reports_order_statuses', array( 'completed', 'processing', 'on-hold' ) ) ) . "' ) ";
391
+ $query['where'] .= "AND postmeta.meta_key = '_order_total' ";
392
+ $query['where'] .= 'AND posts.post_date >= STR_TO_DATE(' . $wpdb->prepare( '%s', $start_date ) . ", '%Y-%m-%d %H:%i:%s' ) ";
393
+ $query['where'] .= 'AND posts.post_date <= STR_TO_DATE(' . $wpdb->prepare( '%s', $end_date ) . ", '%Y-%m-%d %H:%i:%s' ) ";
394
+
395
+ $sales = $wpdb->get_var( implode( ' ', apply_filters( 'woocommerce_dashboard_status_widget_sales_query', $query ) ) ); // phpcs:ignore -- safe query.
396
+
397
+ // Get top seller.
398
+ $query = array();
399
+ $query['fields'] = "SELECT SUM( order_item_meta.meta_value ) as qty, order_item_meta_2.meta_value as product_id FROM {$wpdb->posts} as posts";
400
+ $query['join'] = "INNER JOIN {$wpdb->prefix}woocommerce_order_items AS order_items ON posts.ID = order_id ";
401
+ $query['join'] .= "INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS order_item_meta ON order_items.order_item_id = order_item_meta.order_item_id ";
402
+ $query['join'] .= "INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS order_item_meta_2 ON order_items.order_item_id = order_item_meta_2.order_item_id ";
403
+ $query['where'] = "WHERE posts.post_type IN ( '" . implode( "','", wc_get_order_types( 'order-count' ) ) . "' ) ";
404
+ $query['where'] .= "AND posts.post_status IN ( 'wc-" . implode( "','wc-", apply_filters( 'woocommerce_reports_order_statuses', array( 'completed', 'processing', 'on-hold' ) ) ) . "' ) ";
405
+ $query['where'] .= "AND order_item_meta.meta_key = '_qty' ";
406
+ $query['where'] .= "AND order_item_meta_2.meta_key = '_product_id' ";
407
+ $query['where'] .= 'AND posts.post_date >= STR_TO_DATE(' . $wpdb->prepare( '%s', $start_date ) . ", '%Y-%m-%d %H:%i:%s') ";
408
+ $query['where'] .= 'AND posts.post_date <= STR_TO_DATE(' . $wpdb->prepare( '%s', $end_date ) . ", '%Y-%m-%d %H:%i:%s') ";
409
+ $query['groupby'] = 'GROUP BY product_id';
410
+ $query['orderby'] = 'ORDER BY qty DESC';
411
+ $query['limits'] = 'LIMIT 1';
412
+
413
+ $top_seller = $wpdb->get_row( implode( ' ', $query ) ); // phpcs:ignore -- safe query.
414
+
415
+ if ( ! empty( $top_seller ) ) {
416
+ $top_seller->name = get_the_title( $top_seller->product_id );
417
+ }
418
+
419
+ // Counts.
420
+ $on_hold_count = 0;
421
+ $processing_count = 0;
422
+
423
+ foreach ( wc_get_order_types( 'order-count' ) as $type ) {
424
+ $counts = (array) wp_count_posts( $type );
425
+ $on_hold_count += isset( $counts['wc-on-hold'] ) ? $counts['wc-on-hold'] : 0;
426
+ $processing_count += isset( $counts['wc-processing'] ) ? $counts['wc-processing'] : 0;
427
+ }
428
+
429
+ // Get products using a query.
430
+ $stock = absint( max( get_option( 'woocommerce_notify_low_stock_amount' ), 1 ) );
431
+ $nostock = absint( max( get_option( 'woocommerce_notify_no_stock_amount' ), 0 ) );
432
+
433
+ $query_from = "FROM {$wpdb->posts} as posts INNER JOIN {$wpdb->postmeta} AS postmeta ON posts.ID = postmeta.post_id INNER JOIN {$wpdb->postmeta} AS postmeta2 ON posts.ID = postmeta2.post_id WHERE 1=1 AND posts.post_type IN ('product', 'product_variation') AND posts.post_status = 'publish' AND ( postmeta.meta_key = '_stock' AND CAST(postmeta.meta_value AS SIGNED) <= '{$stock}' AND CAST(postmeta.meta_value AS SIGNED) > '{$nostock}' AND postmeta.meta_value != '' ) AND ( ( postmeta2.meta_key = '_manage_stock' AND postmeta2.meta_value = 'yes' ) OR ( posts.post_type = 'product_variation' ) )";
434
+
435
+ $lowinstock_count = absint( $wpdb->get_var( "SELECT COUNT( DISTINCT posts.ID ) {$query_from};" ) ); //phpcs:ignore -- safe query.
436
+
437
+ $query_from = "FROM {$wpdb->posts} as posts INNER JOIN {$wpdb->postmeta} AS postmeta ON posts.ID = postmeta.post_id INNER JOIN {$wpdb->postmeta} AS postmeta2 ON posts.ID = postmeta2.post_id WHERE 1=1 AND posts.post_type IN ('product', 'product_variation') AND posts.post_status = 'publish' AND ( postmeta.meta_key = '_stock' AND CAST(postmeta.meta_value AS SIGNED) <= '{$nostock}' AND postmeta.meta_value != '' ) AND ( ( postmeta2.meta_key = '_manage_stock' AND postmeta2.meta_value = 'yes' ) OR ( posts.post_type = 'product_variation' ) ) ";
438
+
439
+ $outofstock_count = absint( $wpdb->get_var( "SELECT COUNT( DISTINCT posts.ID ) {$query_from};" ) ); //phpcs:ignore -- safe query.
440
+
441
+ $data = array(
442
+ 'sales' => $sales,
443
+ 'formated_sales' => wc_price( $sales ),
444
+ 'top_seller' => $top_seller,
445
+ 'onhold' => $on_hold_count,
446
+ 'awaiting' => $processing_count,
447
+ 'stock' => $stock,
448
+ 'nostock' => $nostock,
449
+ 'lowstock' => $lowinstock_count,
450
+ 'outstock' => $outofstock_count,
451
+ );
452
+
453
+ $data = apply_filters( 'mainwp_child_woocom_get_data', $data );
454
+
455
+ $information['data'] = $data;
456
+ $information['need_db_update'] = $this->check_db_update();
457
+ return $information;
458
+ }
459
+
460
+ /**
461
+ * Update Woocommerce Database.
462
+ *
463
+ * @return string[] Success.
464
+ */
465
+ private static function update_wc_db() {
466
+ include_once WC()->plugin_path() . '/includes/class-wc-background-updater.php';
467
+ $background_updater = new \WC_Background_Updater();
468
+
469
+ $current_db_version = get_option( 'woocommerce_db_version' );
470
+ $logger = wc_get_logger();
471
+ $update_queued = false;
472
+
473
+ foreach ( \WC_Install::get_db_update_callbacks() as $version => $update_callbacks ) {
474
+ if ( version_compare( $current_db_version, $version, '<' ) ) {
475
+ foreach ( $update_callbacks as $update_callback ) {
476
+ $logger->info(
477
+ sprintf( 'Queuing %s - %s', $version, $update_callback ),
478
+ array( 'source' => 'wc_db_updates' )
479
+ );
480
+ $background_updater->push_to_queue( $update_callback );
481
+ $update_queued = true;
482
+ }
483
+ }
484
+ }
485
+
486
+ if ( $update_queued ) {
487
+ $background_updater->save()->dispatch();
488
+ }
489
+
490
+ return array( 'result' => 'success' );
491
+ }
492
+
493
+ }
class/class-mainwp-child.php CHANGED
@@ -1,456 +1,456 @@
1
- <?php
2
- /**
3
- * MainWP Child
4
- *
5
- * @package MainWP\Child
6
- */
7
-
8
- namespace MainWP\Child;
9
-
10
- // phpcs:disable -- required for debugging.
11
- if ( isset( $_REQUEST['mainwpsignature'] ) ) {
12
- // if not debug.
13
- if ( ! defined('MAINWP_CHILD_DEBUG') || false == MAINWP_CHILD_DEBUG ) {
14
- ini_set( 'display_errors', false );
15
- error_reporting( 0 );
16
- }
17
- }
18
-
19
- // phpcs:enable
20
-
21
- require_once ABSPATH . '/wp-admin/includes/file.php';
22
- require_once ABSPATH . '/wp-admin/includes/plugin.php';
23
-
24
- /**
25
- * Class MainWP_Child
26
- *
27
- * Manage all MainWP features.
28
- */
29
- class MainWP_Child {
30
-
31
- /**
32
- * Public static variable containing the latest MainWP Child plugin version.
33
- *
34
- * @var string MainWP Child plugin version.
35
- */
36
- public static $version = '4.1.6.1';
37
-
38
- /**
39
- * Private variable containing the latest MainWP Child update version.
40
- *
41
- * @var string MainWP Child update version.
42
- */
43
- private $update_version = '1.5';
44
-
45
- /**
46
- * Public variable containing the MainWP Child plugin slug.
47
- *
48
- * @var string MainWP Child plugin slug.
49
- */
50
- public $plugin_slug;
51
-
52
- /**
53
- * Private variable containing the MainWP Child plugin directory.
54
- *
55
- * @var string MainWP Child plugin directory.
56
- */
57
- private $plugin_dir;
58
-
59
- /**
60
- * MainWP_Child constructor.
61
- *
62
- * Run any time class is called.
63
- *
64
- * @param resource $plugin_file MainWP Child plugin file.
65
- *
66
- * @uses \MainWP\Child\MainWP_Child_Branding::save_branding_options()
67
- * @uses \MainWP\Child\MainWP_Child_Plugins_Check::instance()
68
- * @uses \MainWP\Child\MainWP_Child_Server_Information::init()
69
- * @uses \MainWP\Child\MainWP_Child_Themes_Check::instance()
70
- * @uses \MainWP\Child\MainWP_Child_Updates::get_instance()
71
- * @uses \MainWP\Child\MainWP_Client_Report::init()
72
- * @uses \MainWP\Child\MainWP_Clone::init()
73
- * @uses \MainWP\Child\MainWP_Connect::check_other_auth()
74
- * @uses \MainWP\Child\MainWP_Pages::init()
75
- * @uses \MainWP\Child\MainWP_Helper::update_option()
76
- * @uses \MainWP\Child\MainWP_Utility::run_saved_snippets()
77
- * @uses \MainWP\Child\MainWP_Utility::get_class_name()
78
- */
79
- public function __construct( $plugin_file ) {
80
- $this->update();
81
- $this->load_all_options();
82
-
83
- $this->plugin_slug = plugin_basename( $plugin_file );
84
-
85
- add_action( 'template_redirect', array( $this, 'template_redirect' ) );
86
- add_action( 'init', array( &$this, 'init_check_login' ), 1 );
87
- add_action( 'init', array( &$this, 'parse_init' ), 9999 );
88
- add_action( 'init', array( &$this, 'localization' ), 33 );
89
- add_action( 'admin_init', array( &$this, 'admin_init' ) );
90
-
91
- // support for better detection for premium plugins.
92
- add_action( 'pre_current_active_plugins', array( MainWP_Child_Updates::get_instance(), 'detect_premium_themesplugins_updates' ) );
93
-
94
- // support for better detection for premium themes.
95
- add_action( 'core_upgrade_preamble', array( MainWP_Child_Updates::get_instance(), 'detect_premium_themesplugins_updates' ) );
96
-
97
- MainWP_Pages::get_instance()->init();
98
-
99
- if ( is_admin() ) {
100
- MainWP_Helper::update_option( 'mainwp_child_plugin_version', self::$version, 'yes' );
101
- }
102
-
103
- MainWP_Connect::instance()->check_other_auth();
104
-
105
- MainWP_Clone::instance()->init();
106
- MainWP_Child_Server_Information::init();
107
- MainWP_Client_Report::instance()->init();
108
- MainWP_Child_Plugins_Check::instance();
109
- MainWP_Child_Themes_Check::instance();
110
- MainWP_Utility::instance()->run_saved_snippets();
111
-
112
- if ( ! get_option( 'mainwp_child_pubkey' ) ) {
113
- MainWP_Child_Branding::instance()->save_branding_options( 'branding_disconnected', 'yes' );
114
- }
115
-
116
- if ( defined( 'DOING_CRON' ) && DOING_CRON ) {
117
- if ( isset( $_GET['mainwp_child_run'] ) && ! empty( $_GET['mainwp_child_run'] ) ) {
118
- add_action( 'init', array( MainWP_Utility::get_class_name(), 'cron_active' ), PHP_INT_MAX );
119
- }
120
- }
121
- }
122
-
123
- /**
124
- * Method load_all_options()
125
- *
126
- * Load all MainWP Child plugin options.
127
- *
128
- * @return array|bool Return array of options or false on failure.
129
- */
130
- public function load_all_options() {
131
-
132
- /**
133
- * WP Database object.
134
- *
135
- * @global object $wpdb WordPress object.
136
- */
137
- global $wpdb;
138
-
139
- if ( ! defined( 'WP_INSTALLING' ) || ! is_multisite() ) {
140
- $alloptions = wp_cache_get( 'alloptions', 'options' );
141
- } else {
142
- $alloptions = false;
143
- }
144
-
145
- if ( ! defined( 'WP_INSTALLING' ) || ! is_multisite() ) {
146
- $notoptions = wp_cache_get( 'notoptions', 'options' );
147
- } else {
148
- $notoptions = false;
149
- }
150
-
151
- if ( ! isset( $alloptions['mainwp_child_server'] ) ) {
152
- $suppress = $wpdb->suppress_errors();
153
- $options = array(
154
- 'mainwp_child_auth',
155
- 'mainwp_child_reports_db',
156
- 'mainwp_child_pluginDir',
157
- 'mainwp_updraftplus_hide_plugin',
158
- 'mainwp_backwpup_ext_enabled',
159
- 'mainwp_child_server',
160
- 'mainwp_pagespeed_hide_plugin',
161
- 'mainwp_child_clone_permalink',
162
- 'mainwp_child_restore_permalink',
163
- 'mainwp_ext_snippets_enabled',
164
- 'mainwp_child_pubkey',
165
- 'mainwp_child_nossl',
166
- 'mainwp_security',
167
- 'mainwp_backupwordpress_ext_enabled',
168
- 'mainwp_pagespeed_ext_enabled',
169
- 'mainwp_linkschecker_ext_enabled',
170
- 'mainwp_child_branding_settings',
171
- 'mainwp_child_plugintheme_days_outdate',
172
- 'mainwp_wp_staging_ext_enabled',
173
- );
174
- $query = "SELECT option_name, option_value FROM $wpdb->options WHERE option_name in (";
175
- foreach ( $options as $option ) {
176
- $query .= "'" . $option . "', ";
177
- }
178
- $query = substr( $query, 0, strlen( $query ) - 2 );
179
- $query .= ")"; // phpcs:ignore -- simple style problem.
180
-
181
- $alloptions_db = $wpdb->get_results( $query ); // phpcs:ignore -- safe query, required to achieve desired results, pull request solutions appreciated.
182
- $wpdb->suppress_errors( $suppress );
183
- if ( ! is_array( $alloptions ) ) {
184
- $alloptions = array();
185
- }
186
- if ( is_array( $alloptions_db ) ) {
187
- foreach ( (array) $alloptions_db as $o ) {
188
- $alloptions[ $o->option_name ] = $o->option_value;
189
- unset( $options[ array_search( $o->option_name, $options ) ] );
190
- }
191
- foreach ( $options as $option ) {
192
- $notoptions[ $option ] = true;
193
- }
194
- if ( ! defined( 'WP_INSTALLING' ) || ! is_multisite() ) {
195
- wp_cache_set( 'alloptions', $alloptions, 'options' );
196
- wp_cache_set( 'notoptions', $notoptions, 'options' );
197
- }
198
- }
199
- }
200
-
201
- return $alloptions;
202
- }
203
-
204
- /**
205
- * Method update()
206
- *
207
- * Update the MainWP Child plugin version (mainwp_child_update_version) option.
208
- *
209
- * @return void
210
- *
211
- * @uses \MainWP\Child\MainWP_Helper::update_option()
212
- */
213
- public function update() {
214
- $update_version = get_option( 'mainwp_child_update_version' );
215
-
216
- if ( $update_version === $this->update_version ) {
217
- return;
218
- }
219
-
220
- MainWP_Helper::update_option( 'mainwp_child_update_version', $this->update_version, 'yes' );
221
- }
222
-
223
- /**
224
- * Method localization()
225
- *
226
- * Load the MainWP Child plugin textdomains.
227
- */
228
- public function localization() {
229
- load_plugin_textdomain( 'mainwp-child', false, dirname( dirname( plugin_basename( __FILE__ ) ) ) . '/languages/' );
230
- }
231
-
232
- /**
233
- * Method template_redirect()
234
- *
235
- * Handle the template redirect for 404 maintenance alerts.
236
- *
237
- * @uses \MainWP\Child\MainWP_Utility::maintenance_alert()
238
- */
239
- public function template_redirect() {
240
- MainWP_Utility::instance()->maintenance_alert();
241
- }
242
-
243
- /**
244
- * Method parse_init()
245
- *
246
- * Parse the init hook.
247
- *
248
- * @return void
249
- *
250
- * @uses \MainWP\Child\MainWP_Child_Callable::init_call_functions()
251
- * @uses \MainWP\Child\MainWP_Clone::request_clone_funct()
252
- * @uses \MainWP\Child\MainWP_Connect::parse_login_required()
253
- * @uses \MainWP\Child\MainWP_Connect::register_site()
254
- * @uses \MainWP\Child\MainWP_Connect::auth()
255
- * @uses \MainWP\Child\MainWP_Connect::parse_init_auth()
256
- * @uses \MainWP\Child\MainWP_Security::fix_all()
257
- * @uses \MainWP\Child\MainWP_Utility::fix_for_custom_themes()
258
- */
259
- public function parse_init() {
260
-
261
- if ( isset( $_REQUEST['cloneFunc'] ) ) {
262
- $valid_clone = MainWP_Clone::instance()->request_clone_funct();
263
- if ( ! $valid_clone ) {
264
- return;
265
- }
266
- }
267
-
268
- // if login required.
269
- if ( isset( $_REQUEST['login_required'] ) && ( '1' === $_REQUEST['login_required'] ) && isset( $_REQUEST['user'] ) ) {
270
- $valid_login_required = MainWP_Connect::instance()->parse_login_required();
271
- // return if login required are not valid, if login is valid will redirect to admin side.
272
- if ( ! $valid_login_required ) {
273
- return;
274
- }
275
- }
276
-
277
- MainWP_Security::fix_all();
278
-
279
- // Register does not require auth, so we register here.
280
- if ( isset( $_POST['function'] ) && 'register' === $_POST['function'] ) {
281
-
282
- /**
283
- * Checks whether cron is in progress.
284
- *
285
- * @const ( bool ) Default: true
286
- * @source https://code-reference.mainwp.com/classes/MainWP.Child.MainWP_Child.html
287
- */
288
- define( 'DOING_CRON', true );
289
-
290
- MainWP_Utility::fix_for_custom_themes();
291
- MainWP_Connect::instance()->register_site(); // register the site and exit.
292
- }
293
-
294
- $mainwpsignature = isset( $_POST['mainwpsignature'] ) ? rawurldecode( wp_unslash( $_POST['mainwpsignature'] ) ) : '';
295
- $function = isset( $_POST['function'] ) ? sanitize_text_field( wp_unslash( $_POST['function'] ) ) : null;
296
- $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
297
- $nossl = isset( $_POST['nossl'] ) ? sanitize_text_field( wp_unslash( $_POST['nossl'] ) ) : 0;
298
-
299
- // Authenticate here.
300
- $auth = MainWP_Connect::instance()->auth( $mainwpsignature, $function, $nonce, $nossl );
301
-
302
- // Parse auth, if it is not correct actions then exit with message or return.
303
- if ( ! MainWP_Connect::instance()->parse_init_auth( $auth ) ) {
304
- return;
305
- }
306
-
307
- $this->parse_init_extensions();
308
-
309
- /**
310
- * WordPress submenu no privilege.
311
- *
312
- * @global string
313
- */
314
- global $_wp_submenu_nopriv;
315
-
316
- if ( null === $_wp_submenu_nopriv ) {
317
- $_wp_submenu_nopriv = array(); // phpcs:ignore -- Required to fix warnings, pull request solutions appreciated.
318
- }
319
-
320
- // execute callable functions here.
321
- MainWP_Child_Callable::get_instance()->init_call_functions( $auth );
322
- }
323
-
324
- /**
325
- * Method init_check_login()
326
- *
327
- * Initiate the check login process.
328
- *
329
- * @uses MainWP_Connect::check_login()
330
- */
331
- public function init_check_login() {
332
- MainWP_Connect::instance()->check_login();
333
- }
334
-
335
- /**
336
- * Method admin_init()
337
- *
338
- * If the current user is administrator initiate the admin ajax.
339
- *
340
- * @uses \MainWP\Child\MainWP_Clone::init_ajax()
341
- * @uses \MainWP\Child\MainWP_Helper::is_admin()
342
- */
343
- public function admin_init() {
344
- if ( MainWP_Helper::is_admin() && is_admin() ) {
345
- MainWP_Clone::instance()->init_ajax();
346
- }
347
- }
348
-
349
- /**
350
- * Method parse_init_extensions()
351
- *
352
- * Parse MainWP Extension initiations.
353
- *
354
- * @uses \MainWP\Child\MainWP_Child_Branding::branding_init()
355
- * @uses \MainWP\Child\MainWP_Client_Report::creport_init()
356
- * @uses \MainWP\Child\MainWP_Child_IThemes_Security::ithemes_init()
357
- * @uses \MainWP\Child\MainWP_Child_Updraft_Plus_Backups::updraftplus_init()
358
- * @uses \MainWP\Child\MainWP_Child_Back_Up_WordPress::init()
359
- * @uses \MainWP\Child\MainWP_Child_WP_Rocket::init()
360
- * @uses \MainWP\Child\MainWP_Child_Back_WP_Up::init()
361
- * @uses \MainWP\Child\MainWP_Child_Back_Up_Buddy::instance()
362
- * @uses \MainWP\Child\MainWP_Child_Wordfence::wordfence_init()
363
- * @uses \MainWP\Child\MainWP_Child_Timecapsule::init()
364
- * @uses \MainWP\Child\MainWP_Child_Staging::init()
365
- * @uses \MainWP\Child\MainWP_Child_Pagespeed::init()
366
- * @uses \MainWP\Child\MainWP_Child_Links_Checker::init()
367
- * @uses \MainWP\Child\MainWP_Child_WPvivid_BackupRestore::init()
368
- */
369
- private function parse_init_extensions() {
370
- MainWP_Child_Branding::instance()->branding_init();
371
- MainWP_Client_Report::instance()->creport_init();
372
- MainWP_Child_IThemes_Security::instance()->ithemes_init();
373
- MainWP_Child_Updraft_Plus_Backups::instance()->updraftplus_init();
374
- MainWP_Child_Back_Up_WordPress::instance()->init();
375
- MainWP_Child_WP_Rocket::instance()->init();
376
- MainWP_Child_Back_WP_Up::instance()->init();
377
- MainWP_Child_Back_Up_Buddy::instance();
378
- MainWP_Child_Wordfence::instance()->wordfence_init();
379
- MainWP_Child_Timecapsule::instance()->init();
380
- MainWP_Child_Staging::instance()->init();
381
- MainWP_Child_Pagespeed::instance()->init();
382
- MainWP_Child_Links_Checker::instance()->init();
383
- MainWP_Child_WPvivid_BackupRestore::instance()->init();
384
- }
385
-
386
- /**
387
- * Method deactivation()
388
- *
389
- * Deactivate the MainWP Child plugin and delete unwanted data.
390
- *
391
- * @param bool $deact Whether or not to deactivate pugin. Default: true.
392
- */
393
- public function deactivation( $deact = true ) {
394
-
395
- $mu_plugin_enabled = apply_filters( 'mainwp_child_mu_plugin_enabled', false );
396
- if ( $mu_plugin_enabled ) {
397
- return;
398
- }
399
-
400
- $to_delete = array(
401
- 'mainwp_child_pubkey',
402
- 'mainwp_child_nonce',
403
- 'mainwp_child_nossl',
404
- 'mainwp_child_nossl_key',
405
- 'mainwp_security',
406
- 'mainwp_child_server',
407
- );
408
- $to_delete[] = 'mainwp_ext_snippets_enabled';
409
- $to_delete[] = 'mainwp_ext_code_snippets';
410
-
411
- foreach ( $to_delete as $delete ) {
412
- if ( get_option( $delete ) ) {
413
- delete_option( $delete );
414
- wp_cache_delete( $delete, 'options' );
415
- }
416
- }
417
-
418
- if ( $deact ) {
419
- do_action( 'mainwp_child_deactivation' );
420
- }
421
- }
422
-
423
- /**
424
- * Method activation()
425
- *
426
- * Activate the MainWP Child plugin and delete unwanted data.
427
- *
428
- * @uses \MainWP\Child\MainWP_Helper::update_option()
429
- */
430
- public function activation() {
431
- $mu_plugin_enabled = apply_filters( 'mainwp_child_mu_plugin_enabled', false );
432
- if ( $mu_plugin_enabled ) {
433
- return;
434
- }
435
-
436
- $to_delete = array(
437
- 'mainwp_child_pubkey',
438
- 'mainwp_child_nonce',
439
- 'mainwp_child_nossl',
440
- 'mainwp_child_nossl_key',
441
- );
442
- foreach ( $to_delete as $delete ) {
443
- if ( get_option( $delete ) ) {
444
- delete_option( $delete );
445
- }
446
- }
447
-
448
- MainWP_Helper::update_option( 'mainwp_child_activated_once', true );
449
-
450
- $to_delete = array( 'mainwp_ext_snippets_enabled', 'mainwp_ext_code_snippets' );
451
- foreach ( $to_delete as $delete ) {
452
- delete_option( $delete );
453
- }
454
- }
455
-
456
- }
1
+ <?php
2
+ /**
3
+ * MainWP Child
4
+ *
5
+ * @package MainWP\Child
6
+ */
7
+
8
+ namespace MainWP\Child;
9
+
10
+ // phpcs:disable -- required for debugging.
11
+ if ( isset( $_REQUEST['mainwpsignature'] ) ) {
12
+ // if not debug.
13
+ if ( ! defined('MAINWP_CHILD_DEBUG') || false == MAINWP_CHILD_DEBUG ) {
14
+ ini_set( 'display_errors', false );
15
+ error_reporting( 0 );
16
+ }
17
+ }
18
+
19
+ // phpcs:enable
20
+
21
+ require_once ABSPATH . '/wp-admin/includes/file.php';
22
+ require_once ABSPATH . '/wp-admin/includes/plugin.php';
23
+
24
+ /**
25
+ * Class MainWP_Child
26
+ *
27
+ * Manage all MainWP features.
28
+ */
29
+ class MainWP_Child {
30
+
31
+ /**
32
+ * Public static variable containing the latest MainWP Child plugin version.
33
+ *
34
+ * @var string MainWP Child plugin version.
35
+ */
36
+ public static $version = '4.1.7';
37
+
38
+ /**
39
+ * Private variable containing the latest MainWP Child update version.
40
+ *
41
+ * @var string MainWP Child update version.
42
+ */
43
+ private $update_version = '1.5';
44
+
45
+ /**
46
+ * Public variable containing the MainWP Child plugin slug.
47
+ *
48
+ * @var string MainWP Child plugin slug.
49
+ */
50
+ public $plugin_slug;
51
+
52
+ /**
53
+ * Private variable containing the MainWP Child plugin directory.
54
+ *
55
+ * @var string MainWP Child plugin directory.
56
+ */
57
+ private $plugin_dir;
58
+
59
+ /**
60
+ * MainWP_Child constructor.
61
+ *
62
+ * Run any time class is called.
63
+ *
64
+ * @param resource $plugin_file MainWP Child plugin file.
65
+ *
66
+ * @uses \MainWP\Child\MainWP_Child_Branding::save_branding_options()
67
+ * @uses \MainWP\Child\MainWP_Child_Plugins_Check::instance()
68
+ * @uses \MainWP\Child\MainWP_Child_Server_Information::init()
69
+ * @uses \MainWP\Child\MainWP_Child_Themes_Check::instance()
70
+ * @uses \MainWP\Child\MainWP_Child_Updates::get_instance()
71
+ * @uses \MainWP\Child\MainWP_Client_Report::init()
72
+ * @uses \MainWP\Child\MainWP_Clone::init()
73
+ * @uses \MainWP\Child\MainWP_Connect::check_other_auth()
74
+ * @uses \MainWP\Child\MainWP_Pages::init()
75
+ * @uses \MainWP\Child\MainWP_Helper::update_option()
76
+ * @uses \MainWP\Child\MainWP_Utility::run_saved_snippets()
77
+ * @uses \MainWP\Child\MainWP_Utility::get_class_name()
78
+ */
79
+ public function __construct( $plugin_file ) {
80
+ $this->update();
81
+ $this->load_all_options();
82
+
83
+ $this->plugin_slug = plugin_basename( $plugin_file );
84
+
85
+ add_action( 'template_redirect', array( $this, 'template_redirect' ) );
86
+ add_action( 'init', array( &$this, 'init_check_login' ), 1 );
87
+ add_action( 'init', array( &$this, 'parse_init' ), 9999 );
88
+ add_action( 'init', array( &$this, 'localization' ), 33 );
89
+ add_action( 'admin_init', array( &$this, 'admin_init' ) );
90
+
91
+ // support for better detection for premium plugins.
92
+ add_action( 'pre_current_active_plugins', array( MainWP_Child_Updates::get_instance(), 'detect_premium_themesplugins_updates' ) );
93
+
94
+ // support for better detection for premium themes.
95
+ add_action( 'core_upgrade_preamble', array( MainWP_Child_Updates::get_instance(), 'detect_premium_themesplugins_updates' ) );
96
+
97
+ MainWP_Pages::get_instance()->init();
98
+
99
+ if ( is_admin() ) {
100
+ MainWP_Helper::update_option( 'mainwp_child_plugin_version', self::$version, 'yes' );
101
+ }
102
+
103
+ MainWP_Connect::instance()->check_other_auth();
104
+
105
+ MainWP_Clone::instance()->init();
106
+ MainWP_Child_Server_Information::init();
107
+ MainWP_Client_Report::instance()->init();
108
+ MainWP_Child_Plugins_Check::instance();
109
+ MainWP_Child_Themes_Check::instance();
110
+ MainWP_Utility::instance()->run_saved_snippets();
111
+
112
+ if ( ! get_option( 'mainwp_child_pubkey' ) ) {
113
+ MainWP_Child_Branding::instance()->save_branding_options( 'branding_disconnected', 'yes' );
114
+ }
115
+
116
+ if ( defined( 'DOING_CRON' ) && DOING_CRON ) {
117
+ if ( isset( $_GET['mainwp_child_run'] ) && ! empty( $_GET['mainwp_child_run'] ) ) {
118
+ add_action( 'init', array( MainWP_Utility::get_class_name(), 'cron_active' ), PHP_INT_MAX );
119
+ }
120
+ }
121
+ }
122
+
123
+ /**
124
+ * Method load_all_options()
125
+ *
126
+ * Load all MainWP Child plugin options.
127
+ *
128
+ * @return array|bool Return array of options or false on failure.
129
+ */
130
+ public function load_all_options() {
131
+
132
+ /**
133
+ * WP Database object.
134
+ *
135
+ * @global object $wpdb WordPress object.
136
+ */
137
+ global $wpdb;
138
+
139
+ if ( ! defined( 'WP_INSTALLING' ) || ! is_multisite() ) {
140
+ $alloptions = wp_cache_get( 'alloptions', 'options' );
141
+ } else {
142
+ $alloptions = false;
143
+ }
144
+
145
+ if ( ! defined( 'WP_INSTALLING' ) || ! is_multisite() ) {
146
+ $notoptions = wp_cache_get( 'notoptions', 'options' );
147
+ } else {
148
+ $notoptions = false;
149
+ }
150
+
151
+ if ( ! isset( $alloptions['mainwp_child_server'] ) ) {
152
+ $suppress = $wpdb->suppress_errors();
153
+ $options = array(
154
+ 'mainwp_child_auth',
155
+ 'mainwp_child_reports_db',
156
+ 'mainwp_child_pluginDir',
157
+ 'mainwp_updraftplus_hide_plugin',
158
+ 'mainwp_backwpup_ext_enabled',
159
+ 'mainwp_child_server',
160
+ 'mainwp_pagespeed_hide_plugin',
161
+ 'mainwp_child_clone_permalink',
162
+ 'mainwp_child_restore_permalink',
163
+ 'mainwp_ext_snippets_enabled',
164
+ 'mainwp_child_pubkey',
165
+ 'mainwp_child_nossl',
166
+ 'mainwp_security',
167
+ 'mainwp_backupwordpress_ext_enabled',
168
+ 'mainwp_pagespeed_ext_enabled',
169
+ 'mainwp_linkschecker_ext_enabled',
170
+ 'mainwp_child_branding_settings',
171
+ 'mainwp_child_plugintheme_days_outdate',
172
+ 'mainwp_wp_staging_ext_enabled',
173
+ );
174
+ $query = "SELECT option_name, option_value FROM $wpdb->options WHERE option_name in (";
175
+ foreach ( $options as $option ) {
176
+ $query .= "'" . $option . "', ";
177
+ }
178
+ $query = substr( $query, 0, strlen( $query ) - 2 );
179
+ $query .= ")"; // phpcs:ignore -- simple style problem.
180
+
181
+ $alloptions_db = $wpdb->get_results( $query ); // phpcs:ignore -- safe query, required to achieve desired results, pull request solutions appreciated.
182
+ $wpdb->suppress_errors( $suppress );
183
+ if ( ! is_array( $alloptions ) ) {
184
+ $alloptions = array();
185
+ }
186
+ if ( is_array( $alloptions_db ) ) {
187
+ foreach ( (array) $alloptions_db as $o ) {
188
+ $alloptions[ $o->option_name ] = $o->option_value;
189
+ unset( $options[ array_search( $o->option_name, $options ) ] );
190
+ }
191
+ foreach ( $options as $option ) {
192
+ $notoptions[ $option ] = true;
193
+ }
194
+ if ( ! defined( 'WP_INSTALLING' ) || ! is_multisite() ) {
195
+ wp_cache_set( 'alloptions', $alloptions, 'options' );
196
+ wp_cache_set( 'notoptions', $notoptions, 'options' );
197
+ }
198
+ }
199
+ }
200
+
201
+ return $alloptions;
202
+ }
203
+
204
+ /**
205
+ * Method update()
206
+ *
207
+ * Update the MainWP Child plugin version (mainwp_child_update_version) option.
208
+ *
209
+ * @return void
210
+ *
211
+ * @uses \MainWP\Child\MainWP_Helper::update_option()
212
+ */
213
+ public function update() {
214
+ $update_version = get_option( 'mainwp_child_update_version' );
215
+
216
+ if ( $update_version === $this->update_version ) {
217
+ return;
218
+ }
219
+
220
+ MainWP_Helper::update_option( 'mainwp_child_update_version', $this->update_version, 'yes' );
221
+ }
222
+
223
+ /**
224
+ * Method localization()
225
+ *
226
+ * Load the MainWP Child plugin textdomains.
227
+ */
228
+ public function localization() {
229
+ load_plugin_textdomain( 'mainwp-child', false, dirname( dirname( plugin_basename( __FILE__ ) ) ) . '/languages/' );
230
+ }
231
+
232
+ /**
233
+ * Method template_redirect()
234
+ *
235
+ * Handle the template redirect for 404 maintenance alerts.
236
+ *
237
+ * @uses \MainWP\Child\MainWP_Utility::maintenance_alert()
238
+ */
239
+ public function template_redirect() {
240
+ MainWP_Utility::instance()->maintenance_alert();
241
+ }
242
+
243
+ /**
244
+ * Method parse_init()
245
+ *
246
+ * Parse the init hook.
247
+ *
248
+ * @return void
249
+ *
250
+ * @uses \MainWP\Child\MainWP_Child_Callable::init_call_functions()
251
+ * @uses \MainWP\Child\MainWP_Clone::request_clone_funct()
252
+ * @uses \MainWP\Child\MainWP_Connect::parse_login_required()
253
+ * @uses \MainWP\Child\MainWP_Connect::register_site()
254
+ * @uses \MainWP\Child\MainWP_Connect::auth()
255
+ * @uses \MainWP\Child\MainWP_Connect::parse_init_auth()
256
+ * @uses \MainWP\Child\MainWP_Security::fix_all()
257
+ * @uses \MainWP\Child\MainWP_Utility::fix_for_custom_themes()
258
+ */
259
+ public function parse_init() {
260
+
261
+ if ( isset( $_REQUEST['cloneFunc'] ) ) {
262
+ $valid_clone = MainWP_Clone::instance()->request_clone_funct();
263
+ if ( ! $valid_clone ) {
264
+ return;
265
+ }
266
+ }
267
+
268
+ // if login required.
269
+ if ( isset( $_REQUEST['login_required'] ) && ( '1' === $_REQUEST['login_required'] ) && isset( $_REQUEST['user'] ) ) {
270
+ $valid_login_required = MainWP_Connect::instance()->parse_login_required();
271
+ // return if login required are not valid, if login is valid will redirect to admin side.
272
+ if ( ! $valid_login_required ) {
273
+ return;
274
+ }
275
+ }
276
+
277
+ MainWP_Security::fix_all();
278
+
279
+ // Register does not require auth, so we register here.
280
+ if ( isset( $_POST['function'] ) && 'register' === $_POST['function'] ) {
281
+
282
+ /**
283
+ * Checks whether cron is in progress.
284
+ *
285
+ * @const ( bool ) Default: true
286
+ * @source https://code-reference.mainwp.com/classes/MainWP.Child.MainWP_Child.html
287
+ */
288
+ define( 'DOING_CRON', true );
289
+
290
+ MainWP_Utility::fix_for_custom_themes();
291
+ MainWP_Connect::instance()->register_site(); // register the site and exit.
292
+ }
293
+
294
+ $mainwpsignature = isset( $_POST['mainwpsignature'] ) ? rawurldecode( wp_unslash( $_POST['mainwpsignature'] ) ) : '';
295
+ $function = isset( $_POST['function'] ) ? sanitize_text_field( wp_unslash( $_POST['function'] ) ) : null;
296
+ $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
297
+ $nossl = isset( $_POST['nossl'] ) ? sanitize_text_field( wp_unslash( $_POST['nossl'] ) ) : 0;
298
+
299
+ // Authenticate here.
300
+ $auth = MainWP_Connect::instance()->auth( $mainwpsignature, $function, $nonce, $nossl );
301
+
302
+ // Parse auth, if it is not correct actions then exit with message or return.
303
+ if ( ! MainWP_Connect::instance()->parse_init_auth( $auth ) ) {
304
+ return;
305
+ }
306
+
307
+ $this->parse_init_extensions();
308
+
309
+ /**
310
+ * WordPress submenu no privilege.
311
+ *
312
+ * @global string
313
+ */
314
+ global $_wp_submenu_nopriv;
315
+
316
+ if ( null === $_wp_submenu_nopriv ) {
317
+ $_wp_submenu_nopriv = array(); // phpcs:ignore -- Required to fix warnings, pull request solutions appreciated.
318
+ }
319
+
320
+ // execute callable functions here.
321
+ MainWP_Child_Callable::get_instance()->init_call_functions( $auth );
322
+ }
323
+
324
+ /**
325
+ * Method init_check_login()
326
+ *
327
+ * Initiate the check login process.
328
+ *
329
+ * @uses MainWP_Connect::check_login()
330
+ */
331
+ public function init_check_login() {
332
+ MainWP_Connect::instance()->check_login();
333
+ }
334
+
335
+ /**
336
+ * Method admin_init()
337
+ *
338
+ * If the current user is administrator initiate the admin ajax.
339
+ *
340
+ * @uses \MainWP\Child\MainWP_Clone::init_ajax()
341
+ * @uses \MainWP\Child\MainWP_Helper::is_admin()
342
+ */
343
+ public function admin_init() {
344
+ if ( MainWP_Helper::is_admin() && is_admin() ) {
345
+ MainWP_Clone::instance()->init_ajax();
346
+ }
347
+ }
348
+
349
+ /**
350
+ * Method parse_init_extensions()
351
+ *
352
+ * Parse MainWP Extension initiations.
353
+ *
354
+ * @uses \MainWP\Child\MainWP_Child_Branding::branding_init()
355
+ * @uses \MainWP\Child\MainWP_Client_Report::creport_init()
356
+ * @uses \MainWP\Child\MainWP_Child_IThemes_Security::ithemes_init()
357
+ * @uses \MainWP\Child\MainWP_Child_Updraft_Plus_Backups::updraftplus_init()
358
+ * @uses \MainWP\Child\MainWP_Child_Back_Up_WordPress::init()
359
+ * @uses \MainWP\Child\MainWP_Child_WP_Rocket::init()
360
+ * @uses \MainWP\Child\MainWP_Child_Back_WP_Up::init()
361
+ * @uses \MainWP\Child\MainWP_Child_Back_Up_Buddy::instance()
362
+ * @uses \MainWP\Child\MainWP_Child_Wordfence::wordfence_init()
363
+ * @uses \MainWP\Child\MainWP_Child_Timecapsule::init()
364
+ * @uses \MainWP\Child\MainWP_Child_Staging::init()
365
+ * @uses \MainWP\Child\MainWP_Child_Pagespeed::init()
366
+ * @uses \MainWP\Child\MainWP_Child_Links_Checker::init()
367
+ * @uses \MainWP\Child\MainWP_Child_WPvivid_BackupRestore::init()
368
+ */
369
+ private function parse_init_extensions() {
370
+ MainWP_Child_Branding::instance()->branding_init();
371
+ MainWP_Client_Report::instance()->creport_init();
372
+ MainWP_Child_IThemes_Security::instance()->ithemes_init();
373
+ MainWP_Child_Updraft_Plus_Backups::instance()->updraftplus_init();
374
+ MainWP_Child_Back_Up_WordPress::instance()->init();
375
+ MainWP_Child_WP_Rocket::instance()->init();
376
+ MainWP_Child_Back_WP_Up::instance()->init();
377
+ MainWP_Child_Back_Up_Buddy::instance();
378
+ MainWP_Child_Wordfence::instance()->wordfence_init();
379
+ MainWP_Child_Timecapsule::instance()->init();
380
+ MainWP_Child_Staging::instance()->init();
381
+ MainWP_Child_Pagespeed::instance()->init();
382
+ MainWP_Child_Links_Checker::instance()->init();
383
+ MainWP_Child_WPvivid_BackupRestore::instance()->init();
384
+ }
385
+
386
+ /**
387
+ * Method deactivation()
388
+ *
389
+ * Deactivate the MainWP Child plugin and delete unwanted data.
390
+ *
391
+ * @param bool $deact Whether or not to deactivate pugin. Default: true.
392
+ */
393
+ public function deactivation( $deact = true ) {
394
+
395
+ $mu_plugin_enabled = apply_filters( 'mainwp_child_mu_plugin_enabled', false );
396
+ if ( $mu_plugin_enabled ) {
397
+ return;
398
+ }
399
+
400
+ $to_delete = array(
401
+ 'mainwp_child_pubkey',
402
+ 'mainwp_child_nonce',
403
+ 'mainwp_child_nossl',
404
+ 'mainwp_child_nossl_key',
405
+ 'mainwp_security',
406
+ 'mainwp_child_server',
407
+ );
408
+ $to_delete[] = 'mainwp_ext_snippets_enabled';
409
+ $to_delete[] = 'mainwp_ext_code_snippets';
410
+
411
+ foreach ( $to_delete as $delete ) {
412
+ if ( get_option( $delete ) ) {
413
+ delete_option( $delete );
414
+ wp_cache_delete( $delete, 'options' );
415
+ }
416
+ }
417
+
418
+ if ( $deact ) {
419
+ do_action( 'mainwp_child_deactivation' );
420
+ }
421
+ }
422
+
423
+ /**
424
+ * Method activation()
425
+ *
426
+ * Activate the MainWP Child plugin and delete unwanted data.
427
+ *
428
+ * @uses \MainWP\Child\MainWP_Helper::update_option()
429
+ */
430
+ public function activation() {
431
+ $mu_plugin_enabled = apply_filters( 'mainwp_child_mu_plugin_enabled', false );
432
+ if ( $mu_plugin_enabled ) {
433
+ return;
434
+ }
435
+
436
+ $to_delete = array(
437
+ 'mainwp_child_pubkey',
438
+ 'mainwp_child_nonce',
439
+ 'mainwp_child_nossl',
440
+ 'mainwp_child_nossl_key',
441
+ );
442
+ foreach ( $to_delete as $delete ) {
443
+ if ( get_option( $delete ) ) {
444
+ delete_option( $delete );
445
+ }
446
+ }
447
+
448
+ MainWP_Helper::update_option( 'mainwp_child_activated_once', true );
449
+
450
+ $to_delete = array( 'mainwp_ext_snippets_enabled', 'mainwp_ext_code_snippets' );
451
+ foreach ( $to_delete as $delete ) {
452
+ delete_option( $delete );
453
+ }
454
+ }
455
+
456
+ }
class/class-mainwp-clone.php CHANGED
@@ -1,857 +1,863 @@
1
- <?php
2
- /**
3
- * MainWP MainWP_Clone
4
- *
5
- * Manage child site cloning process.
6
- *
7
- * @package MainWP\Child
8
- */
9
-
10
- namespace MainWP\Child;
11
-
12
- /**
13
- * Class MainWP_Clone
14
- *
15
- * Manage child site cloning process.
16
- */
17
- class MainWP_Clone {
18
-
19
- /**
20
- * Public static variable to hold the single instance of the class.
21
- *
22
- * @var mixed Default null
23
- */
24
- protected static $instance = null;
25
-
26
- /**
27
- * Protected variable to hold security nonces.
28
- *
29
- * @var array Security nonces.
30
- */
31
- protected $security_nonces;
32
-
33
- /**
34
- * Method get_class_name()
35
- *
36
- * Get class name.
37
- *
38
- * @return string __CLASS__ Class name.
39
- */
40
- public static function get_class_name() {
41
- return __CLASS__;
42
- }
43
-
44
- /**
45
- * Method instance()
46
- *
47
- * Create a public static instance.
48
- *
49
- * @return mixed Class instance.
50
- */
51
- public static function instance() {
52
- if ( null === self::$instance ) {
53
- self::$instance = new self();
54
- }
55
- return self::$instance;
56
- }
57
-
58
- /**
59
- * Method init_ajax()
60
- *
61
- * Initiate AJAX requests.
62
- */
63
- public function init_ajax() {
64
- $this->add_action( 'mainwp-child_clone_backupcreate', array( &$this, 'clone_backup_create' ) );
65
- $this->add_action( 'mainwp-child_clone_backupcreatepoll', array( &$this, 'clone_backup_create_poll' ) );
66
- $this->add_action( 'mainwp-child_clone_backupdownload', array( &$this, 'clone_backup_download' ) );
67
- $this->add_action( 'mainwp-child_clone_backupdownloadpoll', array( &$this, 'clone_backup_download_poll' ) );
68
- $this->add_action( 'mainwp-child_clone_backupextract', array( &$this, 'clone_backup_extract' ) );
69
- }
70
-
71
- /**
72
- * Method add_security_nonce()
73
- *
74
- * Create security nonce for specific actions.
75
- *
76
- * @param string $action Contains the action that requires security nonce.
77
- */
78
- public function add_security_nonce( $action ) {
79
- if ( ! is_array( $this->security_nonces ) ) {
80
- $this->security_nonces = array();
81
- }
82
- if ( ! function_exists( 'wp_create_nonce' ) ) {
83
- include_once ABSPATH . WPINC . '/pluggable.php';
84
- }
85
- $this->security_nonces[ $action ] = wp_create_nonce( $action );
86
- }
87
-
88
- /**
89
- * Method get_security_nonces()
90
- *
91
- * Get security nonces from the security nonces array.
92
- *
93
- * @return array Security nonces.
94
- */
95
- public function get_security_nonces() {
96
- return $this->security_nonces;
97
- }
98
-
99
- /**
100
- * Method add_action()
101
- *
102
- * Add actions to the 'wp_ajax_' hook and create security nonce.
103
- *
104
- * @param string $action Contains action to be added to the 'wp_ajax_' hook.
105
- * @param string $callback Contains a callback action.
106
- */
107
- public function add_action( $action, $callback ) {
108
- add_action( 'wp_ajax_' . $action, $callback );
109
- $this->add_security_nonce( $action );
110
- }
111
-
112
- /**
113
- * Method secure_request()
114
- *
115
- * Build secure request for the clone process.
116
- *
117
- * @param string $action Contains the action that is being performed.
118
- * @param string $query_arg Contains the query argument.
119
- *
120
- * @return void
121
- *
122
- * @uses \MainWP\Child\MainWP_Helper::is_admin()
123
- * @uses \MainWP\Child\MainWP_Helper::update_option()
124
- */
125
- public function secure_request( $action = '', $query_arg = 'security' ) {
126
- if ( ! MainWP_Helper::is_admin() ) {
127
- die( 0 );
128
- }
129
-
130
- if ( '' == $action ) {
131
- return;
132
- }
133
-
134
- if ( ! $this->check_security( $action, $query_arg ) ) {
135
- die( wp_json_encode( array( 'error' => __( 'Invalid request!', 'mainwp-child' ) ) ) );
136
- }
137
-
138
- if ( isset( $_POST['dts'] ) ) {
139
- $ajaxPosts = get_option( 'mainwp_ajaxposts' );
140
- if ( ! is_array( $ajaxPosts ) ) {
141
- $ajaxPosts = array();
142
- }
143
-
144
- // If already processed, just quit!
145
- if ( isset( $ajaxPosts[ $action ] ) && ( $ajaxPosts[ $action ] == $_POST['dts'] ) ) {
146
- die( wp_json_encode( array( 'error' => __( 'Double request!', 'mainwp-child' ) ) ) );
147
- }
148
-
149
- $ajaxPosts[ $action ] = isset( $_POST['dts'] ) ? sanitize_text_field( wp_unslash( $_POST['dts'] ) ) : '';
150
- MainWP_Helper::update_option( 'mainwp_ajaxposts', $ajaxPosts );
151
- }
152
- }
153
-
154
- /**
155
- * Method check_security()
156
- *
157
- * Check the clone request security.
158
- *
159
- * @param string $action Contains the action that is being performed.
160
- * @param string $query_arg Contains the query argument.
161
- *
162
- * @return bool true|false If secure, return true, if not, return false.
163
- */
164
- public function check_security( $action = - 1, $query_arg = 'security' ) {
165
- if ( - 1 == $action ) {
166
- return false;
167
- }
168
-
169
- $adminurl = strtolower( admin_url() );
170
- $referer = strtolower( wp_get_referer() );
171
- $result = isset( $_REQUEST[ $query_arg ] ) ? wp_verify_nonce( sanitize_text_field( wp_unslash( $_REQUEST[ $query_arg ] ) ), $action ) : false;
172
- if ( ! $result && ! ( - 1 == $action && 0 === strpos( $referer, $adminurl ) ) ) {
173
- return false;
174
- }
175
-
176
- return true;
177
- }
178
-
179
- /**
180
- * Method init()
181
- *
182
- * Initiate action hooks.
183
- *
184
- * @uses \MainWP\Child\MainWP_Clone_Page::get_class_name()
185
- */
186
- public function init() {
187
- add_action( 'check_admin_referer', array( self::get_class_name(), 'permalink_changed' ) );
188
- if ( get_option( 'mainwp_child_clone_permalink' ) || get_option( 'mainwp_child_restore_permalink' ) ) {
189
- add_action( 'admin_notices', array( MainWP_Clone_Page::get_class_name(), 'permalink_admin_notice' ) );
190
- }
191
- }
192
-
193
- /**
194
- * Method upload_mimes()
195
- *
196
- * Add allowed mime types and file extensions.
197
- *
198
- * @param array $mime_types Mime types keyed by the file extension regex corresponding to those types.
199
- *
200
- * @return array Array containing allowed mime types.
201
- */
202
- public static function upload_mimes( $mime_types = array() ) {
203
- if ( ! isset( $mime_types['tar.bz2'] ) ) {
204
- $mime_types['tar.bz2'] = 'application/x-tar';
205
- }
206
-
207
- return $mime_types;
208
- }
209
-
210
- /**
211
- * Request clone.
212
- *
213
- * @return bool|void true|void.
214
- *
215
- * @uses \MainWP\Child\MainWP_Connect::is_valid_auth()
216
- * @uses \MainWP\Child\MainWP_Helper::get_mainwp_dir()
217
- * @uses \MainWP\Child\MainWP_Helper::write()
218
- * @uses \MainWP\Child\MainWP_Utility::upload_file()
219
- */
220
- public function request_clone_funct() {
221
-
222
- if ( ! isset( $_REQUEST['key'] ) ) {
223
- return;
224
- }
225
- if ( ! isset( $_REQUEST['f'] ) || ( '' === $_REQUEST['f'] ) ) {
226
- return;
227
- }
228
- if ( ! isset( $_REQUEST['key'] ) || ! MainWP_Connect::instance()->is_valid_auth( wp_unslash( $_REQUEST['key'] ) ) ) {
229
- return;
230
- }
231
-
232
- $cloneFunc = isset( $_REQUEST['cloneFunc'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['cloneFunc'] ) ) : '';
233
-
234
- if ( 'dl' === $cloneFunc ) {
235
- $f = isset( $_REQUEST['f'] ) ? wp_unslash( $_REQUEST['f'] ) : '';
236
- if ( ! empty( $f ) ) {
237
- MainWP_Utility::instance()->upload_file( wp_unslash( $_REQUEST['f'] ) );
238
- }
239
- exit;
240
- } elseif ( 'deleteCloneBackup' === $cloneFunc ) {
241
- $df = isset( $_POST['f'] ) ? sanitize_text_field( wp_unslash( $_POST['f'] ) ) : '';
242
- if ( empty( $df ) || stristr( $df, '..' ) ) {
243
- return false;
244
- }
245
-
246
- $dirs = MainWP_Helper::get_mainwp_dir( 'backup' );
247
- $backupdir = $dirs[0];
248
- $result = glob( $backupdir . $df );
249
- if ( 0 === count( $result ) ) {
250
- return;
251
- }
252
-
253
- unlink( $result[0] );
254
- MainWP_Helper::write( array( 'result' => 'ok' ) );
255
- } elseif ( 'createCloneBackupPoll' === $cloneFunc ) {
256
- $dirs = MainWP_Helper::get_mainwp_dir( 'backup' );
257
- $backupdir = $dirs[0];
258
- $f = isset( $_POST['f'] ) ? wp_unslash( $_POST['f'] ) : '';
259
- $archiveFile = false;
260
- if ( ! empty( $f ) ) {
261
- $result = glob( $backupdir . 'backup-' . $f . '-*' );
262
- foreach ( $result as $file ) {
263
- if ( self::is_archive( $file, 'backup-' . $f . '-' ) ) {
264
- $archiveFile = $file;
265
- break;
266
- }
267
- }
268
- }
269
- if ( false === $archiveFile ) {
270
- return;
271
- }
272
-
273
- MainWP_Helper::write( array( 'size' => filesize( $archiveFile ) ) );
274
- } elseif ( 'createCloneBackup' === $cloneFunc ) {
275
- $this->create_clone_backup();
276
- }
277
- return true;
278
- }
279
-
280
-
281
- /**
282
- * Create backup of clone.
283
- *
284
- * @uses \MainWP\Child\MainWP_Backup::create_full_backup()
285
- * @uses \MainWP\Child\MainWP_Helper::end_session()
286
- * @uses \MainWP\Child\MainWP_Helper::is_dir_empty()
287
- * @uses \MainWP\Child\MainWP_Helper::get_mainwp_dir()
288
- * @uses \MainWP\Child\MainWP_Helper::write()
289
- */
290
- private function create_clone_backup() { // phpcs:ignore -- Current complexity is the only way to achieve desired results, pull request solutions appreciated.
291
- MainWP_Helper::end_session();
292
- $files = glob( WP_CONTENT_DIR . '/dbBackup*.sql' );
293
- foreach ( $files as $file ) {
294
- unlink( $file );
295
- }
296
- if ( file_exists( ABSPATH . 'clone/config.txt' ) ) {
297
- unlink( ABSPATH . 'clone/config.txt' );
298
- }
299
- if ( MainWP_Helper::is_dir_empty( ABSPATH . 'clone' ) ) {
300
- rmdir( ABSPATH . 'clone' );
301
- }
302
-
303
- $wpversion = isset( $_POST['wpversion'] ) ? sanitize_text_field( wp_unslash( $_POST['wpversion'] ) ) : '';
304
- global $wp_version;
305
- $includeCoreFiles = ( $wpversion !== $wp_version );
306
- $excludes = ( isset( $_POST['exclude'] ) ? explode( ',', wp_unslash( $_POST['exclude'] ) ) : array() );
307
- $excludes[] = str_replace( ABSPATH, '', WP_CONTENT_DIR ) . '/uploads/mainwp';
308
- $uploadDir = MainWP_Helper::get_mainwp_dir();
309
- $uploadDir = $uploadDir[0];
310
- $excludes[] = str_replace( ABSPATH, '', $uploadDir );
311
- $excludes[] = str_replace( ABSPATH, '', WP_CONTENT_DIR ) . '/object-cache.php';
312
- if ( version_compare( phpversion(), '5.3.0' ) >= 0 || ! ini_get( 'safe_mode' ) ) {
313
- set_time_limit( 6000 );
314
- }
315
-
316
- $newExcludes = array();
317
- foreach ( $excludes as $exclude ) {
318
- $newExcludes[] = rtrim( $exclude, '/' );
319
- }
320
-
321
- $method = ( ! isset( $_POST['zipmethod'] ) ? 'tar.gz' : wp_unslash( $_POST['zipmethod'] ) );
322
- if ( 'tar.gz' === $method && ! function_exists( 'gzopen' ) ) {
323
- $method = 'zip';
324
- }
325
-
326
- $file = false;
327
- if ( isset( $_POST['f'] ) ) {
328
- $file = ! empty( $_POST['f'] ) ? wp_unslash( $_POST['f'] ) : false;
329
- } elseif ( isset( $_POST['file'] ) ) {
330
- $file = ! empty( $_POST['file'] ) ? wp_unslash( $_POST['file'] ) : false;
331
- }
332
-
333
- $res = MainWP_Backup::get()->create_full_backup( $newExcludes, $file, true, $includeCoreFiles, 0, false, false, false, false, $method );
334
- if ( ! $res ) {
335
- $information['backup'] = false;
336
- } else {
337
- $information['backup'] = $res['file'];
338
- $information['size'] = $res['filesize'];
339
- }
340
-
341
- $plugins = array();
342
- $dir = WP_CONTENT_DIR . '/plugins/';
343
- $fh = opendir( $dir );
344
- while ( $entry = readdir( $fh ) ) {
345
- if ( ! is_dir( $dir . $entry ) ) {
346
- continue;
347
- }
348
- if ( ( '.' === $entry ) || ( '..' === $entry ) ) {
349
- continue;
350
- }
351
- $plugins[] = $entry;
352
- }
353
- closedir( $fh );
354
- $information['plugins'] = $plugins;
355
-
356
- $themes = array();
357
- $dir = WP_CONTENT_DIR . '/themes/';
358
- $fh = opendir( $dir );
359
- while ( $entry = readdir( $fh ) ) {
360
- if ( ! is_dir( $dir . $entry ) ) {
361
- continue;
362
- }
363
- if ( ( '.' === $entry ) || ( '..' === $entry ) ) {
364
- continue;
365
- }
366
- $themes[] = $entry;
367
- }
368
- closedir( $fh );
369
- $information['themes'] = $themes;
370
- MainWP_Helper::write( $information );
371
- }
372
-
373
- /**
374
- * Method clone_backup_create()
375
- *
376
- * Create backup of template site so it can be used to clone it.
377
- *
378
- * @throws \Exception Error message.
379
- *
380
- * @uses \MainWP\Child\MainWP_Helper::end_session()
381
- * @uses \MainWP\Child\MainWP_Helper::update_option()
382
- * @uses \MainWP\Child\MainWP_Utility::fetch_url()
383
- */
384
- public function clone_backup_create() {
385
- try {
386
- $this->secure_request( 'mainwp-child_clone_backupcreate' );
387
-
388
- if ( ! isset( $_POST['siteId'] ) ) {
389
- throw new \Exception( __( 'No site given', 'mainwp-child' ) );
390
- }
391
-
392
- $siteId = isset( $_POST['siteId'] ) ? intval( wp_unslash( $_POST['siteId'] ) ) : false;
393
-
394
- $rand = isset( $_POST['rand'] ) ? sanitize_text_field( wp_unslash( $_POST['rand'] ) ) : '';
395
- $sitesToClone = get_option( 'mainwp_child_clone_sites' );
396
-
397
- if ( ! is_array( $sitesToClone ) || ! isset( $sitesToClone[ $siteId ] ) ) {
398
- throw new \Exception( __( 'Site not found', 'mainwp-child' ) );
399
- }
400
-
401
- $siteToClone = $sitesToClone[ $siteId ];
402
- $url = $siteToClone['url'];
403
- $key = $siteToClone['extauth'];
404
-
405
- MainWP_Helper::end_session();
406
-
407
- // Send request to the childsite!
408
-
409
- /**
410
- * The installed version of WordPress.
411
- *
412
- * @global string $wp_version The installed version of WordPress.
413
- */
414
- global $wp_version;
415
-
416
- $method = ( function_exists( 'gzopen' ) ? 'tar.gz' : 'zip' );
417
- $result = MainWP_Utility::fetch_url(
418
- $url,
419
- array(
420
- 'cloneFunc' => 'createCloneBackup',
421
- 'key' => $key,
422
- 'f' => $rand,
423
- 'wpversion' => $wp_version,
424
- 'zipmethod' => $method,
425
- 'json_result' => true,
426
- )
427
- );
428
-
429
- if ( ! $result['backup'] ) {
430
- throw new \Exception( __( 'Could not create backupfile on child', 'mainwp-child' ) );
431
- }
432
- MainWP_Helper::update_option( 'mainwp_temp_clone_plugins', $result['plugins'] );
433
- MainWP_Helper::update_option( 'mainwp_temp_clone_themes', $result['themes'] );
434
-
435
- $output = array(
436
- 'url' => $result['backup'],
437
- 'size' => round( $result['size'] / 1024, 0 ),
438
- );
439
- } catch ( \Exception $e ) {
440
- $output = array( 'error' => $e->getMessage() );
441
- }
442
-
443
- die( wp_json_encode( $output ) );
444
- }
445
-
446
- /**
447
- * Method clone_backup_create_poll()
448
- *
449
- * Create backup poll of template site so it can be used to clone it.
450
- *
451
- * @throws \Exception Error message.
452
- *
453
- * @uses \MainWP\Child\MainWP_Helper::end_session()
454
- * @uses \MainWP\Child\MainWP_Utility::fetch_url()
455
- */
456
- public function clone_backup_create_poll() {
457
- try {
458
- $this->secure_request( 'mainwp-child_clone_backupcreatepoll' );
459
-
460
- if ( ! isset( $_POST['siteId'] ) ) {
461
- throw new \Exception( __( 'No site given', 'mainwp-child' ) );
462
- }
463
- $siteId = isset( $_POST['siteId'] ) ? sanitize_text_field( wp_unslash( $_POST['siteId'] ) ) : '';
464
- $rand = isset( $_POST['rand'] ) ? sanitize_text_field( wp_unslash( $_POST['rand'] ) ) : '';
465
-
466
- $sitesToClone = get_option( 'mainwp_child_clone_sites' );
467
- if ( ! is_array( $sitesToClone ) || ! isset( $sitesToClone[ $siteId ] ) ) {
468
- throw new \Exception( __( 'Site not found', 'mainwp-child' ) );
469
- }
470
-
471
- $siteToClone = $sitesToClone[ $siteId ];
472
- $url = $siteToClone['url'];
473
-
474
- $key = $siteToClone['extauth'];
475
-
476
- MainWP_Helper::end_session();
477
- // Send request to the childsite!
478
- $result = MainWP_Utility::fetch_url(
479
- $url,
480
- array(
481
- 'cloneFunc' => 'createCloneBackupPoll',
482
- 'key' => $key,
483
- 'f' => $rand,
484
- 'json_result' => true,
485
- )
486
- );
487
-
488
- if ( ! isset( $result['size'] ) ) {
489
- throw new \Exception( __( 'Invalid response', 'mainwp-child' ) );
490
- }
491
-
492
- $output = array( 'size' => round( $result['size'] / 1024, 0 ) );
493
- } catch ( \Exception $e ) {
494
- $output = array( 'error' => $e->getMessage() );
495
- }
496
- die( wp_json_encode( $output ) );
497
- }
498
-
499
- /**
500
- * Method clone_backup_download()
501
- *
502
- * Download backup file of template site so it can be used to clone it.
503
- *
504
- * @return mixed Response message.
505
- * @throws \Exception Error message.
506
- *
507
- * @uses \MainWP\Child\MainWP_Helper::end_session()
508
- * @uses \MainWP\Child\MainWP_Helper::get_mainwp_dir()
509
- * @uses \MainWP\Child\MainWP_Utility::fetch_url()
510
- */
511
- public function clone_backup_download() {
512
- try {
513
- $this->secure_request( 'mainwp-child_clone_backupdownload' );
514
-
515
- if ( ! isset( $_POST['file'] ) ) {
516
- throw new \Exception( __( 'No download link given', 'mainwp-child' ) );
517
- }
518
-
519
- $file = isset( $_POST['file'] ) ? wp_unslash( $_POST['file'] ) : '';
520
- if ( isset( $_POST['siteId'] ) ) {
521
- $siteId = isset( $_POST['siteId'] ) ? intval( wp_unslash( $_POST['siteId'] ) ) : false;
522
-
523
- $sitesToClone = get_option( 'mainwp_child_clone_sites' );
524
-
525
- if ( ! is_array( $sitesToClone ) || ! isset( $sitesToClone[ $siteId ] ) ) {
526
- throw new \Exception( __( 'Site not found', 'mainwp-child' ) );
527
- }
528
-
529
- $siteToClone = $sitesToClone[ $siteId ];
530
- $url = $siteToClone['url'];
531
- $key = $siteToClone['extauth'];
532
-
533
- $url = trailingslashit( $url ) . '?cloneFunc=dl&key=' . rawurlencode( $key ) . '&f=' . $file;
534
- } else {
535
- $url = $file;
536
- }
537
- MainWP_Helper::end_session();
538
- // Send request to the childsite!
539
- $split = explode( '=', $file );
540
- $file = urldecode( $split[ count( $split ) - 1 ] );
541
- $filename = 'download-' . basename( $file );
542
- $dirs = MainWP_Helper::get_mainwp_dir( 'backup', false );
543
- $backupdir = $dirs[0];
544
- $dh = opendir( $backupdir );
545
- if ( $dh ) {
546
- $fl = readdir( $dh );
547
- while ( false !== $fl ) {
548
- if ( '.' !== $fl && '..' !== $fl && self::is_archive( $fl, 'download-' ) ) {
549
- unlink( $backupdir . $fl );
550
- }
551
- $fl = readdir( $dh );
552
- }
553
- closedir( $dh );
554
- }
555
-
556
- $filename = $backupdir . $filename;
557
-
558
- $response = wp_remote_get(
559
- $url,
560
- array(
561
- 'timeout' => 300000,
562
- 'stream' => true,
563
- 'filename' => $filename,
564
- )
565
- );
566
-
567
- if ( is_wp_error( $response ) ) {
568
- unlink( $filename );
569
-
570
- return $response;
571
- }
572
-
573
- if ( 200 !== (int) wp_remote_retrieve_response_code( $response ) ) {
574
- unlink( $filename );
575
-
576
- return new \WP_Error( 'http_404', trim( wp_remote_retrieve_response_message( $response ) ) );
577
- }
578
-
579
- $output = array( 'done' => $filename );
580
-
581
- // Delete backup on child.
582
- try {
583
- if ( isset( $_POST['siteId'] ) ) {
584
- $siteId = isset( $_POST['siteId'] ) ? intval( wp_unslash( $_POST['siteId'] ) ) : false;
585
-
586
- $sitesToClone = get_option( 'mainwp_child_clone_sites' );
587
- if ( is_array( $sitesToClone ) && isset( $sitesToClone[ $siteId ] ) ) {
588
- $siteToClone = $sitesToClone[ $siteId ];
589
-
590
- MainWP_Utility::fetch_url(
591
- $siteToClone['url'],
592
- array(
593
- 'cloneFunc' => 'deleteCloneBackup',
594
- 'key' => $siteToClone['extauth'],
595
- 'f' => $file,
596
- 'json_result' => true,
597
- )
598
- );
599
- }
600
- }
601
- } catch ( \Exception $e ) {
602
- throw $e;
603
- }
604
- } catch ( \Exception $e ) {
605
- $output = array( 'error' => $e->getMessage() );
606
- }
607
-
608
- die( wp_json_encode( $output ) );
609
- }
610
-
611
- /**
612
- * Method clone_backup_download_poll()
613
- *
614
- * Download backup file poll of template site so it can be used to clone it.
615
- *
616
- * @throws \Exception Error message.
617
- *
618
- * @uses \MainWP\Child\MainWP_Helper::end_session()
619
- * @uses \MainWP\Child\MainWP_Helper::get_mainwp_dir()
620
- */
621
- public function clone_backup_download_poll() {
622
- try {
623
- $this->secure_request( 'mainwp-child_clone_backupdownloadpoll' );
624
-
625
- MainWP_Helper::end_session();
626
-
627
- $dirs = MainWP_Helper::get_mainwp_dir( 'backup', false );
628
- $backupdir = $dirs[0];
629
- $files = glob( $backupdir . 'download-*' );
630
- $archiveFile = false;
631
-
632
- foreach ( $files as $file ) {
633
- if ( self::is_archive( $file, 'download-' ) ) {
634
- $archiveFile = $file;
635
- break;
636
- }
637
- }
638
- if ( false === $archiveFile ) {
639
- throw new \Exception( __( 'No download file found', 'mainwp-child' ) );
640
- }
641
- $output = array( 'size' => filesize( $archiveFile ) / 1024 );
642
- } catch ( \Exception $e ) {
643
- $output = array( 'error' => $e->getMessage() );
644
- }
645
- die( wp_json_encode( $output ) );
646
- }
647
-
648
- /**
649
- * Method clone_backup_extract()
650
- *
651
- * Extract the backup archive to clone the site.
652
- *
653
- * @uses \MainWP\Child\MainWP_Clone_Install()
654
- * @uses \MainWP\Child\MainWP_Helper::end_session()
655
- * @uses \MainWP\Child\MainWP_Helper::update_option()
656
- * @uses \MainWP\Child\MainWP_Helper::starts_with()
657
- */
658
- public function clone_backup_extract() {
659
- try {
660
- $this->secure_request( 'mainwp-child_clone_backupextract' );
661
-
662
- MainWP_Helper::end_session();
663
-
664
- $file = false;
665
- if ( isset( $_POST['f'] ) ) {
666
- $file = ! empty( $_POST['f'] ) ? wp_unslash( $_POST['f'] ) : false;
667
- } elseif ( isset( $_POST['file'] ) ) {
668
- $file = ! empty( $_POST['file'] ) ? wp_unslash( $_POST['file'] ) : false;
669
- }
670
-
671
- $testFull = false;
672
- $file = $this->clone_backup_get_file( $file, $testFull );
673
- $cloneInstall = new MainWP_Clone_Install( $file );
674
- $cloneInstall->read_configuration_file();
675
-
676
- $plugins = get_option( 'mainwp_temp_clone_plugins' );
677
- $themes = get_option( 'mainwp_temp_clone_themes' );
678
-
679
- if ( $testFull ) {
680
- $cloneInstall->test_download();
681
- }
682
- $cloneInstall->remove_config_file();
683
- $cloneInstall->extract_backup();
684
-
685
- $pubkey = get_option( 'mainwp_child_pubkey' );
686
- $uniqueId = get_option( 'mainwp_child_uniqueId' );
687
- $server = get_option( 'mainwp_child_server' );
688
- $nonce = get_option( 'mainwp_child_nonce' );
689
- $nossl = get_option( 'mainwp_child_nossl' );
690
- $nossl_key = get_option( 'mainwp_child_nossl_key' );
691
- $sitesToClone = get_option( 'mainwp_child_clone_sites' );
692
-
693
- $cloneInstall->install();
694
-
695
- delete_option( 'mainwp_child_pubkey' );
696
- delete_option( 'mainwp_child_uniqueId' );
697
- delete_option( 'mainwp_child_server' );
698
- delete_option( 'mainwp_child_nonce' );
699
- delete_option( 'mainwp_child_nossl' );
700
- delete_option( 'mainwp_child_nossl_key' );
701
- delete_option( 'mainwp_child_clone_sites' );
702
-
703
- MainWP_Helper::update_option( 'mainwp_child_pubkey', $pubkey, 'yes' );
704
- MainWP_Helper::update_option( 'mainwp_child_uniqueId', $uniqueId );
705
- MainWP_Helper::update_option( 'mainwp_child_server', $server );
706
- MainWP_Helper::update_option( 'mainwp_child_nonce', $nonce );
707
- MainWP_Helper::update_option( 'mainwp_child_nossl', $nossl, 'yes' );
708
- MainWP_Helper::update_option( 'mainwp_child_nossl_key', $nossl_key );
709
- MainWP_Helper::update_option( 'mainwp_child_clone_sites', $sitesToClone );
710
- if ( ! MainWP_Helper::starts_with( basename( $file ), 'download-backup-' ) ) {
711
- MainWP_Helper::update_option( 'mainwp_child_restore_permalink', true, 'yes' );
712
- } else {
713
- MainWP_Helper::update_option( 'mainwp_child_clone_permalink', true, 'yes' );
714
- }
715
-
716
- $cloneInstall->update_wp_config();
717
- $cloneInstall->clean();
718
- $output = $this->clone_backup_delete_files( $plugins, $themes );
719
- } catch ( \Exception $e ) {
720
- $output = array( 'error' => $e->getMessage() );
721
- }
722
-
723
- die( wp_json_encode( $output ) );
724
- }
725
-
726
- /**
727
- * Method clone_backup_get_file()
728
- *
729
- * Get the backup file to download and clone.
730
- *
731
- * @param resource $file Backup file to be downloaded.
732
- * @param bool $testFull Return true if the file exists.
733
- *
734
- * @return resource Return the backup file.
735
- * @throws \Exception Error message.
736
- *
737
- * @uses \MainWP\Child\MainWP_Helper::get_mainwp_dir()
738
- */
739
- private function clone_backup_get_file( $file, &$testFull ) {
740
- if ( '' == $file ) {
741
- $dirs = MainWP_Helper::get_mainwp_dir( 'backup', false );
742
- $backupdir = $dirs[0];
743
- $files = glob( $backupdir . 'download-*' );
744
- $archiveFile = false;
745
- foreach ( $files as $file ) {
746
- if ( self::is_archive( $file, 'download-' ) ) {
747
- $archiveFile = $file;
748
- break;
749
- }
750
- }
751
- if ( false === $archiveFile ) {
752
- throw new \Exception( __( 'No download file found', 'mainwp-child' ) );
753
- }
754
- $file = $archiveFile;
755
- } elseif ( file_exists( $file ) ) {
756
- $testFull = true;
757
- } else {
758
- $file = ABSPATH . $file;
759
- if ( ! file_exists( $file ) ) {
760
- throw new \Exception( __( 'Backup file not found', 'mainwp-child' ) );
761
- }
762
- $testFull = true;
763
- }
764
- return $file;
765
- }
766
-
767
- /**
768
- * Method is_archive()
769
- *
770
- * Check if the file is archive file.
771
- *
772
- * @param string $file_name Contains the file name.
773
- * @param string $prefix Contains the prefix.
774
- * @param string $suffix Contains the sufix.
775
- *
776
- * @return bool true|false If the file is archive, return true, if not, return false.
777
- */
778
- public static function is_archive( $file_name, $prefix = '', $suffix = '' ) {
779
- return preg_match( '/' . $prefix . '(.*).(zip|tar|tar.gz|tar.bz2)' . $suffix . '$/', $file_name );
780
- }
781
-
782
- /**
783
- * Method clone_backup_delete_files()
784
- *
785
- * Delete unneeded files (plugins and themes).
786
- *
787
- * @param array $plugins Array containig plugins to be kept.
788
- * @param array $themes Array containig themes to be kept.
789
- *
790
- * @return array Array containing output feedback.
791
- *
792
- * @uses \MainWP\Child\MainWP_Helper::delete_dir()
793
- */
794
- private function clone_backup_delete_files( $plugins, $themes ) {
795
- if ( false !== $plugins ) {
796
- $out = array();
797
- if ( is_array( $plugins ) ) {
798
- $dir = WP_CONTENT_DIR . '/plugins/';
799
- $fh = opendir( $dir );
800
- while ( $entry = readdir( $fh ) ) {
801
- if ( ! is_dir( $dir . $entry ) ) {
802
- continue;
803
- }
804
- if ( ( '.' === $entry ) || ( '..' === $entry ) ) {
805
- continue;
806
- }
807
- if ( ! in_array( $entry, $plugins ) ) {
808
- MainWP_Helper::delete_dir( $dir . $entry );
809
- }
810
- }
811
- closedir( $fh );
812
- }
813
- delete_option( 'mainwp_temp_clone_plugins' );
814
- }
815
- if ( false !== $themes ) {
816
- $out = array();
817
- if ( is_array( $themes ) ) {
818
- $dir = WP_CONTENT_DIR . '/themes/';
819
- $fh = opendir( $dir );
820
- while ( $entry = readdir( $fh ) ) {
821
- if ( ! is_dir( $dir . $entry ) ) {
822
- continue;
823
- }
824
- if ( ( '.' === $entry ) || ( '..' === $entry ) ) {
825
- continue;
826
- }
827
- if ( ! in_array( $entry, $themes ) ) {
828
- MainWP_Helper::delete_dir( $dir . $entry );
829
- }
830
- }
831
- closedir( $fh );
832
- }
833
- delete_option( 'mainwp_temp_clone_themes' );
834
- }
835
- $output = array( 'result' => 'ok' );
836
- wp_logout();
837
- wp_set_current_user( 0 );
838
- return $output;
839
- }
840
-
841
- /**
842
- * Method permalink_changed()
843
- *
844
- * Check if the permalinks settings are re-saved.
845
- *
846
- * @param string $action Contains performed action.
847
- */
848
- public static function permalink_changed( $action ) {
849
- if ( 'update-permalink' === $action ) {
850
- if ( isset( $_POST['permalink_structure'] ) || isset( $_POST['category_base'] ) || isset( $_POST['tag_base'] ) ) {
851
- delete_option( 'mainwp_child_clone_permalink' );
852
- delete_option( 'mainwp_child_restore_permalink' );
853
- }
854
- }
855
- }
856
-
857
- }
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * MainWP MainWP_Clone
4
+ *
5
+ * Manage child site cloning process.
6
+ *
7
+ * @package MainWP\Child
8
+ */
9
+
10
+ namespace MainWP\Child;
11
+
12
+ /**
13
+ * Class MainWP_Clone
14
+ *
15
+ * Manage child site cloning process.
16
+ */
17
+ class MainWP_Clone {
18
+
19
+ /**
20
+ * Public static variable to hold the single instance of the class.
21
+ *
22
+ * @var mixed Default null
23
+ */
24
+ protected static $instance = null;
25
+
26
+ /**
27
+ * Protected variable to hold security nonces.
28
+ *
29
+ * @var array Security nonces.
30
+ */
31
+ protected $security_nonces;
32
+
33
+ /**
34
+ * Method get_class_name()
35
+ *
36
+ * Get class name.
37
+ *
38
+ * @return string __CLASS__ Class name.
39
+ */
40
+ public static function get_class_name() {
41
+ return __CLASS__;
42
+ }
43
+
44
+ /**
45
+ * Method instance()
46
+ *
47
+ * Create a public static instance.
48
+ *
49
+ * @return mixed Class instance.
50
+ */
51
+ public static function instance() {
52
+ if ( null === self::$instance ) {
53
+ self::$instance = new self();
54
+ }
55
+ return self::$instance;
56
+ }
57
+
58
+ /**
59
+ * Method init_ajax()
60
+ *
61
+ * Initiate AJAX requests.
62
+ */
63
+ public function init_ajax() {
64
+ $this->add_action( 'mainwp-child_clone_backupcreate', array( &$this, 'clone_backup_create' ) );
65
+ $this->add_action( 'mainwp-child_clone_backupcreatepoll', array( &$this, 'clone_backup_create_poll' ) );
66
+ $this->add_action( 'mainwp-child_clone_backupdownload', array( &$this, 'clone_backup_download' ) );
67
+ $this->add_action( 'mainwp-child_clone_backupdownloadpoll', array( &$this, 'clone_backup_download_poll' ) );
68
+ $this->add_action( 'mainwp-child_clone_backupextract', array( &$this, 'clone_backup_extract' ) );
69
+ }
70
+
71
+ /**
72
+ * Method add_security_nonce()
73
+ *
74
+ * Create security nonce for specific actions.
75
+ *
76
+ * @param string $action Contains the action that requires security nonce.
77
+ */
78
+ public function add_security_nonce( $action ) {
79
+ if ( ! is_array( $this->security_nonces ) ) {
80
+ $this->security_nonces = array();
81
+ }
82
+ if ( ! function_exists( 'wp_create_nonce' ) ) {
83
+ include_once ABSPATH . WPINC . '/pluggable.php';
84
+ }
85
+ $this->security_nonces[ $action ] = wp_create_nonce( $action );
86
+ }
87
+
88
+ /**
89
+ * Method get_security_nonces()
90
+ *
91
+ * Get security nonces from the security nonces array.
92
+ *
93
+ * @return array Security nonces.
94
+ */
95
+ public function get_security_nonces() {
96
+ return $this->security_nonces;
97
+ }
98
+
99
+ /**
100
+ * Method add_action()
101
+ *
102
+ * Add actions to the 'wp_ajax_' hook and create security nonce.
103
+ *
104
+ * @param string $action Contains action to be added to the 'wp_ajax_' hook.
105
+ * @param string $callback Contains a callback action.
106
+ */
107
+ public function add_action( $action, $callback ) {
108
+ add_action( 'wp_ajax_' . $action, $callback );
109
+ $this->add_security_nonce( $action );
110
+ }
111
+
112
+ /**
113
+ * Method secure_request()
114
+ *
115
+ * Build secure request for the clone process.
116
+ *
117
+ * @param string $action Contains the action that is being performed.
118
+ * @param string $query_arg Contains the query argument.
119
+ *
120
+ * @return void
121
+ *
122
+ * @uses \MainWP\Child\MainWP_Helper::is_admin()
123
+ * @uses \MainWP\Child\MainWP_Helper::update_option()
124
+ */
125
+ public function secure_request( $action = '', $query_arg = 'security' ) {
126
+ if ( ! MainWP_Helper::is_admin() ) {
127
+ die( 0 );
128
+ }
129
+
130
+ if ( '' == $action ) {
131
+ return;
132
+ }
133
+
134
+ if ( ! $this->check_security( $action, $query_arg ) ) {
135
+ die( wp_json_encode( array( 'error' => __( 'Invalid request!', 'mainwp-child' ) ) ) );
136
+ }
137
+
138
+ if ( isset( $_POST['dts'] ) ) {
139
+ $ajaxPosts = get_option( 'mainwp_ajaxposts' );
140
+ if ( ! is_array( $ajaxPosts ) ) {
141
+ $ajaxPosts = array();
142
+ }
143
+
144
+ // If already processed, just quit!
145
+ if ( isset( $ajaxPosts[ $action ] ) && ( $ajaxPosts[ $action ] == $_POST['dts'] ) ) {
146
+ die( wp_json_encode( array( 'error' => __( 'Double request!', 'mainwp-child' ) ) ) );
147
+ }
148
+
149
+ $ajaxPosts[ $action ] = isset( $_POST['dts'] ) ? sanitize_text_field( wp_unslash( $_POST['dts'] ) ) : '';
150
+ MainWP_Helper::update_option( 'mainwp_ajaxposts', $ajaxPosts );
151
+ }
152
+ }
153
+
154
+ /**
155
+ * Method check_security()
156
+ *
157
+ * Check the clone request security.
158
+ *
159
+ * @param string $action Contains the action that is being performed.
160
+ * @param string $query_arg Contains the query argument.
161
+ *
162
+ * @return bool true|false If secure, return true, if not, return false.
163
+ */
164
+ public function check_security( $action = - 1, $query_arg = 'security' ) {
165
+ if ( - 1 == $action ) {
166
+ return false;
167
+ }
168
+
169
+ $adminurl = strtolower( admin_url() );
170
+ $referer = strtolower( wp_get_referer() );
171
+ $result = isset( $_REQUEST[ $query_arg ] ) ? wp_verify_nonce( sanitize_text_field( wp_unslash( $_REQUEST[ $query_arg ] ) ), $action ) : false;
172
+ if ( ! $result && ! ( - 1 == $action && 0 === strpos( $referer, $adminurl ) ) ) {
173
+ return false;
174
+ }
175
+
176
+ return true;
177
+ }
178
+
179
+ /**
180
+ * Method init()
181
+ *
182
+ * Initiate action hooks.
183
+ *
184
+ * @uses \MainWP\Child\MainWP_Clone_Page::get_class_name()
185
+ */
186
+ public function init() {
187
+ add_action( 'check_admin_referer', array( self::get_class_name(), 'permalink_changed' ) );
188
+ if ( get_option( 'mainwp_child_clone_permalink' ) || get_option( 'mainwp_child_restore_permalink' ) ) {
189
+ add_action( 'admin_notices', array( MainWP_Clone_Page::get_class_name(), 'permalink_admin_notice' ) );
190
+ }
191
+ }
192
+
193
+ /**
194
+ * Method upload_mimes()
195
+ *
196
+ * Add allowed mime types and file extensions.
197
+ *
198
+ * @param array $mime_types Mime types keyed by the file extension regex corresponding to those types.
199
+ *
200
+ * @return array Array containing allowed mime types.
201
+ */
202
+ public static function upload_mimes( $mime_types = array() ) {
203
+ if ( ! isset( $mime_types['tar.bz2'] ) ) {
204
+ $mime_types['tar.bz2'] = 'application/x-tar';
205
+ }
206
+
207
+ return $mime_types;
208
+ }
209
+
210
+ /**
211
+ * Request clone.
212
+ *
213
+ * @return bool|void true|void.
214
+ *
215
+ * @uses \MainWP\Child\MainWP_Connect::is_valid_auth()
216
+ * @uses \MainWP\Child\MainWP_Helper::get_mainwp_dir()
217
+ * @uses \MainWP\Child\MainWP_Helper::write()
218
+ * @uses \MainWP\Child\MainWP_Utility::upload_file()
219
+ */
220
+ public function request_clone_funct() {
221
+
222
+ if ( ! isset( $_REQUEST['key'] ) ) {
223
+ return;
224
+ }
225
+ if ( ! isset( $_REQUEST['f'] ) || ( '' === $_REQUEST['f'] ) ) {
226
+ return;
227
+ }
228
+ if ( ! isset( $_REQUEST['key'] ) || ! MainWP_Connect::instance()->is_valid_auth( wp_unslash( $_REQUEST['key'] ) ) ) {
229
+ return;
230
+ }
231
+
232
+ $cloneFunc = isset( $_REQUEST['cloneFunc'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['cloneFunc'] ) ) : '';
233
+
234
+ if ( 'dl' === $cloneFunc ) {
235
+ $f = isset( $_REQUEST['f'] ) ? wp_unslash( $_REQUEST['f'] ) : '';
236
+ if ( ! empty( $f ) ) {
237
+ MainWP_Utility::instance()->upload_file( wp_unslash( $_REQUEST['f'] ) );
238
+ }
239
+ exit;
240
+ } elseif ( 'deleteCloneBackup' === $cloneFunc ) {
241
+ $df = isset( $_POST['f'] ) ? sanitize_text_field( wp_unslash( $_POST['f'] ) ) : '';
242
+ if ( empty( $df ) || stristr( $df, '..' ) ) {
243
+ return false;
244
+ }
245
+
246
+ $dirs = MainWP_Helper::get_mainwp_dir( 'backup' );
247
+ $backupdir = $dirs[0];
248
+ $result = glob( $backupdir . $df );
249
+ if ( 0 === count( $result ) ) {
250
+ return;
251
+ }
252
+
253
+ unlink( $result[0] );
254
+ MainWP_Helper::write( array( 'result' => 'ok' ) );
255
+ } elseif ( 'createCloneBackupPoll' === $cloneFunc ) {
256
+ $dirs = MainWP_Helper::get_mainwp_dir( 'backup' );
257
+ $backupdir = $dirs[0];
258
+ $f = isset( $_POST['f'] ) ? wp_unslash( $_POST['f'] ) : '';
259
+ $archiveFile = false;
260
+ if ( ! empty( $f ) ) {
261
+ $result = glob( $backupdir . 'backup-' . $f . '-*' );
262
+ foreach ( $result as $file ) {
263
+ if ( self::is_archive( $file, 'backup-' . $f . '-' ) ) {
264
+ $archiveFile = $file;
265
+ break;
266
+ }
267
+ }
268
+ }
269
+ if ( false === $archiveFile ) {
270
+ return;
271
+ }
272
+
273
+ MainWP_Helper::write( array( 'size' => filesize( $archiveFile ) ) );
274
+ } elseif ( 'createCloneBackup' === $cloneFunc ) {
275
+ $this->create_clone_backup();
276
+ }
277
+ return true;
278
+ }
279
+
280
+
281
+ /**
282
+ * Create backup of clone.
283
+ *
284
+ * @uses \MainWP\Child\MainWP_Backup::create_full_backup()
285
+ * @uses \MainWP\Child\MainWP_Helper::end_session()
286
+ * @uses \MainWP\Child\MainWP_Helper::is_dir_empty()
287
+ * @uses \MainWP\Child\MainWP_Helper::get_mainwp_dir()
288
+ * @uses \MainWP\Child\MainWP_Helper::write()
289
+ */
290
+ private function create_clone_backup() { // phpcs:ignore -- Current complexity is the only way to achieve desired results, pull request solutions appreciated.
291
+ MainWP_Helper::end_session();
292
+ $files = glob( WP_CONTENT_DIR . '/dbBackup*.sql' );
293
+ foreach ( $files as $file ) {
294
+ unlink( $file );
295
+ }
296
+ if ( file_exists( ABSPATH . 'clone/config.txt' ) ) {
297
+ unlink( ABSPATH . 'clone/config.txt' );
298
+ }
299
+ if ( MainWP_Helper::is_dir_empty( ABSPATH . 'clone' ) ) {
300
+ rmdir( ABSPATH . 'clone' );
301
+ }
302
+
303
+ $wpversion = isset( $_POST['wpversion'] ) ? sanitize_text_field( wp_unslash( $_POST['wpversion'] ) ) : '';
304
+ global $wp_version;
305
+ $includeCoreFiles = ( $wpversion !== $wp_version );
306
+ $excludes = ( isset( $_POST['exclude'] ) ? explode( ',', wp_unslash( $_POST['exclude'] ) ) : array() );
307
+ $excludes[] = str_replace( ABSPATH, '', WP_CONTENT_DIR ) . '/uploads/mainwp';
308
+ $uploadDir = MainWP_Helper::get_mainwp_dir();
309
+ $uploadDir = $uploadDir[0];
310
+ $excludes[] = str_replace( ABSPATH, '', $uploadDir );
311
+ $excludes[] = str_replace( ABSPATH, '', WP_CONTENT_DIR ) . '/object-cache.php';
312
+ if ( version_compare( phpversion(), '5.3.0' ) >= 0 || ! ini_get( 'safe_mode' ) ) {
313
+ set_time_limit( 6000 );
314
+ }
315
+
316
+ $newExcludes = array();
317
+ foreach ( $excludes as $exclude ) {
318
+ $newExcludes[] = rtrim( $exclude, '/' );
319
+ }
320
+
321
+ $method = ( ! isset( $_POST['zipmethod'] ) ? 'tar.gz' : wp_unslash( $_POST['zipmethod'] ) );
322
+ if ( 'tar.gz' === $method && ! function_exists( 'gzopen' ) ) {
323
+ $method = 'zip';
324
+ }
325
+
326
+ $file = false;
327
+ if ( isset( $_POST['f'] ) ) {
328
+ $file = ! empty( $_POST['f'] ) ? wp_unslash( $_POST['f'] ) : false;
329
+ } elseif ( isset( $_POST['file'] ) ) {
330
+ $file = ! empty( $_POST['file'] ) ? wp_unslash( $_POST['file'] ) : false;
331
+ }
332
+
333
+ $res = MainWP_Backup::get()->create_full_backup( $newExcludes, $file, true, $includeCoreFiles, 0, false, false, false, false, $method );
334
+ if ( ! $res ) {
335
+ $information['backup'] = false;
336
+ } else {
337
+ $information['backup'] = $res['file'];
338
+ $information['size'] = $res['filesize'];
339
+ }
340
+
341
+ $plugins = array();
342
+ $dir = WP_CONTENT_DIR . '/plugins/';
343
+ $fh = opendir( $dir );
344
+ while ( $entry = readdir( $fh ) ) {
345
+ if ( ! is_dir( $dir . $entry ) ) {
346
+ continue;
347
+ }
348
+ if ( ( '.' === $entry ) || ( '..' === $entry ) ) {
349
+ continue;
350
+ }
351
+ $plugins[] = $entry;
352
+ }
353
+ closedir( $fh );
354
+ $information['plugins'] = $plugins;
355
+
356
+ $themes = array();
357
+ $dir = WP_CONTENT_DIR . '/themes/';
358
+ $fh = opendir( $dir );
359
+ while ( $entry = readdir( $fh ) ) {
360
+ if ( ! is_dir( $dir . $entry ) ) {
361
+ continue;
362
+ }
363
+ if ( ( '.' === $entry ) || ( '..' === $entry ) ) {
364
+ continue;
365
+ }
366
+ $themes[] = $entry;
367
+ }
368
+ closedir( $fh );
369
+ $information['themes'] = $themes;
370
+ MainWP_Helper::write( $information );
371
+ }
372
+
373
+ /**
374
+ * Method clone_backup_create()
375
+ *
376
+ * Create backup of template site so it can be used to clone it.
377
+ *
378
+ * @throws \Exception Error message.
379
+ *
380
+ * @uses \MainWP\Child\MainWP_Helper::end_session()
381
+ * @uses \MainWP\Child\MainWP_Helper::update_option()
382
+ * @uses \MainWP\Child\MainWP_Utility::fetch_url()
383
+ */
384
+ public function clone_backup_create() {
385
+ try {
386
+ $this->secure_request( 'mainwp-child_clone_backupcreate' );
387
+
388
+ if ( ! isset( $_POST['siteId'] ) ) {
389
+ throw new \Exception( __( 'No site given', 'mainwp-child' ) );
390
+ }
391
+
392
+ $siteId = isset( $_POST['siteId'] ) ? intval( wp_unslash( $_POST['siteId'] ) ) : false;
393
+
394
+ $rand = isset( $_POST['rand'] ) ? sanitize_text_field( wp_unslash( $_POST['rand'] ) ) : '';
395
+ $sitesToClone = get_option( 'mainwp_child_clone_sites' );
396
+
397
+ if ( ! is_array( $sitesToClone ) || ! isset( $sitesToClone[ $siteId ] ) ) {
398
+ throw new \Exception( __( 'Site not found', 'mainwp-child' ) );
399
+ }
400
+
401
+ $siteToClone = $sitesToClone[ $siteId ];
402
+ $url = $siteToClone['url'];
403
+ $key = $siteToClone['extauth'];
404
+ $clone_admin = $siteToClone['connect_admin'];
405
+
406
+ MainWP_Helper::end_session();
407
+
408
+ // Send request to the childsite!
409
+
410
+ /**
411
+ * The installed version of WordPress.
412
+ *
413
+ * @global string $wp_version The installed version of WordPress.
414
+ */
415
+ global $wp_version;
416
+
417
+ $method = ( function_exists( 'gzopen' ) ? 'tar.gz' : 'zip' );
418
+ $result = MainWP_Utility::fetch_url(
419
+ $url,
420
+ array(
421
+ 'cloneFunc' => 'createCloneBackup',
422
+ 'key' => $key,
423
+ 'f' => $rand,
424
+ 'wpversion' => $wp_version,
425
+ 'zipmethod' => $method,
426
+ 'json_result' => true,
427
+ )
428
+ );
429
+
430
+ if ( ! $result['backup'] ) {
431
+ throw new \Exception( __( 'Could not create backupfile on child', 'mainwp-child' ) );
432
+ }
433
+ MainWP_Helper::update_option( 'mainwp_temp_clone_plugins', $result['plugins'] );
434
+ MainWP_Helper::update_option( 'mainwp_temp_clone_themes', $result['themes'] );
435
+ MainWP_Helper::update_option( 'mainwp_temp_clone_admin', $clone_admin );
436
+
437
+ $output = array(
438
+ 'url' => $result['backup'],
439
+ 'size' => round( $result['size'] / 1024, 0 ),
440
+ );
441
+ } catch ( \Exception $e ) {
442
+ $output = array( 'error' => $e->getMessage() );
443
+ }
444
+
445
+ die( wp_json_encode( $output ) );
446
+ }
447
+
448
+ /**
449
+ * Method clone_backup_create_poll()
450
+ *
451
+ * Create backup poll of template site so it can be used to clone it.
452
+ *
453
+ * @throws \Exception Error message.
454
+ *
455
+ * @uses \MainWP\Child\MainWP_Helper::end_session()
456
+ * @uses \MainWP\Child\MainWP_Utility::fetch_url()
457
+ */
458
+ public function clone_backup_create_poll() {
459
+ try {
460
+ $this->secure_request( 'mainwp-child_clone_backupcreatepoll' );
461
+
462
+ if ( ! isset( $_POST['siteId'] ) ) {
463
+ throw new \Exception( __( 'No site given', 'mainwp-child' ) );
464
+ }
465
+ $siteId = isset( $_POST['siteId'] ) ? sanitize_text_field( wp_unslash( $_POST['siteId'] ) ) : '';
466
+ $rand = isset( $_POST['rand'] ) ? sanitize_text_field( wp_unslash( $_POST['rand'] ) ) : '';
467
+
468
+ $sitesToClone = get_option( 'mainwp_child_clone_sites' );
469
+ if ( ! is_array( $sitesToClone ) || ! isset( $sitesToClone[ $siteId ] ) ) {
470
+ throw new \Exception( __( 'Site not found', 'mainwp-child' ) );
471
+ }
472
+
473
+ $siteToClone = $sitesToClone[ $siteId ];
474
+ $url = $siteToClone['url'];
475
+
476
+ $key = $siteToClone['extauth'];
477
+
478
+ MainWP_Helper::end_session();
479
+ // Send request to the childsite!
480
+ $result = MainWP_Utility::fetch_url(
481
+ $url,
482
+ array(
483
+ 'cloneFunc' => 'createCloneBackupPoll',
484
+ 'key' => $key,
485
+ 'f' => $rand,
486
+ 'json_result' => true,
487
+ )
488
+ );
489
+
490
+ if ( ! isset( $result['size'] ) ) {
491
+ throw new \Exception( __( 'Invalid response', 'mainwp-child' ) );
492
+ }
493
+
494
+ $output = array( 'size' => round( $result['size'] / 1024, 0 ) );
495
+ } catch ( \Exception $e ) {
496
+ $output = array( 'error' => $e->getMessage() );
497
+ }
498
+ die( wp_json_encode( $output ) );
499
+ }
500
+
501
+ /**
502
+ * Method clone_backup_download()
503
+ *
504
+ * Download backup file of template site so it can be used to clone it.
505
+ *
506
+ * @return mixed Response message.
507
+ * @throws \Exception Error message.
508
+ *
509
+ * @uses \MainWP\Child\MainWP_Helper::end_session()
510
+ * @uses \MainWP\Child\MainWP_Helper::get_mainwp_dir()
511
+ * @uses \MainWP\Child\MainWP_Utility::fetch_url()
512
+ */
513
+ public function clone_backup_download() {
514
+ try {
515
+ $this->secure_request( 'mainwp-child_clone_backupdownload' );
516
+
517
+ if ( ! isset( $_POST['file'] ) ) {
518
+ throw new \Exception( __( 'No download link given', 'mainwp-child' ) );
519
+ }
520
+
521
+ $file = isset( $_POST['file'] ) ? wp_unslash( $_POST['file'] ) : '';
522
+ if ( isset( $_POST['siteId'] ) ) {
523
+ $siteId = isset( $_POST['siteId'] ) ? intval( wp_unslash( $_POST['siteId'] ) ) : false;
524
+
525
+ $sitesToClone = get_option( 'mainwp_child_clone_sites' );
526
+
527
+ if ( ! is_array( $sitesToClone ) || ! isset( $sitesToClone[ $siteId ] ) ) {
528
+ throw new \Exception( __( 'Site not found', 'mainwp-child' ) );
529
+ }
530
+
531
+ $siteToClone = $sitesToClone[ $siteId ];
532
+ $url = $siteToClone['url'];
533
+ $key = $siteToClone['extauth'];
534
+
535
+ $url = trailingslashit( $url ) . '?cloneFunc=dl&key=' . rawurlencode( $key ) . '&f=' . $file;
536
+ } else {
537
+ $url = $file;
538
+ }
539
+ MainWP_Helper::end_session();
540
+ // Send request to the childsite!
541
+ $split = explode( '=', $file );
542
+ $file = urldecode( $split[ count( $split ) - 1 ] );
543
+ $filename = 'download-' . basename( $file );
544
+ $dirs = MainWP_Helper::get_mainwp_dir( 'backup', false );
545
+ $backupdir = $dirs[0];
546
+ $dh = opendir( $backupdir );
547
+ if ( $dh ) {
548
+ $fl = readdir( $dh );
549
+ while ( false !== $fl ) {
550
+ if ( '.' !== $fl && '..' !== $fl && self::is_archive( $fl, 'download-' ) ) {
551
+ unlink( $backupdir . $fl );
552
+ }
553
+ $fl = readdir( $dh );
554
+ }
555
+ closedir( $dh );
556
+ }
557
+
558
+ $filename = $backupdir . $filename;
559
+
560
+ $response = wp_remote_get(
561
+ $url,
562
+ array(
563
+ 'timeout' => 300000,
564
+ 'stream' => true,
565
+ 'filename' => $filename,
566
+ )
567
+ );
568
+
569
+ if ( is_wp_error( $response ) ) {
570
+ unlink( $filename );
571
+
572
+ return $response;
573
+ }
574
+
575
+ if ( 200 !== (int) wp_remote_retrieve_response_code( $response ) ) {
576
+ unlink( $filename );
577
+
578
+ return new \WP_Error( 'http_404', trim( wp_remote_retrieve_response_message( $response ) ) );
579
+ }
580
+
581
+ $output = array( 'done' => $filename );
582
+
583
+ // Delete backup on child.
584
+ try {
585
+ if ( isset( $_POST['siteId'] ) ) {
586
+ $siteId = isset( $_POST['siteId'] ) ? intval( wp_unslash( $_POST['siteId'] ) ) : false;
587
+
588
+ $sitesToClone = get_option( 'mainwp_child_clone_sites' );
589
+ if ( is_array( $sitesToClone ) && isset( $sitesToClone[ $siteId ] ) ) {
590
+ $siteToClone = $sitesToClone[ $siteId ];
591
+
592
+ MainWP_Utility::fetch_url(
593
+ $siteToClone['url'],
594
+ array(
595
+ 'cloneFunc' => 'deleteCloneBackup',
596
+ 'key' => $siteToClone['extauth'],
597
+ 'f' => $file,
598
+ 'json_result' => true,
599
+ )
600
+ );
601
+ }
602
+ }
603
+ } catch ( \Exception $e ) {
604
+ throw $e;
605
+ }
606
+ } catch ( \Exception $e ) {
607
+ $output = array( 'error' => $e->getMessage() );
608
+ }
609
+
610
+ die( wp_json_encode( $output ) );
611
+ }
612
+
613
+ /**
614
+ * Method clone_backup_download_poll()
615
+ *
616
+ * Download backup file poll of template site so it can be used to clone it.
617
+ *
618
+ * @throws \Exception Error message.
619
+ *
620
+ * @uses \MainWP\Child\MainWP_Helper::end_session()
621
+ * @uses \MainWP\Child\MainWP_Helper::get_mainwp_dir()
622
+ */
623
+ public function clone_backup_download_poll() {
624
+ try {
625
+ $this->secure_request( 'mainwp-child_clone_backupdownloadpoll' );
626
+
627
+ MainWP_Helper::end_session();
628
+
629
+ $dirs = MainWP_Helper::get_mainwp_dir( 'backup', false );
630
+ $backupdir = $dirs[0];
631
+ $files = glob( $backupdir . 'download-*' );
632
+ $archiveFile = false;
633
+
634
+ foreach ( $files as $file ) {
635
+ if ( self::is_archive( $file, 'download-' ) ) {
636
+ $archiveFile = $file;
637
+ break;
638
+ }
639
+ }
640
+ if ( false === $archiveFile ) {
641
+ throw new \Exception( __( 'No download file found', 'mainwp-child' ) );
642
+ }
643
+ $output = array( 'size' => filesize( $archiveFile ) / 1024 );
644
+ } catch ( \Exception $e ) {
645
+ $output = array( 'error' => $e->getMessage() );
646
+ }
647
+ die( wp_json_encode( $output ) );
648
+ }
649
+
650
+ /**
651
+ * Method clone_backup_extract()
652
+ *
653
+ * Extract the backup archive to clone the site.
654
+ *
655
+ * @uses \MainWP\Child\MainWP_Clone_Install()
656
+ * @uses \MainWP\Child\MainWP_Helper::end_session()
657
+ * @uses \MainWP\Child\MainWP_Helper::update_option()
658
+ * @uses \MainWP\Child\MainWP_Helper::starts_with()
659
+ */
660
+ public function clone_backup_extract() {
661
+ try {
662
+ $this->secure_request( 'mainwp-child_clone_backupextract' );
663
+
664
+ MainWP_Helper::end_session();
665
+
666
+ $file = false;
667
+ if ( isset( $_POST['f'] ) ) {
668
+ $file = ! empty( $_POST['f'] ) ? wp_unslash( $_POST['f'] ) : false;
669
+ } elseif ( isset( $_POST['file'] ) ) {
670
+ $file = ! empty( $_POST['file'] ) ? wp_unslash( $_POST['file'] ) : false;
671
+ }
672
+
673
+ $testFull = false;
674
+ $file = $this->clone_backup_get_file( $file, $testFull );
675
+ $cloneInstall = new MainWP_Clone_Install( $file );
676
+ $cloneInstall->read_configuration_file();
677
+
678
+ $plugins = get_option( 'mainwp_temp_clone_plugins' );
679
+ $themes = get_option( 'mainwp_temp_clone_themes' );
680
+ $clone_admin = get_option( 'mainwp_temp_clone_admin' );
681
+
682
+ if ( $testFull ) {
683
+ $cloneInstall->test_download();
684
+ }
685
+ $cloneInstall->remove_config_file();
686
+ $cloneInstall->extract_backup();
687
+
688
+ $pubkey = get_option( 'mainwp_child_pubkey' );
689
+ $uniqueId = get_option( 'mainwp_child_uniqueId' );
690
+ $server = get_option( 'mainwp_child_server' );
691
+ $nonce = get_option( 'mainwp_child_nonce' );
692
+ $nossl = get_option( 'mainwp_child_nossl' );
693
+ $nossl_key = get_option( 'mainwp_child_nossl_key' );
694
+ $sitesToClone = get_option( 'mainwp_child_clone_sites' );
695
+
696
+ $cloneInstall->install();
697
+
698
+ delete_option( 'mainwp_child_pubkey' );
699
+ delete_option( 'mainwp_child_uniqueId' );
700
+ delete_option( 'mainwp_child_server' );
701
+ delete_option( 'mainwp_child_nonce' );
702
+ delete_option( 'mainwp_child_nossl' );
703
+ delete_option( 'mainwp_child_nossl_key' );
704
+ delete_option( 'mainwp_child_clone_sites' );
705
+ delete_option( 'mainwp_temp_clone_admin' );
706
+
707
+ MainWP_Helper::update_option( 'mainwp_child_pubkey', $pubkey, 'yes' );
708
+ MainWP_Helper::update_option( 'mainwp_child_uniqueId', $uniqueId );
709
+ MainWP_Helper::update_option( 'mainwp_child_server', $server );
710
+ MainWP_Helper::update_option( 'mainwp_child_nonce', $nonce );
711
+ MainWP_Helper::update_option( 'mainwp_child_nossl', $nossl, 'yes' );
712
+ MainWP_Helper::update_option( 'mainwp_child_nossl_key', $nossl_key );
713
+ MainWP_Helper::update_option( 'mainwp_child_clone_sites', $sitesToClone );
714
+ MainWP_Helper::update_option( 'mainwp_child_just_clone_admin', $clone_admin );
715
+
716
+ if ( ! MainWP_Helper::starts_with( basename( $file ), 'download-backup-' ) ) {
717
+ MainWP_Helper::update_option( 'mainwp_child_restore_permalink', true, 'yes' );
718
+ } else {
719
+ MainWP_Helper::update_option( 'mainwp_child_clone_permalink', true, 'yes' );
720
+ }
721
+
722
+ $cloneInstall->update_wp_config();
723
+ $cloneInstall->clean();
724
+ $output = $this->clone_backup_delete_files( $plugins, $themes );
725
+ } catch ( \Exception $e ) {
726
+ $output = array( 'error' => $e->getMessage() );
727
+ }
728
+
729
+ die( wp_json_encode( $output ) );
730
+ }
731
+
732
+ /**
733
+ * Method clone_backup_get_file()
734
+ *
735
+ * Get the backup file to download and clone.
736
+ *
737
+ * @param resource $file Backup file to be downloaded.
738
+ * @param bool $testFull Return true if the file exists.
739
+ *
740
+ * @return resource Return the backup file.
741
+ * @throws \Exception Error message.
742
+ *
743
+ * @uses \MainWP\Child\MainWP_Helper::get_mainwp_dir()
744
+ */
745
+ private function clone_backup_get_file( $file, &$testFull ) {
746
+ if ( '' == $file ) {
747
+ $dirs = MainWP_Helper::get_mainwp_dir( 'backup', false );
748
+ $backupdir = $dirs[0];
749
+ $files = glob( $backupdir . 'download-*' );
750
+ $archiveFile = false;
751
+ foreach ( $files as $file ) {
752
+ if ( self::is_archive( $file, 'download-' ) ) {
753
+ $archiveFile = $file;
754
+ break;
755
+ }
756
+ }
757
+ if ( false === $archiveFile ) {
758
+ throw new \Exception( __( 'No download file found', 'mainwp-child' ) );
759
+ }
760
+ $file = $archiveFile;
761
+ } elseif ( file_exists( $file ) ) {
762
+ $testFull = true;
763
+ } else {
764
+ $file = ABSPATH . $file;
765
+ if ( ! file_exists( $file ) ) {
766
+ throw new \Exception( __( 'Backup file not found', 'mainwp-child' ) );
767
+ }
768
+ $testFull = true;
769
+ }
770
+ return $file;
771
+ }
772
+
773
+ /**
774
+ * Method is_archive()
775
+ *
776
+ * Check if the file is archive file.
777
+ *
778
+ * @param string $file_name Contains the file name.
779
+ * @param string $prefix Contains the prefix.
780
+ * @param string $suffix Contains the sufix.
781
+ *
782
+ * @return bool true|false If the file is archive, return true, if not, return false.
783
+ */
784
+ public static function is_archive( $file_name, $prefix = '', $suffix = '' ) {
785
+ return preg_match( '/' . $prefix . '(.*).(zip|tar|tar.gz|tar.bz2)' . $suffix . '$/', $file_name );
786
+ }
787
+
788
+ /**
789
+ * Method clone_backup_delete_files()
790
+ *
791
+ * Delete unneeded files (plugins and themes).
792
+ *
793
+ * @param array $plugins Array containig plugins to be kept.
794
+ * @param array $themes Array containig themes to be kept.
795
+ *
796
+ * @return array Array containing output feedback.
797
+ *
798
+ * @uses \MainWP\Child\MainWP_Helper::delete_dir()
799
+ */
800
+ private function clone_backup_delete_files( $plugins, $themes ) {
801
+ if ( false !== $plugins ) {
802
+ $out = array();
803
+ if ( is_array( $plugins ) ) {
804
+ $dir = WP_CONTENT_DIR . '/plugins/';
805
+ $fh = opendir( $dir );
806
+ while ( $entry = readdir( $fh ) ) {
807
+ if ( ! is_dir( $dir . $entry ) ) {
808
+ continue;
809
+ }
810
+ if ( ( '.' === $entry ) || ( '..' === $entry ) ) {
811
+ continue;
812
+ }
813
+ if ( ! in_array( $entry, $plugins ) ) {
814
+ MainWP_Helper::delete_dir( $dir . $entry );
815
+ }
816
+ }
817
+ closedir( $fh );
818
+ }
819
+ delete_option( 'mainwp_temp_clone_plugins' );
820
+ }
821
+ if ( false !== $themes ) {
822
+ $out = array();
823
+ if ( is_array( $themes ) ) {
824
+ $dir = WP_CONTENT_DIR . '/themes/';
825
+ $fh = opendir( $dir );
826
+ while ( $entry = readdir( $fh ) ) {
827
+ if ( ! is_dir( $dir . $entry ) ) {
828
+ continue;
829
+ }
830
+ if ( ( '.' === $entry ) || ( '..' === $entry ) ) {
831
+ continue;
832
+ }
833
+ if ( ! in_array( $entry, $themes ) ) {
834
+ MainWP_Helper::delete_dir( $dir . $entry );
835
+ }
836
+ }
837
+ closedir( $fh );
838
+ }
839
+ delete_option( 'mainwp_temp_clone_themes' );
840
+ }
841
+ $output = array( 'result' => 'ok' );
842
+ wp_logout();
843
+ wp_set_current_user( 0 );
844
+ return $output;
845
+ }
846
+
847
+ /**
848
+ * Method permalink_changed()
849
+ *
850
+ * Check if the permalinks settings are re-saved.
851
+ *
852
+ * @param string $action Contains performed action.
853
+ */
854
+ public static function permalink_changed( $action ) {
855
+ if ( 'update-permalink' === $action ) {
856
+ if ( isset( $_POST['permalink_structure'] ) || isset( $_POST['category_base'] ) || isset( $_POST['tag_base'] ) ) {
857
+ delete_option( 'mainwp_child_clone_permalink' );
858
+ delete_option( 'mainwp_child_restore_permalink' );
859
+ }
860
+ }
861
+ }
862
+
863
+ }
class/class-mainwp-connect.php CHANGED
@@ -161,7 +161,7 @@ class MainWP_Connect {
161
  * @uses \MainWP\Child\MainWP_Child_Callable::is_callable_function_no_auth()
162
  * @uses \MainWP\Child\MainWP_Helper::instance()->error()
163
  */
164
- public function parse_init_auth( $auth = false ) {
165
 
166
  if ( ! $auth && isset( $_POST['mainwpsignature'] ) ) { // with 'mainwpsignature' then need to callable functions.
167
  MainWP_Helper::instance()->error( __( 'Authentication failed! Please deactivate & re-activate the MainWP Child plugin on this site and try again.', 'mainwp-child' ) );
@@ -192,6 +192,17 @@ class MainWP_Connect {
192
  }
193
  }
194
 
 
 
 
 
 
 
 
 
 
 
 
195
  // if alternative admin not existed.
196
  if ( ! $user ) {
197
  // check connected admin existed.
@@ -209,7 +220,15 @@ class MainWP_Connect {
209
  }
210
 
211
  // try to login.
212
- $this->login( $auth_user );
 
 
 
 
 
 
 
 
213
  }
214
 
215
  if ( isset( $_POST['function'] ) && 'visitPermalink' === $_POST['function'] ) {
161
  * @uses \MainWP\Child\MainWP_Child_Callable::is_callable_function_no_auth()
162
  * @uses \MainWP\Child\MainWP_Helper::instance()->error()
163
  */
164
+ public function parse_init_auth( $auth = false ) { // phpcs:ignore -- Current complexity is the only way to achieve desired results, pull request solutions appreciated.
165
 
166
  if ( ! $auth && isset( $_POST['mainwpsignature'] ) ) { // with 'mainwpsignature' then need to callable functions.
167
  MainWP_Helper::instance()->error( __( 'Authentication failed! Please deactivate & re-activate the MainWP Child plugin on this site and try again.', 'mainwp-child' ) );
192
  }
193
  }
194
 
195
+ // check just clone admin here.
196
+ $just_clone_admin = get_option( 'mainwp_child_just_clone_admin' );
197
+ $clone_sync = false;
198
+ if ( ! empty( $just_clone_admin ) ) {
199
+ delete_option( 'mainwp_child_just_clone_admin' );
200
+ if ( $username != $just_clone_admin ) {
201
+ $username = $just_clone_admin;
202
+ $clone_sync = true;
203
+ }
204
+ }
205
+
206
  // if alternative admin not existed.
207
  if ( ! $user ) {
208
  // check connected admin existed.
220
  }
221
 
222
  // try to login.
223
+ $logged_in = $this->login( $auth_user );
224
+
225
+ // authed.
226
+ if ( $clone_sync && $logged_in ) {
227
+ $information = array();
228
+ $information['sync'] = MainWP_Child_Stats::get_instance()->get_site_stats( array(), false );
229
+ $information['sync']['clone_adminname'] = $just_clone_admin;
230
+ MainWP_Helper::write( $information ); // forced exit to sync clone admin.
231
+ }
232
  }
233
 
234
  if ( isset( $_POST['function'] ) && 'visitPermalink' === $_POST['function'] ) {
mainwp-child.php CHANGED
@@ -12,7 +12,7 @@
12
  * Author: MainWP
13
  * Author URI: https://mainwp.com
14
  * Text Domain: mainwp-child
15
- * Version: 4.1.6.1
16
  * Requires at least: 5.4
17
  * Requires PHP: 7.0
18
  */
12
  * Author: MainWP
13
  * Author URI: https://mainwp.com
14
  * Text Domain: mainwp-child
15
+ * Version: 4.1.7
16
  * Requires at least: 5.4
17
  * Requires PHP: 7.0
18
  */
readme.txt CHANGED
@@ -5,9 +5,9 @@ Author: mainwp
5
  Author URI: https://mainwp.com
6
  Plugin URI: https://mainwp.com
7
  Requires at least: 5.4
8
- Tested up to: 5.7.1
9
  Requires PHP: 7.0
10
- Stable tag: 4.1.6.1
11
  License: GPLv3 or later
12
  License URI: https://www.gnu.org/licenses/gpl-3.0.html
13
 
@@ -107,6 +107,9 @@ Sure we have a quick FAQ with a lot more questions and answers [here](https://ma
107
 
108
  == Changelog ==
109
 
 
 
 
110
  = 4.1.6.1 - 4-16-21 =
111
  * Fixed: An issue with disconnecting sites
112
  * Fixed: An issue with applying custom branding
5
  Author URI: https://mainwp.com
6
  Plugin URI: https://mainwp.com
7
  Requires at least: 5.4
8
+ Tested up to: 5.8
9
  Requires PHP: 7.0
10
+ Stable tag: 4.1.7
11
  License: GPLv3 or later
12
  License URI: https://www.gnu.org/licenses/gpl-3.0.html
13
 
107
 
108
  == Changelog ==
109
 
110
+ = 4.1.7 - 6-29-21 =
111
+ * Added: Support for the new Vulnerability Checker API
112
+
113
  = 4.1.6.1 - 4-16-21 =
114
  * Fixed: An issue with disconnecting sites
115
  * Fixed: An issue with applying custom branding