PluginProbe
MainWP Dashboard: Self-hosted WordPress Management for Agencies / trunk
MainWP Dashboard: Self-hosted WordPress Management for Agencies vtrunk
6.2 6.1.8 6.1.7 6.1.6 6.1.5 6.1.4 6.1.3 6.1.2 6.1.1 6.1 6.0.12 6.0.11 4.6.0.1 5.0 5.0.1 5.0.2 5.0.3 5.0.3.1 5.0.3.2 5.1 5.1.1 5.2 5.2.1 5.2.2 5.3 All 153 releases
mainwp / class / class-mainwp-post-site-handler.php

class-mainwp-post-site-handler.php in MainWP Dashboard: Self-hosted WordPress Management for Agencies trunk, at class/class-mainwp-post-site-handler.php

503 lines 18.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * MainWP Post Site Handler.
4 *
5 * @package MainWP/Dashboard
6 */
7
8 namespace MainWP\Dashboard;
9
10 // Exit if accessed directly.
11 if ( ! defined( 'ABSPATH' ) ) {
12 exit;
13 }
14
15 /**
16 * Class MainWP_Post_Site_Handler
17 *
18 * @package MainWP\Dashboard
19 *
20 * @uses \MainWP\Dashboard\MainWP_Post_Base_Handler
21 */
22 class MainWP_Post_Site_Handler extends MainWP_Post_Base_Handler { // phpcs:ignore Generic.Classes.OpeningBraceSameLine.ContentAfterBrace -- NOSONAR.
23
24 /**
25 * Private static variable to hold the single instance of the class.
26 *
27 * @static
28 *
29 * @var mixed Default null
30 */
31 private static $instance = null;
32
33 /**
34 * Method instance()
35 *
36 * Create MainWP Post Site Handler instance.
37 *
38 * @static
39 * @return self $instance MainWP_Post_Site_Handler.
40 */
41 public static function instance() {
42 if ( null === static::$instance ) {
43 static::$instance = new self();
44 }
45 return static::$instance;
46 }
47
48 /**
49 * Init site actions
50 */
51 public function init() {
52 // Page: ManageSites.
53 $this->add_action( 'mainwp_checkwp', array( &$this, 'mainwp_checkwp' ) );
54 $this->add_action( 'mainwp_addwp', array( &$this, 'mainwp_addwp' ) );
55 $this->add_action( 'mainwp_get_site_icon', array( &$this, 'get_site_icon' ) );
56 $this->add_action( 'mainwp_check_abandoned', array( &$this, 'check_abandoned' ) );
57
58 if ( \mainwp_current_user_can( 'dashboard', 'test_connection' ) ) {
59 $this->add_action( 'mainwp_testwp', array( &$this, 'mainwp_testwp' ) );
60 }
61
62 $this->add_action( 'mainwp_removesite', array( &$this, 'mainwp_removesite' ) );
63 $this->add_action( 'mainwp_reconnectwp', array( &$this, 'mainwp_reconnectwp' ) );
64 $this->add_action( 'mainwp_updatechildsite_value', array( &$this, 'mainwp_updatechildsite_value' ) );
65
66 // Page: ManageGroups.
67 $this->add_action( 'mainwp_group_rename', array( &$this, 'mainwp_group_rename' ) );
68 $this->add_action( 'mainwp_group_delete', array( &$this, 'mainwp_group_delete' ) );
69 $this->add_action( 'mainwp_group_add', array( &$this, 'mainwp_group_add' ) );
70
71 $this->add_action( 'mainwp_group_getsites', array( &$this, 'mainwp_group_getsites' ) );
72 $this->add_action( 'mainwp_group_updategroup', array( &$this, 'mainwp_group_updategroup' ) );
73
74 // Widget: RightNow.
75 $this->add_action( 'mainwp_syncsites', array( &$this, 'mainwp_syncsites' ) );
76
77 $this->add_action( 'mainwp_checksites', array( &$this, 'ajax_checksites' ) );
78 $this->add_action( 'mainwp_manage_sites_suspend_site', array( &$this, 'manage_suspend_site' ) );
79 $this->add_action( 'mainwp_group_sites_add', array( &$this, 'ajax_group_sites_add' ) );
80 }
81
82 /**
83 * Method mainwp_group_rename()
84 *
85 * Rename Group.
86 *
87 * @uses \MainWP\Dashboard\MainWP_Manage_Groups::rename_group()
88 */
89 public function mainwp_group_rename() {
90 $this->secure_request( 'mainwp_group_rename' );
91
92 MainWP_Manage_Groups::rename_group();
93 }
94
95 /**
96 * Method mainwp_group_delete()
97 *
98 * Delete Group.
99 *
100 * @uses \MainWP\Dashboard\MainWP_Manage_Groups::delete_group()
101 */
102 public function mainwp_group_delete() {
103 $this->secure_request( 'mainwp_group_delete' );
104
105 MainWP_Manage_Groups::delete_group();
106 }
107
108 /**
109 * Method mainwp_group_add()
110 *
111 * Add Group.
112 *
113 * @uses \MainWP\Dashboard\MainWP_Manage_Groups::add_group()
114 */
115 public function mainwp_group_add() {
116 $this->secure_request( 'mainwp_group_add' );
117 MainWP_Manage_Groups::add_group();
118 }
119
120 /**
121 * Method ajax_group_sites_add()
122 *
123 * Add Group in modal.
124 */
125 public function ajax_group_sites_add() {
126 $this->secure_request( 'mainwp_group_sites_add' );
127 // phpcs:disable WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
128 $newName = isset( $_POST['newName'] ) ? sanitize_text_field( wp_unslash( $_POST['newName'] ) ) : '';
129 $newColor = isset( $_POST['newColor'] ) ? sanitize_hex_color( wp_unslash( $_POST['newColor'] ) ) : '';
130 if ( empty( $newColor ) ) {
131 $newColor = '#cce2ff'; // default.
132 }
133 $selected_sites = isset( $_POST['selected_sites'] ) && is_array( $_POST['selected_sites'] ) ? array_map( 'intval', wp_unslash( $_POST['selected_sites'] ) ) : array();
134 $selected_sites = array_filter( $selected_sites );
135 // phpcs:enable
136 $success = false;
137 if ( ! empty( $newName ) ) {
138 $success = MainWP_Manage_Groups::add_group_sites( $newName, $selected_sites, $newColor );
139 }
140 if ( ! $success ) {
141 wp_die( wp_json_encode( array( 'error' => esc_html__( 'Unexpected error occurred. Please try again.', 'mainwp' ) ) ) );
142 } else {
143 wp_die( wp_json_encode( array( 'success' => $success ) ) );
144 }
145 }
146
147
148 /**
149 * Method mainwp_group_getsites()
150 *
151 * Get Child Sites in group.
152 */
153 public function mainwp_group_getsites() {
154
155 $this->secure_request( 'mainwp_group_getsites' );
156 //phpcs:disable WordPress.Security.NonceVerification.Missing
157 $groupid = isset( $_POST['groupId'] ) && ! empty( $_POST['groupId'] ) ? intval( $_POST['groupId'] ) : false; // phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
158 //phpcs:enable
159
160 if ( $groupid ) {
161 $group = MainWP_DB_Common::instance()->get_group_by_id( $groupid );
162 if ( ! empty( $group ) ) {
163 $websites = MainWP_DB::instance()->get_websites_by_group_id( $group->id );
164 $websiteIds = array();
165 if ( ! empty( $websites ) ) {
166 foreach ( $websites as $website ) {
167 $websiteIds[] = $website->id;
168 }
169 }
170
171 die( wp_json_encode( $websiteIds ) ); // phpcs:ignore WordPress.Security.EscapeOutput
172 }
173 }
174 die( 'ERROR' );
175 }
176
177 /**
178 * Method mainwp_group_updategroup()
179 *
180 * Update Group.
181 *
182 * @uses \MainWP\Dashboard\MainWP_Manage_Groups::update_group()
183 */
184 public function mainwp_group_updategroup() {
185 $this->secure_request( 'mainwp_group_updategroup' );
186
187 MainWP_Manage_Groups::update_group();
188 }
189
190 /**
191 * Method mainwp_checkwp()
192 *
193 * Check if WP can be added.
194 *
195 * @uses \MainWP\Dashboard\MainWP_Manage_Sites_Handler::check_site()
196 */
197 public function mainwp_checkwp() {
198 $this->check_security( 'mainwp_checkwp', 'security' );
199 MainWP_Manage_Sites_Handler::check_site();
200 }
201
202 /**
203 * Method mainwp_addwp()
204 *
205 * Add WP to the database.
206 *
207 * @uses \MainWP\Dashboard\MainWP_Manage_Sites_Handler::add_site()
208 */
209 public function mainwp_addwp() {
210 $this->check_security( 'mainwp_addwp', 'security' );
211 MainWP_Manage_Sites_Handler::add_site();
212 }
213
214 /**
215 * Method get_site_icon()
216 *
217 * Get Child Site Favicon.
218 *
219 * @uses \MainWP\Dashboard\MainWP_Sync::get_wp_icon()
220 */
221 public function get_site_icon() {
222 $this->check_security( 'mainwp_get_site_icon', 'security' );
223 $siteId = isset( $_POST['siteId'] ) ? intval( $_POST['siteId'] ) : null; // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
224 $result = MainWP_Sync::get_wp_icon( $siteId );
225 wp_send_json( $result );
226 }
227
228 /**
229 * Method check_abandoned()
230 *
231 * Check abandoned plugins or themes.
232 */
233 public function check_abandoned() {
234 $this->check_security( 'mainwp_check_abandoned', 'security' );
235 $siteId = isset( $_POST['siteId'] ) ? intval( $_POST['siteId'] ) : null; // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
236 $which = isset( $_POST['which'] ) ? sanitize_text_field( wp_unslash( $_POST['which'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
237 $result = MainWP_Utility::check_abandoned( $siteId, $which );
238 wp_send_json( $result );
239 }
240
241 /**
242 * Method mainwp_testwp()
243 *
244 * Test if Child Site can be reached.
245 *
246 * @uses \MainWP\Dashboard\MainWP_Connect::try_visit()
247 * @uses \MainWP\Dashboard\MainWP_DB::get_website_by_id()
248 * @uses \MainWP\Dashboard\MainWP_Utility::remove_http_prefix()
249 */
250 public function mainwp_testwp() { // phpcs:ignore -- NOSONAR - complex function. Current complexity is the only way to achieve desired results, pull request solutions appreciated.
251 $this->secure_request( 'mainwp_testwp' );
252
253 $url = null;
254 $name = null;
255 $http_user = null;
256 $http_pass = null;
257 $verifyCertificate = 1;
258 $sslVersion = 0;
259
260 // phpcs:disable WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
261 if ( isset( $_POST['url'] ) ) {
262 $url = sanitize_text_field( wp_unslash( $_POST['url'] ) );
263 $url = urldecode( $url );
264
265 $invalid = false;
266 $info = wp_parse_url( $url );
267
268 $def_not_allow = array( 21, 22 ); // not allow ports 21, 22.
269 $not_allow_ports = apply_filters( 'mainwp_connect_sites_not_allow_ports', $def_not_allow, $url );
270
271 if ( ! is_array( $not_allow_ports ) ) {
272 $not_allow_ports = $def_not_allow;
273 }
274
275 if ( is_array( $info ) && ! empty( $info['port'] ) && ( in_array( intval( $info['port'] ), $not_allow_ports, true ) ) ) {
276 $invalid = true;
277 }
278
279 $temp_url = MainWP_Utility::remove_http_prefix( $url, true );
280
281 if ( $invalid || false !== strpos( $url, '?=' ) ) {
282 die( wp_json_encode( array( 'error' => esc_html__( 'Invalid URL.', 'mainwp' ) ) ) );
283 }
284
285 if ( strpos( $temp_url, ':' ) ) {
286 $invalid = true;
287 $allow_ports = apply_filters( 'mainwp_connect_sites_allow_ports', array(), $url );
288 if ( ! empty( $allow_ports ) && is_array( $allow_ports ) && is_array( $info ) && ! empty( $info['port'] ) && ( in_array( intval( $info['port'] ), $allow_ports, true ) ) ) {
289 $invalid = false;
290 }
291 if ( $invalid ) {
292 die( wp_json_encode( array( 'error' => esc_html__( 'Invalid URL.', 'mainwp' ) ) ) );
293 }
294 }
295
296 $verifyCertificate = isset( $_POST['test_verify_cert'] ) ? intval( $_POST['test_verify_cert'] ) : 1;
297 $forceUseIPv4 = apply_filters( 'mainwp_manage_sites_force_use_ipv4', false, $url );
298 $sslVersion = isset( $_POST['ssl_version'] ) ? intval( $_POST['ssl_version'] ) : 0;
299 $http_user = isset( $_POST['http_user'] ) ? sanitize_text_field( wp_unslash( $_POST['http_user'] ) ) : '';
300 $http_pass = isset( $_POST['http_pass'] ) ? wp_unslash( $_POST['http_pass'] ) : '';
301
302 } elseif ( isset( $_POST['siteid'] ) ) {
303 $website = MainWP_DB::instance()->get_website_by_id( intval( $_POST['siteid'] ) );
304 if ( $website ) {
305 $url = $website->url;
306 $name = $website->name;
307 $verifyCertificate = (int) $website->verify_certificate;
308 $forceUseIPv4 = $website->force_use_ipv4;
309 $sslVersion = $website->ssl_version;
310 // MWP-1548: decrypt at the boundary so the reconnect /
311 // try_visit call below uses plaintext credentials.
312 $http_user = MainWP_Credential_Storage::decrypt_credential( $website->http_user );
313 $http_pass = MainWP_Credential_Storage::decrypt_credential( $website->http_pass );
314 }
315 }
316 // phpcs:enable
317
318 $ssl_verifyhost = false;
319
320 if ( 1 === $verifyCertificate ) {
321 $ssl_verifyhost = true;
322 } elseif ( 2 === $verifyCertificate ) {
323 if ( ( false === get_option( 'mainwp_sslVerifyCertificate' ) ) || ( 1 === (int) get_option( 'mainwp_sslVerifyCertificate' ) ) ) {
324 $ssl_verifyhost = true;
325 }
326 }
327
328 $rslt = MainWP_Connect::try_visit( $url, $ssl_verifyhost, $http_user, $http_pass, $sslVersion, $forceUseIPv4 );
329
330 if ( isset( $rslt['error'] ) && ( '' !== $rslt['error'] ) && ( 'wp-admin/' !== substr( $url, - 9 ) ) ) {
331 if ( substr( $url, - 1 ) !== '/' ) {
332 $url .= '/';
333 }
334 $url .= 'wp-admin/';
335 $newrslt = MainWP_Connect::try_visit( $url, $ssl_verifyhost, $http_user, $http_pass, $sslVersion, $forceUseIPv4 );
336 if ( isset( $newrslt['error'] ) && ( '' !== $rslt['error'] ) ) {
337 $rslt = $newrslt;
338 }
339 }
340
341 if ( null !== $name ) {
342 $rslt['sitename'] = esc_html( $name );
343 }
344
345 wp_send_json( $rslt );
346 }
347
348 /**
349 * Method mainwp_removesite()
350 *
351 * Remove a website from MainWP.
352 *
353 * @uses \MainWP\Dashboard\MainWP_Manage_Sites_Handler::remove_site()
354 */
355 public function mainwp_removesite() {
356 if ( ! \mainwp_current_user_can( 'dashboard', 'delete_sites' ) ) {
357 die( wp_json_encode( array( 'error' => \mainwp_do_not_have_permissions( esc_html__( 'delete sites', 'mainwp' ), false ) ) ) );
358 }
359
360 $this->secure_request( 'mainwp_removesite' );
361
362 static::invalidate_warm_cache();
363
364 MainWP_Manage_Sites_Handler::remove_site();
365 }
366
367
368 /**
369 * Method invalidate_warm_cache()
370 */
371 public static function invalidate_warm_cache() {
372 MainWP_Cache_Warm_Helper::invalidate_manage_pages( array( 'managesites', 'mainwp_tab' ) );
373 }
374
375 /**
376 * Method mainwp_reconnectwp()
377 *
378 * Reconnect to Child Site.
379 *
380 * @uses \MainWP\Dashboard\MainWP_Manage_Sites_Handler::reconnect_site()
381 */
382 public function mainwp_reconnectwp() {
383 $this->secure_request( 'mainwp_reconnectwp' );
384
385 MainWP_Manage_Sites_Handler::reconnect_site();
386 }
387
388 /**
389 * Method mainwp_updatechildsite_value()
390 *
391 * Update Child Site value.
392 *
393 * @uses \MainWP\Dashboard\MainWP_Manage_Sites_Handler::update_child_site_value()
394 */
395 public function mainwp_updatechildsite_value() {
396 $this->secure_request( 'mainwp_updatechildsite_value' );
397
398 MainWP_Manage_Sites_Handler::update_child_site_value();
399 }
400
401 /**
402 * Method mainwp_syncsites()
403 *
404 * Sync Child Sites.
405 *
406 * @uses \MainWP\Dashboard\MainWP_Updates_Overview::dismiss_sync_errors()
407 */
408 public function mainwp_syncsites() {
409 $this->secure_request( 'mainwp_syncsites' );
410 MainWP_Updates_Overview::dismiss_sync_errors( false );
411
412 $website = null;
413 $wp_id = isset( $_POST['wp_id'] ) ? intval( $_POST['wp_id'] ) : false; // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
414 if ( $wp_id ) {
415 $website = MainWP_DB::instance()->get_website_by_id( $wp_id );
416 }
417
418 if ( null === $website ) {
419 die( wp_json_encode( array( 'error' => esc_html__( 'Site ID not found. Please reload the page and try again.', 'mainwp' ) ) ) );
420 }
421
422 if ( MainWP_Sync::sync_website( $website ) ) {
423 $website = MainWP_DB::instance()->get_website_by_id( $website->id ); // reload.
424 /**
425 * Fires immediately after website synced successfully.
426 *
427 * @since 4.6
428 *
429 * @param object $website website data.
430 */
431 do_action( 'mainwp_after_sync_site_success', $website );
432 die( wp_json_encode( array( 'result' => 'SUCCESS' ) ) );
433 }
434
435 $website = MainWP_DB::instance()->get_website_by_id( $website->id );
436
437 die( wp_json_encode( array( 'error' => esc_html( wp_strip_all_tags( $website->sync_errors ) ) ) ) );
438 }
439
440 /**
441 * Method ajax_checksites()
442 *
443 * Check Child Sites.
444 */
445 public function ajax_checksites() {
446 $this->secure_request( 'mainwp_checksites' );
447
448 $website = null;
449 if ( isset( $_POST['wp_id'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
450 $website = MainWP_DB::instance()->get_website_by_id( intval( $_POST['wp_id'] ) ); // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
451 }
452
453 if ( null === $website ) {
454 die( wp_json_encode( array( 'error' => esc_html__( 'Site ID not found. Please reload the page and try again.', 'mainwp' ) ) ) );
455 }
456
457 MainWP_Utility::end_session();
458 $result = MainWP_Monitoring_Handler::handle_check_website( $website );
459 MainWP_Utility::end_session();
460
461 if ( is_array( $result ) ) {
462 die( wp_json_encode( array( 'result' => 'success' ) ) );
463 } else {
464 die( wp_json_encode( array( 'error' => esc_html__( 'Request failed. Please, try again.', 'mainwp' ) ) ) );
465 }
466 }
467
468 /**
469 * Method mainwp_manage_sites_suspend_site()
470 *
471 * Check Child Sites.
472 *
473 * @uses \MainWP\Dashboard\MainWP_Sync::get_wp_icon()
474 */
475 public function manage_suspend_site() {
476 $this->secure_request( 'mainwp_manage_sites_suspend_site' );
477 $siteId = isset( $_POST['siteid'] ) ? intval( $_POST['siteid'] ) : null; // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
478 $suspended = isset( $_POST['suspended'] ) && '1' === $_POST['suspended'] ? 1 : 0; // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
479 $newValues = array(
480 'suspended' => $suspended,
481 );
482
483 if ( $siteId ) {
484 $website = MainWP_DB::instance()->get_website_by_id( $siteId );
485 if ( $website && $website->suspended != $suspended ) { //phpcs:ignore -- to valid.
486 MainWP_DB::instance()->update_website_values( $siteId, $newValues );
487 /**
488 * Fires immediately after website suspended/unsuspend.
489 *
490 * @since 4.5.1.1
491 *
492 * @param object $website website data.
493 * @param int $suspended The new suspended value.
494 */
495 do_action( 'mainwp_site_suspended', $website, $suspended );
496 }
497 wp_send_json( array( 'result' => 'success' ) );
498 } else {
499 wp_send_json( array( 'error' => 'Error: site id empty' ) );
500 }
501 }
502 }
503