MainWP Child - Version 4.3

Version Description

  • 11-16-2022 =
  • Fixed: Multiple PHP warnings
  • Added: Support for new security checks
  • Added: Support for the Non-MainWP Changes feature
  • Removed: Unused code
Download this release

Release Info

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

Code changes from version 4.2.6 to 4.3

class/class-mainwp-child-actions.php ADDED
@@ -0,0 +1,897 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * MainWP Child Actions.
4
+ *
5
+ * Handle MainWP Child Actions.
6
+ *
7
+ * @package MainWP\Child
8
+ */
9
+
10
+ namespace MainWP\Child;
11
+
12
+ /**
13
+ * Class MainWP_Child_Actions
14
+ *
15
+ * Handle MainWP Child Actions.
16
+ */
17
+ class MainWP_Child_Actions {
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
+ * Public static variable.
28
+ *
29
+ * @var mixed Default null
30
+ */
31
+ protected static $actions_data = null;
32
+
33
+ /**
34
+ * Public static variable.
35
+ *
36
+ * @var mixed Default null
37
+ */
38
+ protected static $sending = null;
39
+
40
+ /**
41
+ * Public static variable.
42
+ *
43
+ * @var mixed Default null.
44
+ */
45
+ protected static $connected_admin = null;
46
+
47
+ /**
48
+ * Public static variable.
49
+ *
50
+ * @var mixed Default null.
51
+ */
52
+ protected static $enable_actions_notification = null;
53
+
54
+ /**
55
+ * Old plugins.
56
+ *
57
+ * @var array Old plugins array.
58
+ * */
59
+ private $current_plugins_info = array();
60
+
61
+ /**
62
+ * Method get_class_name()
63
+ *
64
+ * Get class name.
65
+ *
66
+ * @return string __CLASS__ Class name.
67
+ */
68
+ public static function get_class_name() {
69
+ return __CLASS__;
70
+ }
71
+
72
+ /**
73
+ * MainWP_Child_Callable constructor.
74
+ *
75
+ * Run any time class is called.
76
+ */
77
+ public function __construct() {
78
+ self::$connected_admin = get_option( 'mainwp_child_connected_admin', '' );
79
+ self::$enable_actions_notification = (int) get_option( 'mainwp_child_actions_notification_enable', 0 );
80
+ }
81
+
82
+ /**
83
+ * Method instance()
84
+ *
85
+ * Create a public static instance.
86
+ *
87
+ * @return mixed Class instance.
88
+ */
89
+ public static function get_instance() {
90
+ if ( null === self::$instance ) {
91
+ self::$instance = new self();
92
+ self::get_actions_data();
93
+ }
94
+ return self::$instance;
95
+ }
96
+
97
+ /**
98
+ * Method init_hooks().
99
+ *
100
+ * Init WP hooks.
101
+ */
102
+ public function init_hooks() {
103
+
104
+ // avoid actions.
105
+ if ( isset( $_POST['mainwpsignature'] ) ) {
106
+ return;
107
+ }
108
+
109
+ // not connected, avoid actions.
110
+ if ( empty( self::$connected_admin ) ) {
111
+ return;
112
+ }
113
+
114
+ $pubkey = get_option( 'mainwp_child_pubkey' );
115
+ // not connected, avoid actions.
116
+ if ( empty( $pubkey ) ) {
117
+ return;
118
+ }
119
+
120
+ $actions = array(
121
+ 'upgrader_pre_install',
122
+ 'upgrader_process_complete',
123
+ 'activate_plugin',
124
+ 'deactivate_plugin',
125
+ 'switch_theme',
126
+ 'delete_site_transient_update_themes',
127
+ 'pre_option_uninstall_plugins',
128
+ 'deleted_plugin',
129
+ '_core_updated_successfully',
130
+ );
131
+
132
+ foreach ( $actions as $action ) {
133
+ add_action( $action, array( $this, 'callback' ), 10, 99 );
134
+ }
135
+ if ( 1 === self::$enable_actions_notification ) {
136
+ self::$enable_actions_notification = 0; // to do.
137
+ }
138
+ }
139
+
140
+ /**
141
+ * Callback for all registered hooks.
142
+ * Looks for a class method with the convention: "callback_{action name}"
143
+ */
144
+ public function callback() {
145
+ $current = current_filter();
146
+ $callback = array( $this, 'callback_' . preg_replace( '/[^A-Za-z0-9_\-]/', '_', $current ) ); // to fix A-Z charater in callback name.
147
+
148
+ // Call the real function.
149
+ if ( is_callable( $callback ) ) {
150
+ return call_user_func_array( $callback, func_get_args() );
151
+ }
152
+ }
153
+
154
+ /**
155
+ * Method to get actions info.
156
+ */
157
+ private function check_to_send_actions_notification() {
158
+ $nexttime_send = (int) get_option( 'mainwp_child_send_action_notification_next_time', 0 );
159
+ if ( ! empty( $nexttime_send ) && $nexttime_send < time() ) {
160
+ $actions_data = get_option( 'mainwp_child_actions_saved_data', array() );
161
+ if ( ! empty( $actions_data ) ) {
162
+ $this->send_actions_notification( $actions_data );
163
+ }
164
+ delete_option( 'mainwp_child_send_action_notification_next_time' );
165
+ }
166
+ }
167
+
168
+ /**
169
+ * Method to get actions info.
170
+ */
171
+ public static function get_actions_data() {
172
+ if ( null === self::$actions_data ) {
173
+ self::$actions_data = get_option( 'mainwp_child_actions_saved_data', array() );
174
+ if ( ! is_array( self::$actions_data ) ) {
175
+ self::$actions_data = array();
176
+ }
177
+ $username = get_option( 'mainwp_child_connected_admin', '' );
178
+ if ( ! isset( self::$actions_data['connected_admin'] ) ) {
179
+ self::$actions_data['connected_admin'] = $username;
180
+ } elseif ( '' != $username && $username != self::$actions_data['connected_admin'] ) {
181
+ self::$actions_data = array( 'connected_admin' => $username ); // if it is not same the connected user then clear the actions data.
182
+ update_option( 'mainwp_child_actions_saved_data', self::$actions_data );
183
+ delete_option( 'mainwp_child_send_action_notification_next_time' );
184
+ }
185
+ self::check_actions_data();
186
+ }
187
+ return self::$actions_data;
188
+ }
189
+
190
+
191
+ /**
192
+ * Method to save actions info.
193
+ *
194
+ * @param int $index index.
195
+ * @param array $data Action data .
196
+ *
197
+ * @return bool Return TRUE.
198
+ */
199
+ private function update_actions_data( $index, $data ) {
200
+ $index = strval( $index );
201
+ self::$actions_data[ $index ] = $data;
202
+ update_option( 'mainwp_child_actions_saved_data', self::$actions_data );
203
+ return true;
204
+ }
205
+
206
+
207
+ /**
208
+ * Method to check actions data.
209
+ * Clear old the action info.
210
+ */
211
+ public static function check_actions_data() {
212
+ $checked = intval( get_option( 'mainwp_child_actions_data_checked', 0 ) );
213
+ if ( empty( $checked ) ) {
214
+ update_option( 'mainwp_child_actions_data_checked', time() );
215
+ } else {
216
+ $checked = date( 'Y-m-d', $checked ); // phpcs:ignore -- Use local time to achieve desired results, pull request solutions appreciated.
217
+ if ( $checked != date( 'Y-m-d' ) ) { // phpcs:ignore -- Use local time to achieve desired results, pull request solutions appreciated.
218
+ $days_number = intval( get_option( 'mainwp_child_actions_saved_number_of_days', 30 ) );
219
+ $days_number = apply_filters( 'mainwp_child_actions_saved_number_of_days', $days_number );
220
+ $days_number = ( 3 > $days_number || 6 * 30 < $days_number ) ? 30 : $days_number;
221
+ $check_time = $days_number * \DAY_IN_SECONDS;
222
+
223
+ $updated = false;
224
+ foreach ( self::$actions_data as $index => $data ) {
225
+
226
+ if ( 'connected_admin' === strval( $index ) ) {
227
+ continue;
228
+ }
229
+
230
+ if ( ! is_array( $data ) || $check_time < time() - intval( $data['created'] ) || empty( $data['action_user'] ) ) {
231
+ unset( self::$actions_data[ $index ] );
232
+ $updated = true;
233
+ }
234
+ }
235
+
236
+ if ( $updated ) {
237
+ update_option( 'mainwp_child_actions_saved_data', self::$actions_data );
238
+ }
239
+ update_option( 'mainwp_child_actions_data_checked', time() );
240
+ }
241
+ }
242
+ }
243
+
244
+ /**
245
+ * Log plugin installations.
246
+ *
247
+ * @action transition_post_status.
248
+ *
249
+ * @param \WP_Upgrader $upgrader WP_Upgrader class object.
250
+ * @param array $extra Extra attributes array.
251
+ *
252
+ * @return bool Return TRUE|FALSE.
253
+ */
254
+ public function callback_upgrader_process_complete( $upgrader, $extra ) { // phpcs:ignore -- required to achieve desired results, pull request solutions appreciated.
255
+ $logs = array();
256
+ $success = ! is_wp_error( $upgrader->skin->result );
257
+ $error = null;
258
+
259
+ if ( ! $success ) {
260
+ $errors = $upgrader->skin->result->errors;
261
+
262
+ list( $error ) = reset( $errors );
263
+ }
264
+
265
+ // This would have failed down the road anyway.
266
+ if ( ! isset( $extra['type'] ) ) {
267
+ return false;
268
+ }
269
+
270
+ $type = $extra['type'];
271
+ $action = $extra['action'];
272
+
273
+ if ( ! in_array( $type, array( 'plugin', 'theme' ), true ) ) {
274
+ return false;
275
+ }
276
+
277
+ if ( 'install' === $action ) {
278
+ if ( 'plugin' === $type ) {
279
+ $path = $upgrader->plugin_info();
280
+
281
+ if ( ! $path ) {
282
+ return false;
283
+ }
284
+
285
+ $data = get_plugin_data( $upgrader->skin->result['local_destination'] . '/' . $path );
286
+ $slug = $upgrader->result['destination_name'];
287
+ $name = $data['Name'];
288
+ $version = $data['Version'];
289
+ } else { // theme.
290
+ $slug = $upgrader->theme_info();
291
+
292
+ if ( ! $slug ) {
293
+ return false;
294
+ }
295
+
296
+ wp_clean_themes_cache();
297
+
298
+ $theme = wp_get_theme( $slug );
299
+ $name = $theme->name;
300
+ $version = $theme->version;
301
+ }
302
+
303
+ $action = 'installed';
304
+ // translators: Placeholders refer to a plugin/theme type, a plugin/theme name, and a plugin/theme version (e.g. "plugin", "Stream", "4.2").
305
+ $message = _x(
306
+ 'Installed %1$s: %2$s %3$s',
307
+ 'Plugin/theme installation. 1: Type (plugin/theme), 2: Plugin/theme name, 3: Plugin/theme version',
308
+ 'mainwp-child'
309
+ );
310
+
311
+ $logs[] = compact( 'slug', 'name', 'version', 'message', 'action' );
312
+ } elseif ( 'update' === $action ) {
313
+
314
+ if ( is_object( $upgrader ) && property_exists( $upgrader, 'skin' ) && 'Automatic_Upgrader_Skin' == get_class( $upgrader->skin ) ) {
315
+ return false;
316
+ }
317
+
318
+ $action = 'updated';
319
+ // translators: Placeholders refer to a plugin/theme type, a plugin/theme name, and a plugin/theme version (e.g. "plugin", "Stream", "4.2").
320
+ $message = _x(
321
+ 'Updated %1$s: %2$s %3$s',
322
+ 'Plugin/theme update. 1: Type (plugin/theme), 2: Plugin/theme name, 3: Plugin/theme version',
323
+ 'mainwp-child'
324
+ );
325
+
326
+ if ( 'plugin' === $type ) {
327
+ if ( isset( $extra['bulk'] ) && true === $extra['bulk'] ) {
328
+ $slugs = $extra['plugins'];
329
+ } else {
330
+ $slugs = array( $upgrader->skin->plugin );
331
+ }
332
+
333
+ foreach ( $slugs as $slug ) {
334
+ $plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $slug );
335
+ $name = $plugin_data['Name'];
336
+ $version = $plugin_data['Version'];
337
+ // ( Net-Concept - Xavier NUEL ) : get old versions.
338
+ if ( isset( $this->current_plugins_info[ $slug ] ) ) {
339
+ $old_version = $this->current_plugins_info[ $slug ]['Version'];
340
+ } else {
341
+ $old_version = $upgrader->skin->plugin_info['Version']; // to fix old version.
342
+ }
343
+
344
+ if ( version_compare( $version, $old_version, '>' ) ) {
345
+ $logs[] = compact( 'slug', 'name', 'old_version', 'version', 'message', 'action' );
346
+ }
347
+ }
348
+ } else { // theme.
349
+ if ( isset( $extra['bulk'] ) && true === $extra['bulk'] ) {
350
+ $slugs = $extra['themes'];
351
+ } else {
352
+ $slugs = array( $upgrader->skin->theme );
353
+ }
354
+
355
+ foreach ( $slugs as $slug ) {
356
+ $theme = wp_get_theme( $slug );
357
+ $stylesheet = $theme['Stylesheet Dir'] . '/style.css';
358
+ $theme_data = get_file_data(
359
+ $stylesheet,
360
+ array(
361
+ 'Version' => 'Version',
362
+ )
363
+ );
364
+ $name = $theme['Name'];
365
+ $old_version = $upgrader->skin->theme_info->get( 'Version' ); // to fix old version //$theme['Version'].
366
+ $version = $theme_data['Version'];
367
+
368
+ $logs[] = compact( 'slug', 'name', 'old_version', 'version', 'message', 'action' );
369
+ }
370
+ }
371
+ } else {
372
+ return false;
373
+ }
374
+
375
+ $context = $type . 's';
376
+
377
+ foreach ( $logs as $log ) {
378
+ $name = isset( $log['name'] ) ? $log['name'] : null;
379
+ $version = isset( $log['version'] ) ? $log['version'] : null;
380
+ $slug = isset( $log['slug'] ) ? $log['slug'] : null;
381
+ $old_version = isset( $log['old_version'] ) ? $log['old_version'] : null;
382
+ $message = isset( $log['message'] ) ? $log['message'] : null;
383
+ $action = isset( $log['action'] ) ? $log['action'] : null;
384
+
385
+ $this->save_actions(
386
+ $message,
387
+ compact( 'type', 'name', 'version', 'slug', 'success', 'error', 'old_version' ),
388
+ $context,
389
+ $action
390
+ );
391
+ }
392
+ return true;
393
+ }
394
+
395
+
396
+ /**
397
+ * Activate plugin callback.
398
+ *
399
+ * @param string $slug Plugin slug.
400
+ * @param bool $network_wide Check if network wide.
401
+ */
402
+ public function callback_activate_plugin( $slug, $network_wide ) {
403
+ $_plugins = $this->get_plugins();
404
+ $name = $_plugins[ $slug ]['Name'];
405
+ $network_wide = $network_wide ? esc_html__( 'network wide', 'mainwp-child' ) : null;
406
+
407
+ if ( empty( $name ) ) {
408
+ return;
409
+ }
410
+
411
+ $this->save_actions(
412
+ _x(
413
+ '"%1$s" plugin activated %2$s',
414
+ '1: Plugin name, 2: Single site or network wide',
415
+ 'mainwp-child'
416
+ ),
417
+ compact( 'name', 'network_wide', 'slug' ),
418
+ 'plugins',
419
+ 'activated'
420
+ );
421
+ }
422
+
423
+ /**
424
+ * Decativate plugin callback.
425
+ *
426
+ * @param string $slug Plugin slug.
427
+ * @param bool $network_wide Check if network wide.
428
+ */
429
+ public function callback_deactivate_plugin( $slug, $network_wide ) {
430
+ $_plugins = $this->get_plugins();
431
+ $name = $_plugins[ $slug ]['Name'];
432
+ $network_wide = $network_wide ? esc_html__( 'network wide', 'mainwp-child' ) : null;
433
+
434
+ $this->save_actions(
435
+ _x(
436
+ '"%1$s" plugin deactivated %2$s',
437
+ '1: Plugin name, 2: Single site or network wide',
438
+ 'mainwp-child'
439
+ ),
440
+ compact( 'name', 'network_wide', 'slug' ),
441
+ 'plugins',
442
+ 'deactivated'
443
+ );
444
+ }
445
+
446
+ /**
447
+ * Switch theme callback.
448
+ *
449
+ * @param string $name Theme name.
450
+ * @param string $theme Theme slug.
451
+ */
452
+ public function callback_switch_theme( $name, $theme ) {
453
+ unset( $theme );
454
+ $this->save_actions(
455
+ __( '"%s" theme activated', 'mainwp-child' ),
456
+ compact( 'name' ),
457
+ 'themes',
458
+ 'activated'
459
+ );
460
+ }
461
+
462
+ /**
463
+ * Update theme & transient delete callback.
464
+ *
465
+ * @todo Core needs a delete_theme hook
466
+ */
467
+ public function callback_delete_site_transient_update_themes() {
468
+ $backtrace = debug_backtrace(); // @codingStandardsIgnoreLine This is used as a hack to determine a theme was deleted.
469
+ $delete_theme_call = null;
470
+
471
+ foreach ( $backtrace as $call ) {
472
+ if ( isset( $call['function'] ) && 'delete_theme' === $call['function'] ) {
473
+ $delete_theme_call = $call;
474
+ break;
475
+ }
476
+ }
477
+
478
+ if ( empty( $delete_theme_call ) ) {
479
+ return;
480
+ }
481
+
482
+ $name = $delete_theme_call['args'][0];
483
+ // @todo Can we get the name of the theme? Or has it already been eliminated
484
+
485
+ $this->save_actions(
486
+ __( '"%s" theme deleted', 'mainwp-child' ),
487
+ compact( 'name' ),
488
+ 'themes',
489
+ 'deleted'
490
+ );
491
+ }
492
+
493
+ /**
494
+ * Uninstall plugins callback.
495
+ */
496
+ public function callback_pre_option_uninstall_plugins() {
497
+ if ( ! isset( $_POST['action'] ) || 'delete-plugin' !== $_POST['action'] ) {
498
+ return false;
499
+ }
500
+ $plugin = $_POST['plugin'];
501
+ $_plugins = $this->get_plugins();
502
+ $plugins_to_delete = array();
503
+ $plugins_to_delete[ $plugin ] = isset( $_plugins[ $plugin ] ) ? $_plugins[ $plugin ] : array();
504
+ update_option( 'wp_mainwp_stream_plugins_to_delete', $plugins_to_delete );
505
+ return false;
506
+ }
507
+
508
+ /**
509
+ * Uninstall plugins callback.
510
+ *
511
+ * @param string $plugin_file plugin file name.
512
+ * @param bool $deleted deleted or not.
513
+ */
514
+ public function callback_deleted_plugin( $plugin_file, $deleted ) {
515
+ if ( $deleted ) {
516
+
517
+ if ( ! isset( $_POST['action'] ) || 'delete-plugin' !== $_POST['action'] ) {
518
+ return;
519
+ }
520
+ $plugins_to_delete = get_option( 'wp_mainwp_stream_plugins_to_delete' );
521
+ if ( ! $plugins_to_delete ) {
522
+ return;
523
+ }
524
+ foreach ( $plugins_to_delete as $plugin => $data ) {
525
+ if ( $plugin_file == $plugin ) {
526
+ $name = $data['Name'];
527
+ $network_wide = $data['Network'] ? esc_html__( 'network wide', 'mainwp-child' ) : '';
528
+
529
+ $this->save_actions(
530
+ __( '"%s" plugin deleted', 'mainwp-child' ),
531
+ compact( 'name', 'plugin', 'network_wide' ),
532
+ 'plugins',
533
+ 'deleted'
534
+ );
535
+ }
536
+ }
537
+ delete_option( 'wp_mainwp_stream_plugins_to_delete' );
538
+ }
539
+ }
540
+
541
+ /**
542
+ * Logs WordPress core upgrades
543
+ *
544
+ * @action automatic_updates_complete
545
+ *
546
+ * @param string $update_results Update results.
547
+ * @return mixed bool|null.
548
+ */
549
+ public function callback_automatic_updates_complete( $update_results ) {
550
+ global $pagenow, $wp_version;
551
+
552
+ if ( ! is_array( $update_results ) || ! isset( $update_results['core'] ) ) {
553
+ return false;
554
+ }
555
+
556
+ $info = $update_results['core'][0];
557
+
558
+ $old_version = $wp_version;
559
+ $new_version = $info->item->version;
560
+ $auto_updated = true;
561
+
562
+ $message = esc_html__( 'WordPress auto-updated to %s', 'stream' );
563
+
564
+ $this->save_actions(
565
+ $message,
566
+ compact( 'new_version', 'old_version', 'auto_updated' ),
567
+ 'wordpress', // phpcs:ignore -- fix format text.
568
+ 'updated'
569
+ );
570
+ }
571
+
572
+ /**
573
+ * Core updated successfully callback.
574
+ *
575
+ * @param string $new_version New WordPress verison.
576
+ */
577
+ public function callback__core_updated_successfully( $new_version ) {
578
+
579
+ /**
580
+ * Global variables.
581
+ *
582
+ * @global string $pagenow Current page.
583
+ * @global string $wp_version WordPress version.
584
+ */
585
+ global $pagenow, $wp_version;
586
+
587
+ $old_version = $wp_version;
588
+ $auto_updated = ( 'update-core.php' !== $pagenow );
589
+
590
+ if ( $auto_updated ) {
591
+ // translators: Placeholder refers to a version number (e.g. "4.2").
592
+ $message = esc_html__( 'WordPress auto-updated to %s', 'mainwp-child' );
593
+ } else {
594
+ // translators: Placeholder refers to a version number (e.g. "4.2").
595
+ $message = esc_html__( 'WordPress updated to %s', 'mainwp-child' );
596
+ }
597
+
598
+ $this->save_actions(
599
+ $message,
600
+ compact( 'new_version', 'old_version', 'auto_updated' ),
601
+ 'wordpress', // phpcs:ignore -- fix format text.
602
+ 'updated'
603
+ );
604
+ }
605
+
606
+ /**
607
+ * Upgrader pre-instaler callback.
608
+ */
609
+ public function callback_upgrader_pre_install() {
610
+ $this->current_plugins_info = $this->get_plugins();
611
+ }
612
+
613
+ /**
614
+ * Wrapper method for calling get_plugins().
615
+ *
616
+ * @return array Installed plugins.
617
+ */
618
+ public function get_plugins() {
619
+ if ( ! function_exists( 'get_plugins' ) ) {
620
+ require_once ABSPATH . 'wp-admin/includes/plugin.php';
621
+ }
622
+
623
+ return get_plugins();
624
+ }
625
+
626
+ /**
627
+ * Log handler.
628
+ *
629
+ * @param string $message sprintf-ready error message string.
630
+ * @param array $args sprintf (and extra) arguments to use.
631
+ * @param string $context Context of the event.
632
+ * @param string $action Action of the event.
633
+ */
634
+ public function save_actions( $message, $args, $context, $action ) {
635
+
636
+ /**
637
+ * Global variable.
638
+ *
639
+ * @global object $wp_roles WordPress user roles object.
640
+ * */
641
+ global $wp_roles;
642
+
643
+ if ( defined( 'WP_IMPORTING' ) && WP_IMPORTING ) {
644
+ return false;
645
+ }
646
+
647
+ $context_label = $this->get_valid_context( $context );
648
+ if ( empty( $context_label ) ) { // not valid.
649
+ return false;
650
+ }
651
+
652
+ $action_label = $this->get_valid_action( $action );
653
+ if ( empty( $action_label ) ) { // not valid.
654
+ return false;
655
+ }
656
+
657
+ $notification = apply_filters( 'mainwp_child_actions_save_data', true, $context, $action, $args, $message );
658
+
659
+ if ( ! $notification ) {
660
+ return false;
661
+ }
662
+
663
+ $user_id = get_current_user_id();
664
+ $user = get_user_by( 'id', $user_id );
665
+
666
+ $connected_user = get_option( 'mainwp_child_connected_admin', '' );
667
+
668
+ if ( ! empty( $user->user_login ) && $connected_user == $user->user_login ) {
669
+ return false; // not save action.
670
+ }
671
+
672
+ $user_role_label = '';
673
+ $role = '';
674
+ $roles = MainWP_Utility::instance()->get_roles();
675
+ if ( ! empty( $user->roles ) ) {
676
+ $user_roles = array_values( $user->roles );
677
+ $role = $user_roles[0];
678
+ $user_role_label = isset( $roles[ $role ] ) ? $roles[ $role ] : $role;
679
+ }
680
+
681
+ $userlogin = (string) ( ! empty( $user->user_login ) ? $user->user_login : '' );
682
+
683
+ $agent = $this->get_current_agent();
684
+ $meta_data = array(
685
+ 'user_id' => (int) $user_id,
686
+ 'display_name' => (string) $this->get_display_name( $user ),
687
+ 'action_user' => (string) $userlogin,
688
+ 'role' => (string) $role,
689
+ 'user_role_label' => (string) $user_role_label,
690
+ 'agent' => (string) $agent,
691
+ );
692
+
693
+ if ( 'wp_cli' === $agent && function_exists( 'posix_getuid' ) ) {
694
+ $uid = posix_getuid();
695
+ $user_info = posix_getpwuid( $uid );
696
+
697
+ $meta_data['system_user_id'] = (int) $uid;
698
+ $meta_data['system_user_name'] = (string) $user_info['name'];
699
+ }
700
+
701
+ // Prevent any meta with null values from being logged.
702
+ $other_meta = array_filter(
703
+ $args,
704
+ function ( $var ) {
705
+ return ! is_null( $var );
706
+ }
707
+ );
708
+
709
+ // Add user meta to Stream meta.
710
+ $other_meta['meta_data'] = $meta_data;
711
+
712
+ $created = MainWP_Helper::get_timestamp();
713
+
714
+ if ( ! empty( $user->roles ) ) {
715
+ $roles = array_values( $user->roles );
716
+ $role = $roles[0];
717
+ } elseif ( is_multisite() && is_super_admin() && $wp_roles->is_role( 'administrator' ) ) {
718
+ $role = 'administrator';
719
+ } else {
720
+ $role = '';
721
+ }
722
+
723
+ $action = (string) $action;
724
+
725
+ $new_action = 0;
726
+ if ( 1 === self::$enable_actions_notification ) {
727
+ $new_action = 1; // new to notification.
728
+ }
729
+
730
+ $recordarr = array(
731
+ 'context' => $context,
732
+ 'action' => $action,
733
+ 'action_user' => $userlogin,
734
+ 'created' => $created,
735
+ 'summary' => (string) vsprintf( $message, $args ),
736
+ 'meta_data' => $other_meta,
737
+ 'new' => $new_action,
738
+ );
739
+ $index = \microtime( true ) * 10000;
740
+ $this->update_actions_data( $index, $recordarr );
741
+
742
+ if ( 1 === $new_action ) {
743
+ update_option( 'mainwp_child_send_action_notification_next_time', time() + 5 * MINUTE_IN_SECONDS );
744
+ }
745
+ }
746
+
747
+ /**
748
+ * Get valid context.
749
+ *
750
+ * @param string $context Context.
751
+ *
752
+ * @return string Context label.
753
+ */
754
+ public function get_valid_context( $context ) {
755
+ $context = (string) $context;
756
+ $valid = array(
757
+ 'plugins' => 'Plugins',
758
+ 'themes' => 'Themes',
759
+ 'wordpress' => 'WordPress' // phpcs:ignore -- fix format text.
760
+ );
761
+ return isset( $valid[ $context ] ) ? $valid[ $context ] : '';
762
+ }
763
+
764
+ /**
765
+ * Get valid action.
766
+ *
767
+ * @param string $action action.
768
+ *
769
+ * @return string action label.
770
+ */
771
+ public function get_valid_action( $action ) {
772
+ $action = (string) $action;
773
+ $valid = array(
774
+ 'updated' => 'updated',
775
+ 'deleted' => 'deleted',
776
+ 'activated' => 'activated',
777
+ 'deactivated' => 'deactivated',
778
+ 'installed' => 'installed',
779
+ );
780
+ return isset( $valid[ $action ] ) ? $valid[ $action ] : '';
781
+ }
782
+
783
+ /**
784
+ * Get the display name of the user
785
+ *
786
+ * @param mixed $user User object.
787
+ *
788
+ * @return string Return User Login or Display Names.
789
+ */
790
+ public function get_display_name( $user ) {
791
+ if ( 0 == $user->ID ) {
792
+ if ( 'wp_cli' === $this->get_current_agent() ) {
793
+ return 'WP-CLI';
794
+ }
795
+ return esc_html__( 'N/A', 'mainwp-child' );
796
+ } else {
797
+ if ( ! empty( $user->display_name ) ) {
798
+ return $user->display_name;
799
+ } else {
800
+ return $user->user_login;
801
+ }
802
+ }
803
+ }
804
+
805
+ /**
806
+ * Get agent.
807
+ *
808
+ * @return string
809
+ */
810
+ public function get_current_agent() {
811
+ $agent = '';
812
+ if ( defined( '\WP_CLI' ) && \WP_CLI ) {
813
+ $agent = 'wp_cli';
814
+ } elseif ( $this->is_doing_wp_cron() ) {
815
+ $agent = 'wp_cron';
816
+ }
817
+ return $agent;
818
+ }
819
+
820
+ /**
821
+ * True if doing WP Cron, otherwise false.
822
+ *
823
+ * @return bool
824
+ */
825
+ public function is_doing_wp_cron() {
826
+ return (
827
+ $this->is_cron_enabled()
828
+ &&
829
+ defined( 'DOING_CRON' )
830
+ &&
831
+ DOING_CRON
832
+ );
833
+ }
834
+
835
+ /**
836
+ * True if native WP Cron is enabled, otherwise false.
837
+ *
838
+ * @return bool
839
+ */
840
+ public function is_cron_enabled() {
841
+ return ( defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON ) ? false : true;
842
+ }
843
+
844
+ /**
845
+ * Method send_installer_notification()
846
+ *
847
+ * To send email notification for plugins/themes/core change.
848
+ *
849
+ * @param array $data Action Data.
850
+ */
851
+ public function send_actions_notification( $data ) {
852
+
853
+ if ( 1 !== self::$enable_actions_notification ) {
854
+ return;
855
+ }
856
+
857
+ $username = get_option( 'mainwp_child_connected_admin', '' );
858
+ $user = get_user_by( 'login', $username );
859
+ $email = ! empty( $user->user_email ) ? $user->user_email : '';
860
+
861
+ if ( empty( $email ) ) {
862
+ return;
863
+ }
864
+
865
+ $actions = self::get_actions_data();
866
+
867
+ ksort( $actions );
868
+ // site info.
869
+ $blog = get_bloginfo( 'name' );
870
+ $site = get_bloginfo( 'url' ) . '/';
871
+
872
+ // log time.
873
+ $time = sanitize_text_field( wp_unslash( date( 'F jS Y, h:ia', time() ) ) ); // phpcs:ignore -- Use local time to achieve desired results, pull request solutions appreciated.
874
+
875
+ $content = '<div>Actions notification</div><div></div><br>';
876
+
877
+ foreach ( $actions as $index => $data ) {
878
+ if ( 'connected_admin' === strval( $index ) ) {
879
+ continue;
880
+ }
881
+ if ( is_array( $data ) && ! empty( $data['action_user'] ) && isset( $data['new'] ) && 1 === (int) $data['new'] ) {
882
+ $content .= $data['action_user'] . ' - ' . $data['summray'] . ' - ' . MainWP_Helper::format_timestamp( ( $data['created'] ) ) . '<br>';
883
+ $data['new'] = 0;
884
+ $this->update_actions_data( $index, $data );
885
+ }
886
+ }
887
+
888
+ MainWP_Utility::instance()->send_wp_mail(
889
+ $email,
890
+ 'MainWP - Actions notification: ' . $blog,
891
+ MainWP_Child_Format::format_email( $content ),
892
+ array(
893
+ 'content-type: text/html',
894
+ )
895
+ );
896
+ }
897
+ }
class/class-mainwp-child-branding-render.php CHANGED
@@ -186,7 +186,7 @@ class MainWP_Child_Branding_Render {
186
  $back_link = ! empty( $back_link ) ? $back_link : 'Go Back';
187
  $back_link = ! empty( $from_page ) ? '<a href="' . esc_url( $from_page ) . '" title="' . esc_attr( $back_link ) . '">' . esc_html( $back_link ) . '</a>' : '';
188
 
189
- if ( $this->send_support_mail() ) {
190
  $send_email_message = isset( $opts['send_email_message'] ) ? $opts['send_email_message'] : '';
191
  if ( ! empty( $send_email_message ) ) {
192
  $send_email_message = stripslashes( $send_email_message );
@@ -201,51 +201,6 @@ class MainWP_Child_Branding_Render {
201
  <?php
202
  }
203
 
204
- /**
205
- * Send support email.
206
- *
207
- * @return bool Return TRUE on success FALSE on failure.
208
- *
209
- * @uses \MainWP\Child\MainWP_Child_Branding::get_branding_options()
210
- */
211
- public function send_support_mail() {
212
- $opts = MainWP_Child_Branding::instance()->get_branding_options();
213
- $email = $opts['support_email'];
214
- $sub = isset( $_POST['mainwp_branding_contact_message_subject'] ) ? wp_kses_post( nl2br( stripslashes( wp_unslash( $_POST['mainwp_branding_contact_message_subject'] ) ) ) ) : '';
215
- $from = isset( $_POST['mainwp_branding_contact_send_from'] ) ? trim( wp_unslash( $_POST['mainwp_branding_contact_send_from'] ) ) : '';
216
- $subject = ! empty( $sub ) ? $sub : 'MainWP - Support Contact';
217
- $content = isset( $_POST['mainwp_branding_contact_message_content'] ) ? wp_kses_post( nl2br( stripslashes( wp_unslash( $_POST['mainwp_branding_contact_message_content'] ) ) ) ) : '';
218
- $mail = '';
219
- $headers = '';
220
-
221
- $from_page = isset( $_POST['mainwp_branding_send_from_page'] ) ? wp_unslash( $_POST['mainwp_branding_send_from_page'] ) : '';
222
-
223
- if ( ! empty( $_POST['mainwp_branding_contact_message_content'] ) && ! empty( $email ) ) {
224
-
225
- /**
226
- * Current user global.
227
- *
228
- * @global string
229
- */
230
- global $current_user;
231
-
232
- $headers .= "Content-Type: text/html;charset=utf-8\r\n";
233
- if ( ! empty( $from ) ) {
234
- $headers .= 'From: "' . $from . '" <' . $from . ">\r\n";
235
- }
236
- $mail .= "<p>Support Email from: <a href='" . site_url() . "'>" . site_url() . "</a></p>\r\n\r\n";
237
- $mail .= '<p>Sent from WordPress page: ' . ( ! empty( $from_page ) ? "<a href='" . esc_url( $from_page ) . "'>" . esc_url( $from_page ) . "</a></p>\r\n\r\n" : '' );
238
- $mail .= '<p>Client Email: ' . $current_user->user_email . " </p>\r\n\r\n";
239
- $mail .= "<p>Support Text:</p>\r\n\r\n";
240
- $mail .= '<p>' . $content . "</p>\r\n\r\n";
241
-
242
- wp_mail( $email, $subject, $mail, $headers );
243
-
244
- return true;
245
- }
246
- return false;
247
- }
248
-
249
  /**
250
  * After admin bar render.
251
  */
186
  $back_link = ! empty( $back_link ) ? $back_link : 'Go Back';
187
  $back_link = ! empty( $from_page ) ? '<a href="' . esc_url( $from_page ) . '" title="' . esc_attr( $back_link ) . '">' . esc_html( $back_link ) . '</a>' : '';
188
 
189
+ if ( MainWP_Utility::instance()->send_support_mail() ) {
190
  $send_email_message = isset( $opts['send_email_message'] ) ? $opts['send_email_message'] : '';
191
  if ( ! empty( $send_email_message ) ) {
192
  $send_email_message = stripslashes( $send_email_message );
201
  <?php
202
  }
203
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
204
  /**
205
  * After admin bar render.
206
  */
class/class-mainwp-child-format.php ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * MainWP Child Format
4
+ *
5
+ * @package MainWP/Child
6
+ */
7
+
8
+ namespace MainWP\Child;
9
+
10
+ /**
11
+ * Class MainWP_Child_Format
12
+ *
13
+ * MainWP Child Format
14
+ */
15
+ class MainWP_Child_Format {
16
+
17
+ /**
18
+ * Public static variable to hold the single instance of the class.
19
+ *
20
+ * @var mixed Default null
21
+ */
22
+ public static $instance = null;
23
+
24
+ /**
25
+ * Method get_class_name()
26
+ *
27
+ * Get class name.
28
+ *
29
+ * @return string __CLASS__ Class name.
30
+ */
31
+ public static function get_class_name() {
32
+ return __CLASS__;
33
+ }
34
+
35
+ /**
36
+ * Method instance()
37
+ *
38
+ * Create a public static instance.
39
+ *
40
+ * @return mixed Class instance.
41
+ */
42
+ public static function instance() {
43
+ if ( null === self::$instance ) {
44
+ self::$instance = new self();
45
+ }
46
+ return self::$instance;
47
+ }
48
+
49
+
50
+ /**
51
+ * Method format_email()
52
+ *
53
+ * Format emails.
54
+ *
55
+ * @param string $body Contains the email content.
56
+ *
57
+ * @return string Return formatted email.
58
+ */
59
+ public static function format_email( $body ) {
60
+ return '<br>
61
+ <div>
62
+ <br>
63
+ <div style="background:#ffffff;padding:0 1.618em;font:13px/20px Helvetica,Arial,Sans-serif;padding-bottom:50px!important">
64
+ <div style="width:600px;background:#fff;margin-left:auto;margin-right:auto;margin-top:10px;margin-bottom:25px;padding:0!important;border:10px Solid #fff;border-radius:10px;overflow:hidden">
65
+ <div style="display: block; width: 100%;border-bottom: 2px Solid #7fb100 ; overflow: hidden;">
66
+ <div style="display: block; width: 95% ; margin-left: auto ; margin-right: auto ; padding: .5em 0 ;">
67
+ <div style="float: left;font-size:45px;"><a href="https://mainwp.com">MainWP</a></div>
68
+ <div style="float: right; margin-top: .6em ;">
69
+ <span style="display: inline-block; margin-right: .8em;"><a href="https://mainwp.com/mainwp-extensions/" style="font-family: Helvetica, Sans; color: #7fb100; text-transform: uppercase; font-size: 14px;">Extensions</a></span>
70
+ <span style="display: inline-block; margin-right: .8em;"><a style="font-family: Helvetica, Sans; color: #7fb100; text-transform: uppercase; font-size: 14px;" href="https://managers.mainwp.com/">Community</a></span>
71
+ <span style="display: inline-block; margin-right: .8em;"><a style="font-family: Helvetica, Sans; color: #7fb100; text-transform: uppercase; font-size: 14px;" href="https://kb.mainwp.com/">Knowledgebase</a></span>
72
+ </div><div style="clear: both;"></div>
73
+ </div>
74
+ </div>
75
+ <div>
76
+ <p>Hello MainWP User!<br></p>
77
+ ' . $body . '
78
+ <div></div>
79
+ <br />
80
+ <div>MainWP</div>
81
+ <div><a href="https://www.MainWP.com" target="_blank">www.MainWP.com</a></div>
82
+ <p></p>
83
+ </div>
84
+
85
+ <div style="display: block; width: 100% ; background: #1c1d1b;">
86
+ <div style="display: block; width: 95% ; margin-left: auto ; margin-right: auto ; padding: .5em 0 ;">
87
+ <div style="padding: .5em 0 ; float: left;"><p style="color: #fff; font-family: Helvetica, Sans; font-size: 12px ;">© 2013 MainWP. All Rights Reserved.</p></div>
88
+ </div>
89
+ </div>
90
+ </div>
91
+ <center>
92
+ <br><br><br><br><br><br>
93
+ <table border="0" cellpadding="0" cellspacing="0" width="100%" style="background-color:#ffffff;border-top:1px solid #e5e5e5">
94
+ <tbody><tr>
95
+ <td align="center" valign="top" style="padding-top:20px;padding-bottom:20px">
96
+ <table border="0" cellpadding="0" cellspacing="0">
97
+ <tbody><tr>
98
+ <td align="center" valign="top" style="color:#606060;font-family:Helvetica,Arial,sans-serif;font-size:11px;line-height:150%;padding-right:20px;padding-bottom:5px;padding-left:20px;text-align:center">
99
+ This email is sent from your MainWP Dashboard.
100
+ <br>
101
+ If you do not wish to receive these notices please re-check your preferences in the MainWP Settings page.
102
+ <br>
103
+ <br>
104
+ </td>
105
+ </tr>
106
+ </tbody></table>
107
+ </td>
108
+ </tr>
109
+ </tbody></table>
110
+
111
+ </center>
112
+ </div>
113
+ </div>
114
+ <br>';
115
+ }
116
+
117
+
118
+ }
class/class-mainwp-child-misc.php CHANGED
@@ -199,7 +199,7 @@ class MainWP_Child_Misc {
199
  * @uses \MainWP\Child\MainWP_Security::admin_user_ok()
200
  * @uses \MainWP\Child\MainWP_Security::remove_readme_ok()
201
  */
202
- public function get_security_stats( $return = false ) {
203
  $information = array();
204
 
205
  $information['listing'] = ( ! MainWP_Security::prevent_listing_ok() ? 'N' : 'Y' );
@@ -212,6 +212,10 @@ class MainWP_Child_Misc {
212
  $information['registered_versions'] = ( MainWP_Security::remove_registered_versions_ok() ? 'Y' : 'N' );
213
  $information['admin'] = ( MainWP_Security::admin_user_ok() ? 'Y' : 'N' );
214
  $information['readme'] = ( MainWP_Security::remove_readme_ok() ? 'Y' : 'N' );
 
 
 
 
215
 
216
  if ( $return ) {
217
  return $information;
199
  * @uses \MainWP\Child\MainWP_Security::admin_user_ok()
200
  * @uses \MainWP\Child\MainWP_Security::remove_readme_ok()
201
  */
202
+ public function get_security_stats( $return = false ) { // phpcs:ignore -- required to achieve desired results, pull request solutions appreciated.
203
  $information = array();
204
 
205
  $information['listing'] = ( ! MainWP_Security::prevent_listing_ok() ? 'N' : 'Y' );
212
  $information['registered_versions'] = ( MainWP_Security::remove_registered_versions_ok() ? 'Y' : 'N' );
213
  $information['admin'] = ( MainWP_Security::admin_user_ok() ? 'Y' : 'N' );
214
  $information['readme'] = ( MainWP_Security::remove_readme_ok() ? 'Y' : 'N' );
215
+ $information['wp_uptodate'] = ( MainWP_Security::wpcore_updated_ok() ? 'Y' : 'N' );
216
+ $information['phpversion_matched'] = ( MainWP_Security::phpversion_ok() ? 'Y' : 'N' );
217
+ $information['sslprotocol'] = ( MainWP_Security::sslprotocol_ok() ? 'Y' : 'N' );
218
+ $information['debug_disabled'] = ( MainWP_Security::debug_disabled_ok() ? 'Y' : 'N' );
219
 
220
  if ( $return ) {
221
  return $information;
class/class-mainwp-child-stats.php CHANGED
@@ -192,6 +192,11 @@ class MainWP_Child_Stats {
192
 
193
  MainWP_Child_Plugins_Check::may_outdate_number_change();
194
 
 
 
 
 
 
195
  $this->stats_get_info( $information );
196
 
197
  include_once ABSPATH . '/wp-admin/includes/update.php';
@@ -263,11 +268,12 @@ class MainWP_Child_Stats {
263
  if ( isset( $last_post ) && isset( $last_post['post_modified_gmt'] ) ) {
264
  $information['last_post_gmt'] = strtotime( $last_post['post_modified_gmt'] );
265
  }
266
- $information['mainwpdir'] = ( MainWP_Utility::validate_mainwp_dir() ? 1 : - 1 );
267
- $information['uniqueId'] = MainWP_Helper::get_site_unique_id();
268
- $information['plugins_outdate_info'] = MainWP_Child_Plugins_Check::instance()->get_plugins_outdate_info();
269
- $information['themes_outdate_info'] = MainWP_Child_Themes_Check::instance()->get_themes_outdate_info();
270
- $information['health_site_status'] = $this->get_health_check_site_status();
 
271
 
272
  if ( isset( $_POST['user'] ) ) {
273
  $user = get_user_by( 'login', sanitize_text_field( wp_unslash( $_POST['user'] ) ) );
192
 
193
  MainWP_Child_Plugins_Check::may_outdate_number_change();
194
 
195
+ if ( isset( $_POST['child_actions_saved_days_number'] ) ) {
196
+ $days_number = intval( $_POST['child_actions_saved_days_number'] );
197
+ MainWP_Helper::update_option( 'mainwp_child_actions_saved_number_of_days', $days_number );
198
+ }
199
+
200
  $this->stats_get_info( $information );
201
 
202
  include_once ABSPATH . '/wp-admin/includes/update.php';
268
  if ( isset( $last_post ) && isset( $last_post['post_modified_gmt'] ) ) {
269
  $information['last_post_gmt'] = strtotime( $last_post['post_modified_gmt'] );
270
  }
271
+ $information['mainwpdir'] = ( MainWP_Utility::validate_mainwp_dir() ? 1 : - 1 );
272
+ $information['uniqueId'] = MainWP_Helper::get_site_unique_id();
273
+ $information['plugins_outdate_info'] = MainWP_Child_Plugins_Check::instance()->get_plugins_outdate_info();
274
+ $information['themes_outdate_info'] = MainWP_Child_Themes_Check::instance()->get_themes_outdate_info();
275
+ $information['health_site_status'] = $this->get_health_check_site_status();
276
+ $information['child_site_actions_data'] = MainWP_Child_Actions::get_actions_data();
277
 
278
  if ( isset( $_POST['user'] ) ) {
279
  $user = get_user_by( 'login', sanitize_text_field( wp_unslash( $_POST['user'] ) ) );
class/class-mainwp-child-updates.php CHANGED
@@ -111,6 +111,14 @@ class MainWP_Child_Updates {
111
  * @uses \MainWP\Child\MainWP_Helper::write()
112
  */
113
  public function upgrade_plugin_theme() {
 
 
 
 
 
 
 
 
114
  MainWP_Helper::maybe_set_doing_cron();
115
 
116
  MainWP_Helper::get_wp_filesystem();
@@ -864,6 +872,13 @@ class MainWP_Child_Updates {
864
  MainWP_Helper::write( $information );
865
  }
866
 
 
 
 
 
 
 
 
867
  if ( null !== $this->filterFunction ) {
868
  add_filter( 'pre_site_transient_update_core', $this->filterFunction, 99 );
869
  }
111
  * @uses \MainWP\Child\MainWP_Helper::write()
112
  */
113
  public function upgrade_plugin_theme() {
114
+
115
+ /**
116
+ * Action before update plugin, theme.
117
+ *
118
+ * @since 4.3
119
+ */
120
+ do_action( 'mainwp_child_before_update_plugin_theme' );
121
+
122
  MainWP_Helper::maybe_set_doing_cron();
123
 
124
  MainWP_Helper::get_wp_filesystem();
872
  MainWP_Helper::write( $information );
873
  }
874
 
875
+ /**
876
+ * Action before update WP.
877
+ *
878
+ * @since 4.3
879
+ */
880
+ do_action( 'mainwp_child_before_update_wp' );
881
+
882
  if ( null !== $this->filterFunction ) {
883
  add_filter( 'pre_site_transient_update_core', $this->filterFunction, 99 );
884
  }
class/class-mainwp-child-users.php CHANGED
@@ -553,7 +553,7 @@ class MainWP_Child_Users {
553
  $message .= sprintf( __( 'Password: %s' ), $new_user['user_pass'] ) . "\r\n";
554
  $message .= wp_login_url() . "\r\n";
555
 
556
- wp_mail( $user_email, sprintf( __( '[%s] Your username and password' ), $blogname ), $message, '' );
557
  }
558
  $information['added'] = true;
559
  MainWP_Helper::write( $information );
553
  $message .= sprintf( __( 'Password: %s' ), $new_user['user_pass'] ) . "\r\n";
554
  $message .= wp_login_url() . "\r\n";
555
 
556
+ MainWP_Utility::instance()->send_wp_mail( $user_email, sprintf( __( '[%s] Your username and password' ), $blogname ), $message );
557
  }
558
  $information['added'] = true;
559
  MainWP_Helper::write( $information );
class/class-mainwp-child-wordfence.php CHANGED
@@ -3518,7 +3518,7 @@ SQL
3518
  ),
3519
  'WP_DEBUG_DISPLAY' => array(
3520
  'description' => 'WordPress error display override',
3521
- 'value' => defined( 'WP_DEBUG_DISPLAY' ) ? ( WP_DEBUG_LOG ? 'Enabled' : 'Disabled' ) : '(not set)',
3522
  ),
3523
  'SCRIPT_DEBUG' => array(
3524
  'description' => 'WordPress script debug mode',
3518
  ),
3519
  'WP_DEBUG_DISPLAY' => array(
3520
  'description' => 'WordPress error display override',
3521
+ 'value' => defined( 'WP_DEBUG_DISPLAY' ) ? ( WP_DEBUG_DISPLAY ? 'Enabled' : 'Disabled' ) : '(not set)',
3522
  ),
3523
  'SCRIPT_DEBUG' => array(
3524
  'description' => 'WordPress script debug mode',
class/class-mainwp-child.php CHANGED
@@ -33,7 +33,7 @@ class MainWP_Child {
33
  *
34
  * @var string MainWP Child plugin version.
35
  */
36
- public static $version = '4.2.6';
37
 
38
  /**
39
  * Private variable containing the latest MainWP Child update version.
@@ -122,6 +122,13 @@ class MainWP_Child {
122
  add_action( 'init', array( MainWP_Utility::get_class_name(), 'cron_active' ), PHP_INT_MAX );
123
  }
124
  }
 
 
 
 
 
 
 
125
  }
126
 
127
  /**
@@ -174,8 +181,11 @@ class MainWP_Child {
174
  'mainwp_child_branding_settings',
175
  'mainwp_child_plugintheme_days_outdate',
176
  'mainwp_wp_staging_ext_enabled',
 
 
 
177
  );
178
- $query = "SELECT option_name, option_value FROM $wpdb->options WHERE option_name in (";
179
  foreach ( $options as $option ) {
180
  $query .= "'" . $option . "', ";
181
  }
@@ -240,11 +250,9 @@ class MainWP_Child {
240
  * Method template_redirect()
241
  *
242
  * Handle the template redirect for 404 maintenance alerts.
243
- *
244
- * @uses \MainWP\Child\MainWP_Utility::maintenance_alert()
245
  */
246
  public function template_redirect() {
247
- MainWP_Utility::instance()->maintenance_alert();
248
  }
249
 
250
  /**
@@ -343,6 +351,7 @@ class MainWP_Child {
343
  if ( MainWP_Helper::is_admin() && is_admin() ) {
344
  MainWP_Clone::instance()->init_ajax();
345
  }
 
346
  }
347
 
348
  /**
@@ -403,6 +412,7 @@ class MainWP_Child {
403
  'mainwp_child_nossl_key',
404
  'mainwp_security',
405
  'mainwp_child_server',
 
406
  );
407
  $to_delete[] = 'mainwp_ext_snippets_enabled';
408
  $to_delete[] = 'mainwp_ext_code_snippets';
@@ -437,6 +447,7 @@ class MainWP_Child {
437
  'mainwp_child_nonce',
438
  'mainwp_child_nossl',
439
  'mainwp_child_nossl_key',
 
440
  );
441
  foreach ( $to_delete as $delete ) {
442
  if ( get_option( $delete ) ) {
33
  *
34
  * @var string MainWP Child plugin version.
35
  */
36
+ public static $version = '4.3';
37
 
38
  /**
39
  * Private variable containing the latest MainWP Child update version.
122
  add_action( 'init', array( MainWP_Utility::get_class_name(), 'cron_active' ), PHP_INT_MAX );
123
  }
124
  }
125
+
126
+ /**
127
+ * Action to response data result.
128
+ *
129
+ * @since 4.3
130
+ */
131
+ add_action( 'mainwp_child_write', array( MainWP_Helper::class, 'write' ) );
132
  }
133
 
134
  /**
181
  'mainwp_child_branding_settings',
182
  'mainwp_child_plugintheme_days_outdate',
183
  'mainwp_wp_staging_ext_enabled',
184
+ 'mainwp_child_connected_admin',
185
+ 'mainwp_child_actions_saved_number_of_days',
186
+
187
  );
188
+ $query = "SELECT option_name, option_value FROM $wpdb->options WHERE option_name in (";
189
  foreach ( $options as $option ) {
190
  $query .= "'" . $option . "', ";
191
  }
250
  * Method template_redirect()
251
  *
252
  * Handle the template redirect for 404 maintenance alerts.
 
 
253
  */
254
  public function template_redirect() {
255
+ MainWP_Utility::instance()->send_maintenance_alert();
256
  }
257
 
258
  /**
351
  if ( MainWP_Helper::is_admin() && is_admin() ) {
352
  MainWP_Clone::instance()->init_ajax();
353
  }
354
+ MainWP_Child_Actions::get_instance()->init_hooks();
355
  }
356
 
357
  /**
412
  'mainwp_child_nossl_key',
413
  'mainwp_security',
414
  'mainwp_child_server',
415
+ 'mainwp_child_connected_admin',
416
  );
417
  $to_delete[] = 'mainwp_ext_snippets_enabled';
418
  $to_delete[] = 'mainwp_ext_code_snippets';
447
  'mainwp_child_nonce',
448
  'mainwp_child_nossl',
449
  'mainwp_child_nossl_key',
450
+ 'mainwp_child_connected_admin',
451
  );
452
  foreach ( $to_delete as $delete ) {
453
  if ( get_option( $delete ) ) {
class/class-mainwp-client-report-base.php CHANGED
@@ -311,66 +311,6 @@ class MainWP_Client_Report_Base {
311
  return $sections_data;
312
  }
313
 
314
- /**
315
- * Fix logging for posts creation action.
316
- *
317
- * @param array $records An array containg actions records.
318
- * @param array $skip_records An array containg records to skip.
319
- */
320
- protected function fix_logs_posts_created( &$records, &$skip_records ) {
321
-
322
- $args = array(
323
- 'post_type' => 'post',
324
- 'post_status' => 'publish',
325
- 'date_query' => array(
326
- 'column' => 'post_date',
327
- 'after' => $args['date_from'],
328
- 'before' => $args['date_to'],
329
- ),
330
- );
331
-
332
- $result = new \WP_Query( $args );
333
- $records_created_posts = $result->posts;
334
-
335
- if ( $records_created_posts ) {
336
-
337
- $count_records = count( $records );
338
- for ( $i = 0; $i < $count_records; $i++ ) {
339
- $record = $records[ $i ];
340
- if ( 'posts' == $record->connector && 'post' == $record->context && 'created' == $record->action ) {
341
- if ( ! in_array( $record->ID, $skip_records ) ) {
342
- $skip_records[] = $record->ID;
343
- }
344
- }
345
- }
346
-
347
- $post_authors = array();
348
-
349
- foreach ( $records_created_posts as $_post ) {
350
- $au_id = $_post->post_author;
351
- if ( ! isset( $post_authors[ $au_id ] ) ) {
352
- $au = get_user_by( 'id', $au_id );
353
- $post_authors[ $au_id ] = $au->display_name;
354
- }
355
- $au_name = $post_authors[ $au_id ];
356
-
357
- // simulate logging created posts record.
358
- $stdObj = new \stdClass();
359
- $stdObj->ID = 0; // simulate ID value.
360
- $stdObj->connector = 'posts';
361
- $stdObj->context = 'post';
362
- $stdObj->action = 'created';
363
- $stdObj->created = $_post->post_date;
364
- $stdObj->meta = array(
365
- 'post_title' => array( $_post->post_title ),
366
- 'user_meta' => array( $au_name ),
367
- );
368
-
369
- $records[] = $stdObj;
370
- }
371
- }
372
- }
373
-
374
  /**
375
  * Get the other tokens data.
376
  *
311
  return $sections_data;
312
  }
313
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
314
  /**
315
  * Get the other tokens data.
316
  *
class/class-mainwp-client-report.php CHANGED
@@ -227,12 +227,6 @@ class MainWP_Client_Report extends MainWP_Client_Report_Base {
227
  // fix invalid data, or skip records!
228
  $skip_records = array();
229
 
230
- // fix for incorrect posts created logs!
231
- // query created posts from WP posts data to simulate records logging for created posts.
232
- if ( isset( $_POST['direct_posts'] ) && ! empty( $_POST['direct_posts'] ) ) {
233
- $this->fix_logs_posts_created( $records, $skip_records );
234
- }
235
-
236
  $other_tokens_data = $this->get_stream_others_tokens( $records, $other_tokens, $skip_records );
237
  $sections_data = $this->get_stream_sections_data( $records, $sections, $skip_records );
238
 
227
  // fix invalid data, or skip records!
228
  $skip_records = array();
229
 
 
 
 
 
 
 
230
  $other_tokens_data = $this->get_stream_others_tokens( $records, $other_tokens, $skip_records );
231
  $sections_data = $this->get_stream_sections_data( $records, $sections, $skip_records );
232
 
class/class-mainwp-clone.php CHANGED
@@ -693,6 +693,7 @@ class MainWP_Clone {
693
  $nossl = get_option( 'mainwp_child_nossl' );
694
  $nossl_key = get_option( 'mainwp_child_nossl_key' );
695
  $sitesToClone = get_option( 'mainwp_child_clone_sites' );
 
696
 
697
  $cloneInstall->install();
698
 
@@ -704,6 +705,7 @@ class MainWP_Clone {
704
  delete_option( 'mainwp_child_nossl_key' );
705
  delete_option( 'mainwp_child_clone_sites' );
706
  delete_option( 'mainwp_temp_clone_admin' );
 
707
 
708
  MainWP_Helper::update_option( 'mainwp_child_pubkey', $pubkey, 'yes' );
709
  MainWP_Helper::update_option( 'mainwp_child_uniqueId', $uniqueId );
@@ -713,6 +715,7 @@ class MainWP_Clone {
713
  MainWP_Helper::update_option( 'mainwp_child_nossl_key', $nossl_key );
714
  MainWP_Helper::update_option( 'mainwp_child_clone_sites', $sitesToClone );
715
  MainWP_Helper::update_option( 'mainwp_child_just_clone_admin', $clone_admin );
 
716
 
717
  if ( ! MainWP_Helper::starts_with( basename( $file ), 'download-backup-' ) ) {
718
  MainWP_Helper::update_option( 'mainwp_child_restore_permalink', true, 'yes' );
693
  $nossl = get_option( 'mainwp_child_nossl' );
694
  $nossl_key = get_option( 'mainwp_child_nossl_key' );
695
  $sitesToClone = get_option( 'mainwp_child_clone_sites' );
696
+ $username = get_option( 'mainwp_child_connected_admin' );
697
 
698
  $cloneInstall->install();
699
 
705
  delete_option( 'mainwp_child_nossl_key' );
706
  delete_option( 'mainwp_child_clone_sites' );
707
  delete_option( 'mainwp_temp_clone_admin' );
708
+ delete_option( 'mainwp_child_connected_admin' );
709
 
710
  MainWP_Helper::update_option( 'mainwp_child_pubkey', $pubkey, 'yes' );
711
  MainWP_Helper::update_option( 'mainwp_child_uniqueId', $uniqueId );
715
  MainWP_Helper::update_option( 'mainwp_child_nossl_key', $nossl_key );
716
  MainWP_Helper::update_option( 'mainwp_child_clone_sites', $sitesToClone );
717
  MainWP_Helper::update_option( 'mainwp_child_just_clone_admin', $clone_admin );
718
+ MainWP_Helper::update_option( 'mainwp_child_connected_admin', $username, 'yes' );
719
 
720
  if ( ! MainWP_Helper::starts_with( basename( $file ), 'download-backup-' ) ) {
721
  MainWP_Helper::update_option( 'mainwp_child_restore_permalink', true, 'yes' );
class/class-mainwp-connect.php CHANGED
@@ -138,6 +138,7 @@ class MainWP_Connect {
138
 
139
  // Update the mainwp_child_nossl_key option.
140
  MainWP_Helper::update_option( 'mainwp_child_nossl_key', $nossl_key, 'yes' );
 
141
 
142
  $information['nosslkey'] = $nossl_key;
143
  $information['register'] = 'OK';
@@ -612,10 +613,13 @@ class MainWP_Connect {
612
  // to fix issue multi user session.
613
  $user_id = wp_validate_auth_cookie();
614
  if ( $user_id && $user_id === $current_user->ID ) {
 
615
  return true;
616
  }
617
 
618
  wp_set_auth_cookie( $current_user->ID );
 
 
619
  return true;
620
  }
621
  do_action( 'wp_logout' );
@@ -629,7 +633,13 @@ class MainWP_Connect {
629
  do_action( 'wp_login', $user->user_login );
630
  }
631
 
632
- return ( is_user_logged_in() && $current_user->user_login === $username );
 
 
 
 
 
 
633
  }
634
 
635
  return false;
@@ -701,5 +711,24 @@ class MainWP_Connect {
701
  return $this->maxHistory;
702
  }
703
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
704
  }
705
 
138
 
139
  // Update the mainwp_child_nossl_key option.
140
  MainWP_Helper::update_option( 'mainwp_child_nossl_key', $nossl_key, 'yes' );
141
+ MainWP_Helper::update_option( 'mainwp_child_connected_admin', $current_user->user_login, 'yes' );
142
 
143
  $information['nosslkey'] = $nossl_key;
144
  $information['register'] = 'OK';
613
  // to fix issue multi user session.
614
  $user_id = wp_validate_auth_cookie();
615
  if ( $user_id && $user_id === $current_user->ID ) {
616
+ $this->check_compatible_connect_info( true );
617
  return true;
618
  }
619
 
620
  wp_set_auth_cookie( $current_user->ID );
621
+
622
+ $this->check_compatible_connect_info( true );
623
  return true;
624
  }
625
  do_action( 'wp_logout' );
633
  do_action( 'wp_login', $user->user_login );
634
  }
635
 
636
+ $logged_in = ( is_user_logged_in() && $current_user->user_login === $username );
637
+
638
+ if ( $logged_in ) {
639
+ $this->check_compatible_connect_info( $logged_in );
640
+ }
641
+
642
+ return $logged_in;
643
  }
644
 
645
  return false;
711
  return $this->maxHistory;
712
  }
713
 
714
+ /**
715
+ * Method check_compatible_connect_info()
716
+ *
717
+ * Check check compatible connected info.
718
+ *
719
+ * @param bool $logged_in logged in or not.
720
+ */
721
+ public function check_compatible_connect_info( $logged_in ) {
722
+ global $current_user;
723
+ $connect_user = isset( $_POST['user'] ) ? wp_unslash( $_POST['user'] ) : '';
724
+ if ( ! empty( $connect_user ) && $current_user->user_login == $connect_user ) {
725
+ $connected_admin = get_option( 'mainwp_child_connected_admin', '' );
726
+ if ( empty( $connected_admin ) ) {
727
+ // to comparable.
728
+ MainWP_Helper::update_option( 'mainwp_child_connected_admin', $connect_user, 'yes' );
729
+ }
730
+ }
731
+ }
732
+
733
  }
734
 
class/class-mainwp-helper.php CHANGED
@@ -58,11 +58,11 @@ class MainWP_Helper {
58
  public static function write( $value ) {
59
  if ( isset( $_REQUEST['json_result'] ) && true == $_REQUEST['json_result'] ) :
60
  $output = wp_json_encode( $value );
61
- else :
62
- $output = serialize( $value ); // phpcs:ignore -- Required for backwards compatibility.
63
- endif;
64
 
65
- die( '<mainwp>' . base64_encode( $output ) . '</mainwp>' ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode function is used for backwards compatibility.
66
  }
67
 
68
  /**
@@ -534,8 +534,12 @@ class MainWP_Helper {
534
  *
535
  * @return string $timestamp The timestamp including the GMT offset.
536
  */
537
- public static function get_timestamp( $timestamp ) {
 
 
 
538
  $gmtOffset = get_option( 'gmt_offset' );
 
539
  return ( $gmtOffset ? ( $gmtOffset * HOUR_IN_SECONDS ) + $timestamp : $timestamp );
540
  }
541
 
58
  public static function write( $value ) {
59
  if ( isset( $_REQUEST['json_result'] ) && true == $_REQUEST['json_result'] ) :
60
  $output = wp_json_encode( $value );
61
+ else :
62
+ $output = serialize( $value ); // phpcs:ignore -- Required for backwards compatibility.
63
+ endif;
64
 
65
+ die( '<mainwp>' . base64_encode( $output ) . '</mainwp>' ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode function is used for backwards compatibility.
66
  }
67
 
68
  /**
534
  *
535
  * @return string $timestamp The timestamp including the GMT offset.
536
  */
537
+ public static function get_timestamp( $timestamp = false ) {
538
+ if ( false === $timestamp ) {
539
+ $timestamp = time();
540
+ }
541
  $gmtOffset = get_option( 'gmt_offset' );
542
+
543
  return ( $gmtOffset ? ( $gmtOffset * HOUR_IN_SECONDS ) + $timestamp : $timestamp );
544
  }
545
 
class/class-mainwp-pages.php CHANGED
@@ -190,14 +190,6 @@ class MainWP_Pages {
190
  $settingsPage = add_submenu_page( 'options-general.php', $child_page_title, $child_menu_title, 'manage_options', 'mainwp_child_tab', array( &$this, 'render_pages' ) );
191
 
192
  add_action( 'admin_print_scripts-' . $settingsPage, array( MainWP_Clone_Page::get_class_name(), 'print_scripts' ) );
193
- $subpageargs = array(
194
- 'child_slug' => 'options-general.php',
195
- 'branding' => ( null === self::$brandingTitle ) ? 'MainWP' : self::$brandingTitle,
196
- 'parent_menu' => $settingsPage,
197
- );
198
-
199
- do_action_deprecated( 'mainwp-child-subpages', array( $subpageargs ), '4.0.7.1', 'mainwp_child_subpages' );
200
- do_action( 'mainwp_child_subpages', $subpageargs );
201
 
202
  $sub_pages = array();
203
 
190
  $settingsPage = add_submenu_page( 'options-general.php', $child_page_title, $child_menu_title, 'manage_options', 'mainwp_child_tab', array( &$this, 'render_pages' ) );
191
 
192
  add_action( 'admin_print_scripts-' . $settingsPage, array( MainWP_Clone_Page::get_class_name(), 'print_scripts' ) );
 
 
 
 
 
 
 
 
193
 
194
  $sub_pages = array();
195
 
class/class-mainwp-security.php CHANGED
@@ -602,6 +602,23 @@ class MainWP_Security {
602
  if ( ! self::remove_readme_ok() ) {
603
  $total_issues ++;
604
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
605
  return $total_issues;
606
  }
607
 
@@ -622,6 +639,7 @@ class MainWP_Security {
622
  return ! empty( $security ) && isset( $security[ $option ] ) && ( true === $security[ $option ] );
623
  }
624
 
 
625
  /**
626
  * Method update_security_option()
627
  *
@@ -637,4 +655,54 @@ class MainWP_Security {
637
  }
638
  MainWP_Helper::update_option( 'mainwp_security', $security, 'yes' );
639
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
640
  }
602
  if ( ! self::remove_readme_ok() ) {
603
  $total_issues ++;
604
  }
605
+
606
+ if ( ! self::wpcore_updated_ok() ) {
607
+ $total_issues ++;
608
+ }
609
+
610
+ if ( ! self::phpversion_ok() ) {
611
+ $total_issues ++;
612
+ }
613
+
614
+ if ( ! self::sslprotocol_ok() ) {
615
+ $total_issues ++;
616
+ }
617
+
618
+ if ( ! self::debug_disabled_ok() ) {
619
+ $total_issues ++;
620
+ }
621
+
622
  return $total_issues;
623
  }
624
 
639
  return ! empty( $security ) && isset( $security[ $option ] ) && ( true === $security[ $option ] );
640
  }
641
 
642
+
643
  /**
644
  * Method update_security_option()
645
  *
655
  }
656
  MainWP_Helper::update_option( 'mainwp_security', $security, 'yes' );
657
  }
658
+
659
+ /**
660
+ * Method wpcore_updated_ok()
661
+ *
662
+ * Check WP core updated.
663
+ */
664
+ public static function wpcore_updated_ok() {
665
+ include_once ABSPATH . '/wp-admin/includes/update.php';
666
+ $ok = true;
667
+ $core_updates = get_core_updates();
668
+ foreach ( $core_updates as $core => $update ) {
669
+ if ( 'upgrade' === $update->response ) {
670
+ $ok = false;
671
+ }
672
+ }
673
+ return $ok;
674
+ }
675
+
676
+
677
+ /**
678
+ * Method phpversion_ok()
679
+ *
680
+ * Check PHP version matches the WP requirement.
681
+ */
682
+ public static function phpversion_ok() {
683
+ require_once ABSPATH . WPINC . '/version.php';
684
+ global $required_php_version;
685
+ return version_compare( phpversion(), $required_php_version, '>=' );
686
+ }
687
+
688
+ /**
689
+ * Method sslprotocol_ok()
690
+ *
691
+ * Check SSL protocol is in place.
692
+ */
693
+ public static function sslprotocol_ok() {
694
+ return is_ssl();
695
+ }
696
+
697
+
698
+ /**
699
+ * Method debug_disabled_ok()
700
+ *
701
+ * Check WP Config and check if debugging is disabled.
702
+ */
703
+ public static function debug_disabled_ok() {
704
+ $ok = ! defined( 'WP_DEBUG' ) || ! WP_DEBUG;
705
+ $ok = $ok && ( ! defined( 'WP_DEBUG_LOG' ) || ! WP_DEBUG_LOG );
706
+ return $ok;
707
+ }
708
  }
class/class-mainwp-utility.php CHANGED
@@ -7,7 +7,7 @@
7
 
8
  namespace MainWP\Child;
9
 
10
- // phpcs:disable WordPress.WP.AlternativeFunctions -- Custom functions required to achieve desired results, pull request solutions appreciated.
11
 
12
  /**
13
  * Class MainWP_Utility
@@ -114,142 +114,27 @@ class MainWP_Utility {
114
  }
115
 
116
  /**
117
- * Method maintenance_alert()
118
  *
119
- * MainWP Maintenance Extension feature to send email notification for 404 (Page not found) errors.
120
- */
121
- public function maintenance_alert() {
122
- if ( ! is_404() ) {
123
- return;
124
- }
125
-
126
- if ( 1 !== (int) get_option( 'mainwp_maintenance_opt_alert_404' ) ) {
127
- return;
128
- }
129
-
130
- $email = get_option( 'mainwp_maintenance_opt_alert_404_email' );
131
-
132
- if ( empty( $email ) || ! preg_match( '/^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$/is', $email ) ) {
133
- return;
134
- }
135
-
136
- // set status.
137
- header( 'HTTP/1.1 404 Not Found' );
138
- header( 'Status: 404 Not Found' );
139
-
140
- // site info.
141
- $blog = get_bloginfo( 'name' );
142
- $site = get_bloginfo( 'url' ) . '/';
143
- $from_email = get_bloginfo( 'admin_email' );
144
-
145
- // referrer.
146
- $referer = isset( $_SERVER['HTTP_REFERER'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_REFERER'] ) ) : 'undefined';
147
-
148
- $protocol = isset( $_SERVER['HTTPS'] ) && strcasecmp( sanitize_text_field( wp_unslash( $_SERVER['HTTPS'] ) ), 'off' ) ? 'https://' : 'http://';
149
- // request URI.
150
- $request = isset( $_SERVER['REQUEST_URI'] ) && isset( $_SERVER['HTTP_HOST'] ) ? $protocol . sanitize_text_field( wp_unslash( $_SERVER['HTTP_HOST'] ) ) . wp_unslash( $_SERVER['REQUEST_URI'] ) : 'undefined';
151
-
152
- // query string.
153
- $string = isset( $_SERVER['QUERY_STRING'] ) ? sanitize_text_field( wp_unslash( $_SERVER['QUERY_STRING'] ) ) : 'undefined';
154
- // IP address.
155
- $address = isset( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ) : 'undefined';
156
-
157
- // user agent.
158
- $agent = isset( $_SERVER['HTTP_USER_AGENT'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) ) : 'undefined';
159
-
160
- // identity.
161
- $remote = isset( $_SERVER['REMOTE_IDENT'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REMOTE_IDENT'] ) ) : 'undefined';
162
-
163
- // log time.
164
- $time = sanitize_text_field( wp_unslash( date( 'F jS Y, h:ia', time() ) ) ); // phpcs:ignore -- Use local time to achieve desired results, pull request solutions appreciated.
165
-
166
- $mail = '<div>404 alert</div><div></div>' .
167
- '<div>TIME: ' . $time . '</div>' .
168
- '<div>*404: ' . $request . '</div>' .
169
- '<div>SITE: ' . $site . '</div>' .
170
- '<div>REFERRER: ' . $referer . '</div>' .
171
- '<div>QUERY STRING: ' . $string . '</div>' .
172
- '<div>REMOTE ADDRESS: ' . $address . '</div>' .
173
- '<div>REMOTE IDENTITY: ' . $remote . '</div>' .
174
- '<div>USER AGENT: ' . $agent . '</div>';
175
- wp_mail(
176
- $email,
177
- 'MainWP - 404 Alert: ' . $blog,
178
- self::format_email( $email, $mail ),
179
- array(
180
- 'content-type: text/html',
181
- )
182
- );
183
- }
184
-
185
- /**
186
- * Method format_email()
187
- *
188
- * Format emails.
189
  *
190
- * @param string $to_email Contains the send to email address.
191
- * @param string $body Contains the email content.
 
 
192
  *
193
- * @return string Return formatted email.
194
  */
195
- public static function format_email( $to_email, $body ) {
196
- return '<br>
197
- <div>
198
- <br>
199
- <div style="background:#ffffff;padding:0 1.618em;font:13px/20px Helvetica,Arial,Sans-serif;padding-bottom:50px!important">
200
- <div style="width:600px;background:#fff;margin-left:auto;margin-right:auto;margin-top:10px;margin-bottom:25px;padding:0!important;border:10px Solid #fff;border-radius:10px;overflow:hidden">
201
- <div style="display: block; width: 100%;border-bottom: 2px Solid #7fb100 ; overflow: hidden;">
202
- <div style="display: block; width: 95% ; margin-left: auto ; margin-right: auto ; padding: .5em 0 ;">
203
- <div style="float: left;font-size:45px;"><a href="https://mainwp.com">MainWP</a></div>
204
- <div style="float: right; margin-top: .6em ;">
205
- <span style="display: inline-block; margin-right: .8em;"><a href="https://mainwp.com/mainwp-extensions/" style="font-family: Helvetica, Sans; color: #7fb100; text-transform: uppercase; font-size: 14px;">Extensions</a></span>
206
- <span style="display: inline-block; margin-right: .8em;"><a style="font-family: Helvetica, Sans; color: #7fb100; text-transform: uppercase; font-size: 14px;" href="https://managers.mainwp.com/">Community</a></span>
207
- <span style="display: inline-block; margin-right: .8em;"><a style="font-family: Helvetica, Sans; color: #7fb100; text-transform: uppercase; font-size: 14px;" href="https://kb.mainwp.com/">Knowledgebase</a></span>
208
- </div><div style="clear: both;"></div>
209
- </div>
210
- </div>
211
- <div>
212
- <p>Hello MainWP User!<br></p>
213
- ' . $body . '
214
- <div></div>
215
- <br />
216
- <div>MainWP</div>
217
- <div><a href="https://www.MainWP.com" target="_blank">www.MainWP.com</a></div>
218
- <p></p>
219
- </div>
220
-
221
- <div style="display: block; width: 100% ; background: #1c1d1b;">
222
- <div style="display: block; width: 95% ; margin-left: auto ; margin-right: auto ; padding: .5em 0 ;">
223
- <div style="padding: .5em 0 ; float: left;"><p style="color: #fff; font-family: Helvetica, Sans; font-size: 12px ;">© 2013 MainWP. All Rights Reserved.</p></div>
224
- </div>
225
- </div>
226
- </div>
227
- <center>
228
- <br><br><br><br><br><br>
229
- <table border="0" cellpadding="0" cellspacing="0" width="100%" style="background-color:#ffffff;border-top:1px solid #e5e5e5">
230
- <tbody><tr>
231
- <td align="center" valign="top" style="padding-top:20px;padding-bottom:20px">
232
- <table border="0" cellpadding="0" cellspacing="0">
233
- <tbody><tr>
234
- <td align="center" valign="top" style="color:#606060;font-family:Helvetica,Arial,sans-serif;font-size:11px;line-height:150%;padding-right:20px;padding-bottom:5px;padding-left:20px;text-align:center">
235
- This email is sent from your MainWP Dashboard.
236
- <br>
237
- If you do not wish to receive these notices please re-check your preferences in the MainWP Settings page.
238
- <br>
239
- <br>
240
- </td>
241
- </tr>
242
- </tbody></table>
243
- </td>
244
- </tr>
245
- </tbody></table>
246
-
247
- </center>
248
- </div>
249
- </div>
250
- <br>';
251
  }
252
 
 
253
  /**
254
  * Method handle_shutdown()
255
  *
@@ -752,6 +637,119 @@ class MainWP_Utility {
752
  flush();
753
  }
754
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
755
  /**
756
  * Method create_nonce_without_session()
757
  *
@@ -821,7 +819,7 @@ class MainWP_Utility {
821
  * @return bool true|false If updated, return true, if the last backup time not updated, return false.
822
  */
823
  public static function update_lasttime_backup( $by, $time ) {
824
- $backup_by = array( 'backupbuddy', 'backupwordpress', 'backwpup', 'updraftplus', 'wptimecapsule' );
825
  if ( ! in_array( $by, $backup_by ) ) {
826
  return false;
827
  }
@@ -843,7 +841,7 @@ class MainWP_Utility {
843
  *
844
  * @return mixed If activated any of the supported backup systems, return the last backup timestamp.
845
  */
846
- public static function get_lasttime_backup( $by ) {
847
  if ( 'backupwp' == $by ) {
848
  $by = 'backupwordpress';
849
  }
@@ -875,6 +873,11 @@ class MainWP_Utility {
875
  $activated = false;
876
  }
877
  break;
 
 
 
 
 
878
  default:
879
  $activated = false;
880
  break;
@@ -887,6 +890,22 @@ class MainWP_Utility {
887
  return get_option( 'mainwp_lasttime_backup_' . $by, 0 );
888
  }
889
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
890
  /**
891
  * Method maybe_base64_decode()
892
  *
7
 
8
  namespace MainWP\Child;
9
 
10
+ // phpcs:disable WordPress.WP.AlternativeFunctions, Generic.Metrics.CyclomaticComplexity -- Custom functions required to achieve desired results, pull request solutions appreciated.
11
 
12
  /**
13
  * Class MainWP_Utility
114
  }
115
 
116
  /**
117
+ * Method send_wp_mail()
118
  *
119
+ * Sends notification email.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
  *
121
+ * @param string|array $to Array or comma-separated list of email addresses to send message.
122
+ * @param string $subject Email subject.
123
+ * @param string $message Message contents.
124
+ * @param string|array $headers Optional. Additional headers.
125
  *
126
+ * @return bool Whether the email contents were sent successfully.
127
  */
128
+ public function send_wp_mail( $to, $subject, $message, $headers = '' ) {
129
+ return wp_mail(
130
+ $to,
131
+ $subject,
132
+ $message,
133
+ $headers
134
+ );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
135
  }
136
 
137
+
138
  /**
139
  * Method handle_shutdown()
140
  *
637
  flush();
638
  }
639
 
640
+ /**
641
+ * Method send_maintenance_alert()
642
+ *
643
+ * MainWP Maintenance Extension feature to send email notification for 404 (Page not found) errors.
644
+ */
645
+ public function send_maintenance_alert() {
646
+ if ( ! is_404() ) {
647
+ return;
648
+ }
649
+
650
+ if ( 1 !== (int) get_option( 'mainwp_maintenance_opt_alert_404' ) ) {
651
+ return;
652
+ }
653
+
654
+ $email = get_option( 'mainwp_maintenance_opt_alert_404_email' );
655
+
656
+ if ( empty( $email ) || ! preg_match( '/^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$/is', $email ) ) {
657
+ return;
658
+ }
659
+
660
+ // set status.
661
+ header( 'HTTP/1.1 404 Not Found' );
662
+ header( 'Status: 404 Not Found' );
663
+
664
+ // site info.
665
+ $blog = get_bloginfo( 'name' );
666
+ $site = get_bloginfo( 'url' ) . '/';
667
+
668
+ // referrer.
669
+ $referer = isset( $_SERVER['HTTP_REFERER'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_REFERER'] ) ) : 'undefined';
670
+
671
+ $protocol = isset( $_SERVER['HTTPS'] ) && strcasecmp( sanitize_text_field( wp_unslash( $_SERVER['HTTPS'] ) ), 'off' ) ? 'https://' : 'http://';
672
+ // request URI.
673
+ $request = isset( $_SERVER['REQUEST_URI'] ) && isset( $_SERVER['HTTP_HOST'] ) ? $protocol . sanitize_text_field( wp_unslash( $_SERVER['HTTP_HOST'] ) . wp_strip_all_tags( wp_unslash( $_SERVER['REQUEST_URI'] ) ) ) : 'undefined';
674
+
675
+ // query string.
676
+ $string = isset( $_SERVER['QUERY_STRING'] ) ? sanitize_text_field( wp_strip_all_tags( wp_unslash( $_SERVER['QUERY_STRING'] ) ) ) : 'undefined';
677
+ // IP address.
678
+ $address = isset( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( wp_strip_all_tags( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ) ) : 'undefined';
679
+
680
+ // user agent.
681
+ $agent = isset( $_SERVER['HTTP_USER_AGENT'] ) ? sanitize_text_field( wp_strip_all_tags( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) ) ) : 'undefined';
682
+
683
+ // identity.
684
+ $remote = isset( $_SERVER['REMOTE_IDENT'] ) ? sanitize_text_field( wp_strip_all_tags( wp_unslash( $_SERVER['REMOTE_IDENT'] ) ) ) : 'undefined';
685
+
686
+ // log time.
687
+ $time = sanitize_text_field( wp_unslash( date( 'F jS Y, h:ia', time() ) ) ); // phpcs:ignore -- Use local time to achieve desired results, pull request solutions appreciated.
688
+
689
+ $mail = '<div>404 alert</div><div></div>' .
690
+ '<div>TIME: ' . $time . '</div>' .
691
+ '<div>*404: ' . $request . '</div>' .
692
+ '<div>SITE: ' . $site . '</div>' .
693
+ '<div>REFERRER: ' . $referer . '</div>' .
694
+ '<div>QUERY STRING: ' . $string . '</div>' .
695
+ '<div>REMOTE ADDRESS: ' . $address . '</div>' .
696
+ '<div>REMOTE IDENTITY: ' . $remote . '</div>' .
697
+ '<div>USER AGENT: ' . $agent . '</div>';
698
+ $this->send_wp_mail(
699
+ $email,
700
+ 'MainWP - 404 Alert: ' . $blog,
701
+ MainWP_Child_Format::format_email( $mail ),
702
+ array(
703
+ 'content-type: text/html',
704
+ )
705
+ );
706
+ }
707
+
708
+ /**
709
+ * Send support email.
710
+ *
711
+ * @return bool Return TRUE on success FALSE on failure.
712
+ *
713
+ * @uses \MainWP\Child\MainWP_Child_Branding::get_branding_options()
714
+ */
715
+ public function send_support_mail() {
716
+ $opts = MainWP_Child_Branding::instance()->get_branding_options();
717
+ $email = $opts['support_email'];
718
+ $sub = isset( $_POST['mainwp_branding_contact_message_subject'] ) ? wp_kses_post( nl2br( stripslashes( wp_unslash( $_POST['mainwp_branding_contact_message_subject'] ) ) ) ) : '';
719
+ $from = isset( $_POST['mainwp_branding_contact_send_from'] ) ? trim( wp_unslash( $_POST['mainwp_branding_contact_send_from'] ) ) : '';
720
+ $subject = ! empty( $sub ) ? $sub : 'MainWP - Support Contact';
721
+ $content = isset( $_POST['mainwp_branding_contact_message_content'] ) ? wp_kses_post( nl2br( stripslashes( wp_unslash( $_POST['mainwp_branding_contact_message_content'] ) ) ) ) : '';
722
+ $mail = '';
723
+ $headers = '';
724
+
725
+ $from_page = isset( $_POST['mainwp_branding_send_from_page'] ) ? wp_unslash( $_POST['mainwp_branding_send_from_page'] ) : '';
726
+
727
+ if ( ! empty( $_POST['mainwp_branding_contact_message_content'] ) && ! empty( $email ) ) {
728
+
729
+ /**
730
+ * Current user global.
731
+ *
732
+ * @global string
733
+ */
734
+ global $current_user;
735
+
736
+ $headers .= "Content-Type: text/html;charset=utf-8\r\n";
737
+ if ( ! empty( $from ) ) {
738
+ $headers .= 'From: "' . $from . '" <' . $from . ">\r\n";
739
+ }
740
+ $mail .= "<p>Support Email from: <a href='" . site_url() . "'>" . site_url() . "</a></p>\r\n\r\n";
741
+ $mail .= '<p>Sent from WordPress page: ' . ( ! empty( $from_page ) ? "<a href='" . esc_url( $from_page ) . "'>" . esc_url( $from_page ) . "</a></p>\r\n\r\n" : '' );
742
+ $mail .= '<p>Client Email: ' . $current_user->user_email . " </p>\r\n\r\n";
743
+ $mail .= "<p>Support Text:</p>\r\n\r\n";
744
+ $mail .= '<p>' . $content . "</p>\r\n\r\n";
745
+
746
+ self::instance()->send_wp_mail( $email, $subject, $mail, $headers );
747
+
748
+ return true;
749
+ }
750
+ return false;
751
+ }
752
+
753
  /**
754
  * Method create_nonce_without_session()
755
  *
819
  * @return bool true|false If updated, return true, if the last backup time not updated, return false.
820
  */
821
  public static function update_lasttime_backup( $by, $time ) {
822
+ $backup_by = array( 'backupbuddy', 'backupwordpress', 'backwpup', 'updraftplus', 'wptimecapsule', 'wpvivid' );
823
  if ( ! in_array( $by, $backup_by ) ) {
824
  return false;
825
  }
841
  *
842
  * @return mixed If activated any of the supported backup systems, return the last backup timestamp.
843
  */
844
+ public static function get_lasttime_backup( $by ) { // phpcs:ignore -- required to achieve desired results, pull request solutions appreciated.
845
  if ( 'backupwp' == $by ) {
846
  $by = 'backupwordpress';
847
  }
873
  $activated = false;
874
  }
875
  break;
876
+ case 'wpvivid':
877
+ if ( ! is_plugin_active( 'wpvivid-backuprestore/wpvivid-backuprestore.php' ) ) {
878
+ $activated = false;
879
+ }
880
+ break;
881
  default:
882
  $activated = false;
883
  break;
890
  return get_option( 'mainwp_lasttime_backup_' . $by, 0 );
891
  }
892
 
893
+ /**
894
+ * Get an array of user roles
895
+ *
896
+ * @return array
897
+ */
898
+ public function get_roles() {
899
+ $wp_roles = new \WP_Roles();
900
+ $roles = array();
901
+
902
+ foreach ( $wp_roles->get_names() as $role => $label ) {
903
+ $roles[ $role ] = translate_user_role( $label );
904
+ }
905
+
906
+ return $roles;
907
+ }
908
+
909
  /**
910
  * Method maybe_base64_decode()
911
  *
includes/functions.php CHANGED
@@ -53,7 +53,7 @@ if ( isset( $_GET['bulk_settings_manageruse_nonce_key'] ) && isset( $_GET['bulk_
53
  * This is a fake post field to fix some conflict with wp_verify_nonce().
54
  * Just return false to unverify nonce, does not exit.
55
  */
56
- if ( isset( $_POST[ $action ] ) && ( 'mainwp-bsm-unverify-nonce' == $_POST[ $action ] ) ) {
57
  return false;
58
  }
59
 
@@ -93,7 +93,7 @@ if ( isset( $_GET['bulk_settings_manageruse_nonce_key'] ) && isset( $_GET['bulk_
93
  * This is a fake post field to fix some conflict with wp_verify_nonce().
94
  * Just return false to unverify nonce, does not exit.
95
  */
96
- if ( isset( $_POST[ $action ] ) && ( 'mainwp-bsm-unverify-nonce' == $_POST[ $action ] ) ) {
97
  return false;
98
  }
99
 
53
  * This is a fake post field to fix some conflict with wp_verify_nonce().
54
  * Just return false to unverify nonce, does not exit.
55
  */
56
+ if ( isset( $_REQUEST[ $action ] ) && ( 'mainwp-bsm-unverify-nonce' == $_REQUEST[ $action ] ) ) {
57
  return false;
58
  }
59
 
93
  * This is a fake post field to fix some conflict with wp_verify_nonce().
94
  * Just return false to unverify nonce, does not exit.
95
  */
96
+ if ( isset( $_REQUEST[ $action ] ) && ( 'mainwp-bsm-unverify-nonce' == $_REQUEST[ $action ] ) ) {
97
  return false;
98
  }
99
 
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.2.6
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.3
16
  * Requires at least: 5.4
17
  * Requires PHP: 7.0
18
  */
readme.txt CHANGED
@@ -1,47 +1,82 @@
1
- === MainWP Child - Securely connects sites to the MainWP WordPress Manager Dashboard ===
2
  Contributors: mainwp
3
- Tags: WordPress management, WordPress Manager, WordPress controller, multiple WordPress Sites, multisite
4
  Author: mainwp
5
  Author URI: https://mainwp.com
6
  Plugin URI: https://mainwp.com
7
  Requires at least: 5.4
8
- Tested up to: 6.1
9
  Requires PHP: 7.0
10
- Stable tag: 4.2.6
11
  License: GPLv3 or later
12
  License URI: https://www.gnu.org/licenses/gpl-3.0.html
13
 
14
- Securely connects unlimited sites to your MainWP WordPress Manager. The MainWP WordPress Management System is both open source and private.
15
 
16
  == Description ==
17
 
18
- The Child plugin connects your WordPress sites to the [MainWP WordPress Manager Dashboard](https://wordpress.org/plugins/mainwp/)
19
-
20
- The [MainWP WordPress Management](https://mainwp.com) system is self-hosted, open source, and private. Connect and control all the WordPress sites you administer, even those on different hosts and servers.
21
-
22
- MainWP is the perfect solution for WordPress consultants, marketers, developers, WordPress shops, or anyone with multiple WordPress sites
23
-
24
- = Your Guarantee of Privacy =
25
-
26
- The MainWP plugins come with their own [privacy policies](https://mainwp.com/mainwp-plugin-privacy-policy/) to ensure you that the plugins do not collect any personally identifiable information (PII). Please review them before activating the plugin.
27
-
28
- = How does the MainWP system work? =
29
-
30
- First, Install and Activate the [MainWP WordPress Manager Dashboard](https://wordpress.org/plugins/mainwp/) plugin on a WordPress site you will use for controlling all other sites; this is your Dashboard Site. We highly recommend this be a new, clean WordPress installation and not on one of your operating sites. Using a clean site helps to eliminate any unnecessary plugin conflicts or security issues.
31
-
32
- Next, Install and Activate the MainWP Child plugin (this plugin) on a WordPress site you want to connect to your MainWP Dashboard. WordPress sites connected to your Dashboard are referred to as Child sites.
33
-
34
- Lastly, you securely connect your child site to your MainWP Dashboard. Once connected, your Dashboard can control most aspects of the Child site.
35
-
36
- Still not sure how MainWP works? [Review these detailed steps on installing your Dashboard and connecting your first Child site.](https://mainwp.com/getting-started-with-mainwp/)
37
-
38
- **Features include:**
39
-
40
- * Connect and control all your WordPress installs, even those on different hosts!
41
- * Update all WordPress installs, Plugins and Themes from one location
42
- * Manage and Add all your Posts from one location
43
- * Manage and Add all your Pages from one location
44
- * Run everything from 1 Dashboard that you host!
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
 
46
  = More Information =
47
  [MainWP Documentation](https://kb.mainwp.com/)
@@ -111,6 +146,12 @@ Sure we have a quick FAQ with a lot more questions and answers [here](https://ma
111
 
112
  == Changelog ==
113
 
 
 
 
 
 
 
114
  = 4.2.6 - 8-26-2022 =
115
  * Fixed: An issue with support for the new extension
116
 
1
+ === MainWP Child - Securely Connects Sites to the MainWP WordPress Manager Dashboard ===
2
  Contributors: mainwp
3
+ Tags: MainWP, MainWP Dashboard, WordPress Manager, WordPress Management, Manage WordPress, Manage Multiple Sites, Control Multiple Sites, WordPress Site Management, WordPress Management Dashboard, ManageWP, Manage WP Sites, WordPress Maintenance, Uptime Monitor, Backup, Security, Lighthouse, Client Reports, Manage Plugins, Updates Manager, Manage WordPress Websites, Client Management, REST API, Hooks
4
  Author: mainwp
5
  Author URI: https://mainwp.com
6
  Plugin URI: https://mainwp.com
7
  Requires at least: 5.4
8
+ Tested up to: 6.1.1
9
  Requires PHP: 7.0
10
+ Stable tag: 4.3
11
  License: GPLv3 or later
12
  License URI: https://www.gnu.org/licenses/gpl-3.0.html
13
 
14
+ Securely connects Unlimited WordPress sites to your MainWP Dashboard, allowing you to control them from a single screen.
15
 
16
  == Description ==
17
 
18
+ This is a Child Plugin for [MainWP Dashboard](https://wordpress.org/plugins/mainwp/) that connects your WordPress sites to the MainWP Dashboard.
19
+
20
+ The [MainWP](https://mainwp.com/), a complete WordPress Management solution, is self-hosted, open source, and private, allowing you to control multiple WordPress websites (even those on different hosting) from your own private self-hosted WordPress website.
21
+
22
+ MainWP is the **perfect solution for**
23
+ - Agencies
24
+ - Freelancers
25
+ - Developers
26
+ - Designers
27
+ - Consultants
28
+ - Marketers
29
+ - In fact, anyone who wants to manage multiple WordPress sites
30
+
31
+ == Here’s Why WordPress Managers Love MainWP! ==
32
+ 💰 Free Forever
33
+ 🏷️ White Label
34
+ ♾️ Connect Unlimited Websites
35
+ 👥 Full Client Management
36
+ 🌐 Organize Sites via Tags
37
+ 🕒 Uptime & Site Health Monitoring
38
+ 🚩 1-Click Lighthouse Stats
39
+ 🔄 Effortless Bulk Updates
40
+ 🚧 Staging, Cloning
41
+ 📝 Professional Reports
42
+ 🔒 Full Privacy, Self-hosted, Lock Your Dashboard
43
+ 💬 Bulk Manage Comments
44
+ 🛡️ Bulk Manage Security
45
+ 📈 SEO, Traffic, Analytics, etc.
46
+ 🚀 WP Rocket, Cache-Control
47
+ ✏️ Fully Customizable
48
+ 🌐 Domain Monitoring
49
+ 🔗 Security & Backup Integrations
50
+ 😌 Bulk Content Management (Draft, Publish, Edit, Trash)
51
+ 🦾 40+ Integrations
52
+
53
+ And [a lot more](https://mainwp.com/mainwp-extensions/)…
54
+
55
+ == HOW DOES THE MAINWP WORK? ==
56
+
57
+ First, Install and Activate the [MainWP WordPress Manager Dashboard](https://wordpress.org/plugins/mainwp/) plugin on a WordPress site you will use for controlling all other sites; this is your Dashboard Site.
58
+
59
+ We highly recommend this be a new, clean WordPress installation and not on one of your operating sites. Using a clean site helps to eliminate any unnecessary plugin conflicts or security issues.
60
+
61
+ Next, Install and Activate the MainWP Child plugin (this plugin) on all the WordPress sites you want to connect to your MainWP Dashboard. WordPress sites connected to your Dashboard are referred to as Child Sites.
62
+
63
+ Once connected, you can manage them from your MainWP Dashboard.
64
+
65
+ Still not sure how MainWP works? [Review these detailed steps on installing your Dashboard and connecting your first Child Site.](https://mainwp.com/getting-started-with-mainwp/)
66
+
67
+ == Features Include: ==
68
+
69
+ - Connect and control all your WordPress installs, even those on different hosts!
70
+ - Update all WordPress installs, Plugins, and Themes from one location
71
+ - Manage and Add all your Posts from one location
72
+ - Manage and Add all your Pages from one location
73
+ - Run everything from one Dashboard that you host!
74
+ - One-click login to your Child Sites
75
+ - Easy plugin management (Bulk update, add, remove, etc.)
76
+ - Fully customizable
77
+ - Self-Hosted, Private, and Open Source
78
+
79
+ To know more about the MainWP WordPress management system, take a look at the [MainWP Dashboard.](https://wordpress.org/plugins/mainwp/)
80
 
81
  = More Information =
82
  [MainWP Documentation](https://kb.mainwp.com/)
146
 
147
  == Changelog ==
148
 
149
+ = 4.3 - 11-16-2022 =
150
+ * Fixed: Multiple PHP warnings
151
+ * Added: Support for new security checks
152
+ * Added: Support for the Non-MainWP Changes feature
153
+ * Removed: Unused code
154
+
155
  = 4.2.6 - 8-26-2022 =
156
  * Fixed: An issue with support for the new extension
157