| 1 |
<?php |
| 2 |
/** |
| 3 |
* This file handles all of the Bulk Installation Methods |
| 4 |
* for Plugins & Themes. |
| 5 |
* |
| 6 |
* @package MainWP/Dashboard |
| 7 |
*/ |
| 8 |
|
| 9 |
namespace MainWP\Dashboard; |
| 10 |
|
| 11 |
/** |
| 12 |
* Class MainWP_Install_Bulk |
| 13 |
* |
| 14 |
* @used-by MainWP_Plugins::InstallPlugins |
| 15 |
* @used-by MainWP_Themes::InstallThemes |
| 16 |
*/ |
| 17 |
class MainWP_Install_Bulk { |
| 18 |
|
| 19 |
/** |
| 20 |
* Get Class Name |
| 21 |
* |
| 22 |
* @return string __CLASS__ |
| 23 |
* |
| 24 |
* @uses self::init() |
| 25 |
*/ |
| 26 |
public static function get_class_name() { |
| 27 |
return __CLASS__; |
| 28 |
} |
| 29 |
|
| 30 |
/** |
| 31 |
* Method init() |
| 32 |
* |
| 33 |
* Instantiate the main page |
| 34 |
* |
| 35 |
* Has to be called in System constructor, |
| 36 |
* adds handling for the main page. |
| 37 |
*/ |
| 38 |
public static function init() { |
| 39 |
add_action( 'admin_init', array( self::get_class_name(), 'admin_init' ) ); |
| 40 |
} |
| 41 |
|
| 42 |
/** |
| 43 |
* Method admin_init() |
| 44 |
* |
| 45 |
* Handles the uploading of a file. |
| 46 |
* |
| 47 |
* @uses \MainWP\Dashboard\MainWP_QQ2_File_Uploader |
| 48 |
* @uses \MainWP\Dashboard\MainWP_System_Utility::get_mainwp_specific_dir() |
| 49 |
*/ |
| 50 |
public static function admin_init() { |
| 51 |
if ( isset( $_REQUEST['mainwp_do'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized |
| 52 |
if ( isset( $_REQUEST['qq_nonce'] ) && 'MainWP_Install_Bulk-uploadfile' === $_REQUEST['mainwp_do'] ) { // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized |
| 53 |
do_action( 'mainwp_secure_request', 'qq_nonce', 'qq_nonce' ); |
| 54 |
$allowedExtensions = array( 'zip' ); // Only zip allowed. |
| 55 |
// max file size in bytes. |
| 56 |
$sizeLimit = 2 * 1024 * 1024; // 2MB = max allowed. |
| 57 |
|
| 58 |
$uploader = new MainWP_QQ2_File_Uploader( $allowedExtensions, $sizeLimit ); |
| 59 |
$path = MainWP_System_Utility::get_mainwp_specific_dir( 'bulk' ); |
| 60 |
|
| 61 |
$result = $uploader->handle_upload( $path, true ); |
| 62 |
// to pass data through iframe you will need to encode all html tags. |
| 63 |
die( htmlspecialchars( wp_json_encode( $result ), ENT_NOQUOTES ) ); // phpcs:ignore WordPress.Security.EscapeOutput |
| 64 |
} |
| 65 |
} |
| 66 |
} |
| 67 |
|
| 68 |
|
| 69 |
/** |
| 70 |
* Method render_upload() |
| 71 |
* |
| 72 |
* Renders the upload sub part. |
| 73 |
* |
| 74 |
* @param string $type Plugin|Theme Type of upload. |
| 75 |
*/ |
| 76 |
public static function render_upload( $type ) { |
| 77 |
$title = ( 'plugin' === $type ) ? 'Plugins' : 'Themes'; |
| 78 |
$favorites_enabled = is_plugin_active( 'mainwp-favorites-extension/mainwp-favorites-extension.php' ); |
| 79 |
$cls = $favorites_enabled ? 'favorites-extension-enabled ' : ''; |
| 80 |
$cls .= ( 'plugin' === $type ) ? 'qq-upload-plugins' : ''; |
| 81 |
|
| 82 |
$disabled_upload = false; |
| 83 |
$disabled_functions = ini_get( 'disable_functions' ); |
| 84 |
if ( ! empty( $disable_functions ) ) { |
| 85 |
$disabled_functions_array = explode( ',', $disabled_functions ); |
| 86 |
if ( is_array( $disabled_functions_array ) && in_array( 'tmpfile', $disabled_functions_array ) ) { |
| 87 |
$disabled_upload = true; |
| 88 |
} |
| 89 |
} |
| 90 |
|
| 91 |
if ( $disabled_upload ) { |
| 92 |
?> |
| 93 |
<div class="ui red message"> |
| 94 |
<div><?php esc_html_e( 'MainWP has detected that the tmpfile() PHP function is disabled on your server. This function is essential for uploading and installing zip files for plugins and themes. Please enable the tmpfile() function on your server to proceed. Contact your hosting provider for assistance if needed.', 'mainwp' ); ?></div> |
| 95 |
</div> |
| 96 |
|
| 97 |
<div class="ui secondary center aligned padded segment"> |
| 98 |
<h2 class="ui icon header"> |
| 99 |
<i class="file archive outline icon" style="color: #ddd"></i> |
| 100 |
<div class="content" style="color: #ddd"> |
| 101 |
<?php esc_html_e( 'Upload .zip File', 'mainwp' ); ?> |
| 102 |
<div class="sub header" style="color: #ddd"><?php esc_html_e( 'If you have', 'mainwp' ); ?> <?php echo esc_html( strtolower( $title ) ); ?> <?php esc_html_e( 'in a .zip format, you may install it by uploading it here.', 'mainwp' ); ?></div> |
| 103 |
</div> |
| 104 |
</h2> |
| 105 |
|
| 106 |
<div class="ui hidden divider"></div> |
| 107 |
|
| 108 |
<div class="ui center aligned segment"> |
| 109 |
<div class="ui labeled icon massive green button disabled"> |
| 110 |
<i class="upload icon"></i> |
| 111 |
<?php esc_html_e( 'Upload Now', 'mainwp' ); ?> |
| 112 |
</div> |
| 113 |
</div> |
| 114 |
|
| 115 |
</div> |
| 116 |
<?php |
| 117 |
} else { |
| 118 |
?> |
| 119 |
<div class="ui secondary center aligned padded segment"> |
| 120 |
<h2 class="ui icon header"> |
| 121 |
<i class="file archive outline icon"></i> |
| 122 |
<div class="content"> |
| 123 |
<?php esc_html_e( 'Upload .zip File', 'mainwp' ); ?> |
| 124 |
<div class="sub header"><?php esc_html_e( 'If you have', 'mainwp' ); ?> <?php echo esc_html( strtolower( $title ) ); ?> <?php esc_html_e( 'in a .zip format, you may install it by uploading it here.', 'mainwp' ); ?></div> |
| 125 |
</div> |
| 126 |
</h2> |
| 127 |
|
| 128 |
<div class="ui hidden divider"></div> |
| 129 |
|
| 130 |
<div id="mainwp-file-uploader" class="<?php echo esc_attr( $cls ); ?>" > |
| 131 |
<noscript> |
| 132 |
<div class="ui message red"><?php esc_html_e( 'Please enable JavaScript to use file uploader.', 'mainwp' ); ?></div> |
| 133 |
</noscript> |
| 134 |
</div> |
| 135 |
|
| 136 |
<script> |
| 137 |
function createUploader() { |
| 138 |
var uploader = new qq.FileUploader( { |
| 139 |
element: document.getElementById( 'mainwp-file-uploader' ), |
| 140 |
action: location.href, |
| 141 |
<?php |
| 142 |
/** |
| 143 |
* Uploader options |
| 144 |
* |
| 145 |
* Adds extra options to the bulk upload process as a support for the Favorites extension. |
| 146 |
* |
| 147 |
* @param string $type Determines if plugins or themes are being installed. |
| 148 |
* |
| 149 |
* @since Unknown |
| 150 |
*/ |
| 151 |
$extraOptions = apply_filters( 'mainwp_uploadbulk_uploader_options', '', $type ); |
| 152 |
$extraOptions = trim( $extraOptions ); |
| 153 |
$extraOptions = trim( trim( $extraOptions, ',' ) ); |
| 154 |
if ( '' !== $extraOptions ) { |
| 155 |
echo wp_strip_all_tags( $extraOptions ) . ','; // phpcs:ignore WordPress.Security.EscapeOutput |
| 156 |
} |
| 157 |
?> |
| 158 |
params: {mainwp_do: 'MainWP_Install_Bulk-uploadfile', qq_nonce: '<?php echo esc_js( wp_create_nonce( 'qq_nonce' ) ); ?>' } |
| 159 |
} ); |
| 160 |
} |
| 161 |
|
| 162 |
// in your app create uploader as soon as the DOM is ready. |
| 163 |
// don't wait for the window to load. |
| 164 |
createUploader(); |
| 165 |
</script> |
| 166 |
</div> |
| 167 |
<?php |
| 168 |
} |
| 169 |
} |
| 170 |
|
| 171 |
/** |
| 172 |
* Method prepare_install() |
| 173 |
* |
| 174 |
* Prepare for the installation. |
| 175 |
* |
| 176 |
* Grab all the necessary data to make the upload and prepare json response. |
| 177 |
* |
| 178 |
* @uses \MainWP\Dashboard\MainWP_DB::query() |
| 179 |
* @uses \MainWP\Dashboard\MainWP_DB::get_website_by_id() |
| 180 |
* @uses \MainWP\Dashboard\MainWP_DB::get_sql_websites_by_group_id() |
| 181 |
* @uses \MainWP\Dashboard\MainWP_DB::fetch_object() |
| 182 |
* @uses \MainWP\Dashboard\MainWP_DB::free_result() |
| 183 |
* @uses \MainWP\Dashboard\MainWP_System_Utility::get_mainwp_dir() |
| 184 |
* @uses \MainWP\Dashboard\MainWP_Utility::ctype_digit() |
| 185 |
* @uses \MainWP\Dashboard\MainWP_Utility::map_site() |
| 186 |
*/ |
| 187 |
public static function prepare_install() { // phpcs:ignore -- Current complexity is the only way to achieve desired results, pull request solutions appreciated. |
| 188 |
include_once ABSPATH . '/wp-admin/includes/plugin-install.php'; |
| 189 |
// phpcs:disable WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized |
| 190 |
|
| 191 |
$type = 'theme'; |
| 192 |
if ( isset( $_POST['type'] ) && 'plugin' === $_POST['type'] ) { |
| 193 |
$type = 'plugin'; |
| 194 |
} |
| 195 |
if ( ! isset( $_POST['url'] ) ) { |
| 196 |
$api = MainWP_System_Utility::get_plugin_theme_info( |
| 197 |
$type, |
| 198 |
array( |
| 199 |
'slug' => isset( $_POST['slug'] ) ? wp_unslash( $_POST['slug'] ) : '', |
| 200 |
'fields' => array( 'sections' => false ), |
| 201 |
) |
| 202 |
); // Save on a bit of bandwidth. |
| 203 |
|
| 204 |
$url = $api->download_link; |
| 205 |
$url = apply_filters( 'mainwp_prepare_install_download_url', $url, $_POST ); |
| 206 |
} else { |
| 207 |
$url = isset( $_POST['url'] ) ? wp_unslash( $_POST['url'] ) : ''; |
| 208 |
|
| 209 |
$mwpDir = MainWP_System_Utility::get_mainwp_dir(); |
| 210 |
$mwpUrl = $mwpDir[1]; |
| 211 |
if ( stristr( $url, $mwpUrl ) ) { |
| 212 |
$fullFile = $mwpDir[0] . str_replace( $mwpUrl, '', $url ); |
| 213 |
$url = admin_url( '?sig=' . MainWP_System_Utility::get_download_sig( $fullFile ) . '&mwpdl=' . rawurlencode( str_replace( $mwpDir[0], '', $fullFile ) ) ); |
| 214 |
} |
| 215 |
} |
| 216 |
|
| 217 |
$output = array(); |
| 218 |
$output['url'] = $url; |
| 219 |
$output['slug'] = isset( $_POST['slug'] ) ? sanitize_text_field( wp_unslash( $_POST['slug'] ) ) : ''; |
| 220 |
$output['name'] = isset( $_POST['name'] ) ? sanitize_text_field( wp_unslash( $_POST['name'] ) ) : ''; |
| 221 |
$output['sites'] = array(); |
| 222 |
|
| 223 |
$data_fields = array( |
| 224 |
'id', |
| 225 |
'url', |
| 226 |
'name', |
| 227 |
'sync_errors', |
| 228 |
); |
| 229 |
|
| 230 |
if ( isset( $_POST['selected_by'] ) && 'site' === $_POST['selected_by'] ) { |
| 231 |
$selected_sites = isset( $_POST['selected_sites'] ) && is_array( $_POST['selected_sites'] ) ? array_map( 'sanitize_text_field', wp_unslash( $_POST['selected_sites'] ) ) : array(); |
| 232 |
// Get sites. |
| 233 |
foreach ( $selected_sites as $enc_id ) { |
| 234 |
$websiteid = $enc_id; |
| 235 |
if ( MainWP_Utility::ctype_digit( $websiteid ) ) { |
| 236 |
$website = MainWP_DB::instance()->get_website_by_id( $websiteid ); |
| 237 |
$output['sites'][ $website->id ] = MainWP_Utility::map_site( |
| 238 |
$website, |
| 239 |
array( |
| 240 |
'id', |
| 241 |
'url', |
| 242 |
'name', |
| 243 |
) |
| 244 |
); |
| 245 |
} |
| 246 |
} |
| 247 |
} elseif ( isset( $_POST['selected_by'] ) && 'client' === $_POST['selected_by'] ) { |
| 248 |
$selected_clients = isset( $_POST['selected_clients'] ) && is_array( $_POST['selected_clients'] ) ? array_map( 'sanitize_text_field', wp_unslash( $_POST['selected_clients'] ) ) : array(); |
| 249 |
$websites = MainWP_DB_Client::instance()->get_websites_by_client_ids( |
| 250 |
$selected_clients, |
| 251 |
array( |
| 252 |
'select_data' => $data_fields, |
| 253 |
) |
| 254 |
); |
| 255 |
// Get sites. |
| 256 |
if ( $websites ) { |
| 257 |
foreach ( $websites as $website ) { |
| 258 |
if ( '' !== $website->sync_errors || MainWP_System_Utility::is_suspended_site( $website ) ) { |
| 259 |
continue; |
| 260 |
} |
| 261 |
$output['sites'][ $website->id ] = MainWP_Utility::map_site( |
| 262 |
$website, |
| 263 |
array( |
| 264 |
'id', |
| 265 |
'url', |
| 266 |
'name', |
| 267 |
) |
| 268 |
); |
| 269 |
} |
| 270 |
} |
| 271 |
} else { |
| 272 |
$selected_groups = ( isset( $_POST['selected_groups'] ) && is_array( $_POST['selected_groups'] ) ) ? array_map( 'sanitize_text_field', wp_unslash( $_POST['selected_groups'] ) ) : array(); |
| 273 |
// Get sites from group. |
| 274 |
foreach ( $selected_groups as $enc_id ) { |
| 275 |
$groupid = $enc_id; |
| 276 |
if ( MainWP_Utility::ctype_digit( $groupid ) ) { |
| 277 |
$websites = MainWP_DB::instance()->query( MainWP_DB::instance()->get_sql_websites_by_group_id( $groupid ) ); |
| 278 |
while ( $websites && ( $website = MainWP_DB::fetch_object( $websites ) ) ) { |
| 279 |
if ( '' !== $website->sync_errors || MainWP_System_Utility::is_suspended_site( $website ) ) { |
| 280 |
continue; |
| 281 |
} |
| 282 |
$output['sites'][ $website->id ] = MainWP_Utility::map_site( |
| 283 |
$website, |
| 284 |
array( |
| 285 |
'id', |
| 286 |
'url', |
| 287 |
'name', |
| 288 |
) |
| 289 |
); |
| 290 |
} |
| 291 |
MainWP_DB::free_result( $websites ); |
| 292 |
} |
| 293 |
} |
| 294 |
} |
| 295 |
// phpcs:enable |
| 296 |
|
| 297 |
/** |
| 298 |
* Filter: mainwp_bulk_prepare_install_result |
| 299 |
* |
| 300 |
* Fires after plugin/theme prepare install. |
| 301 |
* |
| 302 |
* @since 4.6 |
| 303 |
*/ |
| 304 |
$output = apply_filters( 'mainwp_bulk_prepare_install_result', $output, $type ); |
| 305 |
mainwp_send_json_output( $output ); |
| 306 |
} |
| 307 |
|
| 308 |
|
| 309 |
/** |
| 310 |
* Method addition_post_data() |
| 311 |
* |
| 312 |
* Grab Post addition data. |
| 313 |
* |
| 314 |
* @param array $post_data Data for post. |
| 315 |
* |
| 316 |
* @return mixed $post_data Bulk post addition data. |
| 317 |
*/ |
| 318 |
public static function addition_post_data( &$post_data = array() ) { |
| 319 |
|
| 320 |
/** |
| 321 |
* Clean and Lock extension options |
| 322 |
* |
| 323 |
* Adds additional options related to Clean and Lock options in order to avoid conflicts when HTTP Basic auth is set. |
| 324 |
* |
| 325 |
* @since Unknown |
| 326 |
*/ |
| 327 |
$clear_and_lock_opts = apply_filters( 'mainwp_clear_and_lock_options', array() ); |
| 328 |
if ( isset( $post_data['url'] ) && false !== strpos( $post_data['url'], 'mwpdl' ) && false !== strpos( $post_data['url'], 'sig' ) ) { |
| 329 |
if ( is_array( $clear_and_lock_opts ) && isset( $clear_and_lock_opts['wpadmin_user'] ) && ! empty( $clear_and_lock_opts['wpadmin_user'] ) && isset( $clear_and_lock_opts['wpadmin_passwd'] ) && ! empty( $clear_and_lock_opts['wpadmin_passwd'] ) ) { |
| 330 |
$post_data['wpadmin_user'] = $clear_and_lock_opts['wpadmin_user']; |
| 331 |
$post_data['wpadmin_passwd'] = $clear_and_lock_opts['wpadmin_passwd']; |
| 332 |
} |
| 333 |
} |
| 334 |
return $post_data; |
| 335 |
} |
| 336 |
|
| 337 |
/** |
| 338 |
* Perform Install. |
| 339 |
* |
| 340 |
* @uses \MainWP\Dashboard\MainWP_Connect::fetch_url_authed() |
| 341 |
* @uses \MainWP\Dashboard\MainWP_DB::get_website_by_id() |
| 342 |
* @uses \MainWP\Dashboard\MainWP_Utility::end_session() |
| 343 |
*/ |
| 344 |
public static function perform_install() { |
| 345 |
MainWP_Utility::end_session(); |
| 346 |
|
| 347 |
// phpcs:disable WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized |
| 348 |
// Fetch info. |
| 349 |
$type = isset( $_POST['type'] ) ? sanitize_text_field( wp_unslash( $_POST['type'] ) ) : ''; |
| 350 |
$post_data = array( |
| 351 |
'type' => $type, |
| 352 |
); |
| 353 |
if ( isset( $_POST['activatePlugin'] ) && 'true' === $_POST['activatePlugin'] ) { |
| 354 |
$post_data['activatePlugin'] = 'yes'; |
| 355 |
} |
| 356 |
if ( isset( $_POST['overwrite'] ) && 'true' === $_POST['overwrite'] ) { |
| 357 |
$post_data['overwrite'] = true; |
| 358 |
} |
| 359 |
|
| 360 |
/** |
| 361 |
* Addition Post Data. |
| 362 |
* |
| 363 |
* @param $post_data The post data. |
| 364 |
* @deprecated From. |
| 365 |
* @since 3.5.6. |
| 366 |
*/ |
| 367 |
self::addition_post_data( $post_data ); |
| 368 |
|
| 369 |
$site_id = isset( $_POST['siteId'] ) ? intval( $_POST['siteId'] ) : 0; |
| 370 |
$website = MainWP_DB::instance()->get_website_by_id( $site_id ); |
| 371 |
|
| 372 |
// to support demo data. |
| 373 |
if ( MainWP_Demo_Handle::get_instance()->is_demo_website( $website ) ) { |
| 374 |
return MainWP_Demo_Handle::get_instance()->handle_action_demo( $website, 'perform_install' ); |
| 375 |
} |
| 376 |
|
| 377 |
$websites = array( $website ); |
| 378 |
|
| 379 |
/** |
| 380 |
* Perform insatallation additional data |
| 381 |
* |
| 382 |
* Adds support for additional data such as HTTP User and HTTP Password. |
| 383 |
* |
| 384 |
* @param array $post_data Array containg the post data. |
| 385 |
* |
| 386 |
* @since Unknown |
| 387 |
*/ |
| 388 |
$post_data = apply_filters( 'mainwp_perform_install_data', $post_data ); |
| 389 |
|
| 390 |
$post_data['url'] = isset( $_POST['url'] ) ? wp_json_encode( wp_unslash( $_POST['url'] ) ) : ''; |
| 391 |
|
| 392 |
$output = new \stdClass(); |
| 393 |
$output->ok = array(); |
| 394 |
$output->errors = array(); |
| 395 |
$output->results = array(); |
| 396 |
$output->other_data = array(); |
| 397 |
|
| 398 |
// phpcs:enable |
| 399 |
/** |
| 400 |
* Action: mainwp_before_plugin_theme_install |
| 401 |
* |
| 402 |
* Fires before plugin/theme install. |
| 403 |
* |
| 404 |
* @since 4.1 |
| 405 |
*/ |
| 406 |
do_action( 'mainwp_before_plugin_theme_install', $post_data, $websites ); |
| 407 |
|
| 408 |
MainWP_Connect::fetch_urls_authed( |
| 409 |
$websites, |
| 410 |
'installplugintheme', |
| 411 |
$post_data, |
| 412 |
array( |
| 413 |
self::get_class_name(), |
| 414 |
'install_plugin_theme_handler', |
| 415 |
), |
| 416 |
$output, |
| 417 |
null, |
| 418 |
array( 'upgrade' => true ) |
| 419 |
); |
| 420 |
|
| 421 |
$output_obj = $output; |
| 422 |
|
| 423 |
mainwp_get_actions_handler_instance()->do_action_mainwp_install_actions( $websites, 'install', $output_obj, $type, $post_data ); |
| 424 |
|
| 425 |
/** |
| 426 |
* Action: mainwp_after_plugin_theme_install |
| 427 |
* |
| 428 |
* Fires after plugin/theme install. |
| 429 |
* |
| 430 |
* @since 4.1 |
| 431 |
*/ |
| 432 |
do_action( 'mainwp_after_plugin_theme_install', $output, $post_data, $websites ); |
| 433 |
|
| 434 |
wp_send_json( $output ); |
| 435 |
} |
| 436 |
|
| 437 |
/** |
| 438 |
* Method prepare_upload() |
| 439 |
* |
| 440 |
* Prepare the upload. |
| 441 |
* |
| 442 |
* @uses \MainWP\Dashboard\MainWP_DB::query() |
| 443 |
* @uses \MainWP\Dashboard\MainWP_DB::get_website_by_id() |
| 444 |
* @uses \MainWP\Dashboard\MainWP_DB::fetch_object() |
| 445 |
* @uses \MainWP\Dashboard\MainWP_DB::free_result() |
| 446 |
* @uses \MainWP\Dashboard\MainWP_System_Utility::get_download_url() |
| 447 |
* @uses \MainWP\Dashboard\MainWP_Utility::ctype_digit() |
| 448 |
* @uses \MainWP\Dashboard\MainWP_Utility::map_site() |
| 449 |
*/ |
| 450 |
public static function prepare_upload() { // phpcs:ignore -- comlex function. Current complexity is the only way to achieve desired results, pull request solutions appreciated. |
| 451 |
include_once ABSPATH . '/wp-admin/includes/plugin-install.php'; |
| 452 |
|
| 453 |
$output = array(); |
| 454 |
$output['sites'] = array(); |
| 455 |
|
| 456 |
$data_fields = array( |
| 457 |
'id', |
| 458 |
'url', |
| 459 |
'name', |
| 460 |
'sync_errors', |
| 461 |
); |
| 462 |
// phpcs:disable WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized |
| 463 |
if ( isset( $_POST['selected_by'] ) && 'site' === $_POST['selected_by'] ) { |
| 464 |
$selected_sites = isset( $_POST['selected_sites'] ) && is_array( $_POST['selected_sites'] ) ? array_map( 'sanitize_text_field', wp_unslash( $_POST['selected_sites'] ) ) : array(); |
| 465 |
// Get sites. |
| 466 |
foreach ( $selected_sites as $enc_id ) { |
| 467 |
$websiteid = $enc_id; |
| 468 |
if ( MainWP_Utility::ctype_digit( $websiteid ) ) { |
| 469 |
$website = MainWP_DB::instance()->get_website_by_id( $websiteid ); |
| 470 |
$output['sites'][ $website->id ] = MainWP_Utility::map_site( |
| 471 |
$website, |
| 472 |
array( |
| 473 |
'id', |
| 474 |
'url', |
| 475 |
'name', |
| 476 |
) |
| 477 |
); |
| 478 |
} |
| 479 |
} |
| 480 |
} elseif ( isset( $_POST['selected_by'] ) && 'client' === $_POST['selected_by'] ) { |
| 481 |
$selected_clients = isset( $_POST['selected_clients'] ) && is_array( $_POST['selected_clients'] ) ? array_map( 'sanitize_text_field', wp_unslash( $_POST['selected_clients'] ) ) : array(); |
| 482 |
$websites = MainWP_DB_Client::instance()->get_websites_by_client_ids( |
| 483 |
$selected_clients, |
| 484 |
array( |
| 485 |
'select_data' => $data_fields, |
| 486 |
) |
| 487 |
); |
| 488 |
// Get sites. |
| 489 |
if ( $websites ) { |
| 490 |
foreach ( $websites as $website ) { |
| 491 |
if ( '' !== $website->sync_errors || MainWP_System_Utility::is_suspended_site( $website ) ) { |
| 492 |
continue; |
| 493 |
} |
| 494 |
$output['sites'][ $website->id ] = MainWP_Utility::map_site( |
| 495 |
$website, |
| 496 |
array( |
| 497 |
'id', |
| 498 |
'url', |
| 499 |
'name', |
| 500 |
) |
| 501 |
); |
| 502 |
} |
| 503 |
} |
| 504 |
} else { |
| 505 |
$selected_groups = ( isset( $_POST['selected_groups'] ) && is_array( $_POST['selected_groups'] ) ) ? array_map( 'sanitize_text_field', wp_unslash( $_POST['selected_groups'] ) ) : array(); |
| 506 |
// Get sites from group. |
| 507 |
foreach ( $selected_groups as $enc_id ) { |
| 508 |
$groupid = $enc_id; |
| 509 |
if ( MainWP_Utility::ctype_digit( $groupid ) ) { |
| 510 |
$websites = MainWP_DB::instance()->query( MainWP_DB::instance()->get_sql_websites_by_group_id( $groupid ) ); |
| 511 |
while ( $websites && ( $website = MainWP_DB::fetch_object( $websites ) ) ) { |
| 512 |
if ( '' !== $website->sync_errors || MainWP_System_Utility::is_suspended_site( $website ) ) { |
| 513 |
continue; |
| 514 |
} |
| 515 |
$output['sites'][ $website->id ] = MainWP_Utility::map_site( |
| 516 |
$website, |
| 517 |
array( |
| 518 |
'id', |
| 519 |
'url', |
| 520 |
'name', |
| 521 |
) |
| 522 |
); |
| 523 |
} |
| 524 |
MainWP_DB::free_result( $websites ); |
| 525 |
} |
| 526 |
} |
| 527 |
} |
| 528 |
|
| 529 |
$output['urls'] = array(); |
| 530 |
$files = isset( $_POST['files'] ) && is_array( $_POST['files'] ) ? wp_unslash( $_POST['files'] ) : array(); |
| 531 |
foreach ( $files as $file ) { |
| 532 |
$output['urls'][] = MainWP_System_Utility::get_download_url( 'bulk', $file ); |
| 533 |
} |
| 534 |
$output['urls'] = implode( '||', $output['urls'] ); |
| 535 |
// phpcs:enable |
| 536 |
|
| 537 |
/** |
| 538 |
* Prepare upload |
| 539 |
* |
| 540 |
* Prepares upload URLs for the bulk install process. |
| 541 |
* |
| 542 |
* @since Unknown |
| 543 |
*/ |
| 544 |
$output['urls'] = apply_filters( 'mainwp_installbulk_prepareupload', $output['urls'] ); |
| 545 |
|
| 546 |
wp_send_json( $output ); |
| 547 |
} |
| 548 |
|
| 549 |
/** |
| 550 |
* Method perform_upload() |
| 551 |
* |
| 552 |
* Perform the upload. |
| 553 |
* |
| 554 |
* @uses \MainWP\Dashboard\MainWP_Connect::fetch_url_authed() |
| 555 |
* @uses \MainWP\Dashboard\MainWP_DB::get_website_by_id() |
| 556 |
* @uses \MainWP\Dashboard\MainWP_Utility::end_session() |
| 557 |
*/ |
| 558 |
public static function perform_upload() { |
| 559 |
MainWP_Utility::end_session(); |
| 560 |
// phpcs:disable WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized |
| 561 |
$type = isset( $_POST['type'] ) ? sanitize_text_field( wp_unslash( $_POST['type'] ) ) : ''; |
| 562 |
// Fetch info. |
| 563 |
$post_data = array( |
| 564 |
'type' => $type, |
| 565 |
); |
| 566 |
if ( isset( $_POST['activatePlugin'] ) && 'true' === $_POST['activatePlugin'] ) { |
| 567 |
$post_data['activatePlugin'] = 'yes'; |
| 568 |
} |
| 569 |
if ( isset( $_POST['overwrite'] ) && 'true' === $_POST['overwrite'] ) { |
| 570 |
$post_data['overwrite'] = true; |
| 571 |
} |
| 572 |
|
| 573 |
// deprecated from 3.5.6. |
| 574 |
self::addition_post_data( $post_data ); |
| 575 |
|
| 576 |
/** This filter is documented in pages/page-mainwp-install-bulk.php */ |
| 577 |
$post_data = apply_filters( 'mainwp_perform_install_data', $post_data ); |
| 578 |
|
| 579 |
$urls = isset( $_POST['urls'] ) ? esc_url_raw( wp_unslash( $_POST['urls'] ) ) : ''; |
| 580 |
$post_data['url'] = wp_json_encode( explode( '||', $urls ) ); |
| 581 |
$site_id = isset( $_POST['siteId'] ) ? intval( $_POST['siteId'] ) : 0; |
| 582 |
$website = MainWP_DB::instance()->get_website_by_id( $site_id ); |
| 583 |
|
| 584 |
// phpcs:enable |
| 585 |
|
| 586 |
// to support demo data. |
| 587 |
if ( MainWP_Demo_Handle::get_instance()->is_demo_website( $website ) ) { |
| 588 |
return MainWP_Demo_Handle::get_instance()->handle_action_demo( $website, 'perform_upload' ); |
| 589 |
} |
| 590 |
|
| 591 |
$output = new \stdClass(); |
| 592 |
$output->ok = array(); |
| 593 |
$output->errors = array(); |
| 594 |
$output->results = array(); |
| 595 |
$output->other_data = array(); |
| 596 |
$websites = array( $website ); |
| 597 |
|
| 598 |
/** |
| 599 |
* Action: mainwp_before_plugin_theme_install |
| 600 |
* |
| 601 |
* Fires before plugin/theme install. |
| 602 |
* |
| 603 |
* @since 4.1 |
| 604 |
*/ |
| 605 |
do_action( 'mainwp_before_plugin_theme_install', $post_data, $websites ); |
| 606 |
|
| 607 |
MainWP_Connect::fetch_urls_authed( |
| 608 |
$websites, |
| 609 |
'installplugintheme', |
| 610 |
$post_data, |
| 611 |
array( |
| 612 |
self::get_class_name(), |
| 613 |
'install_plugin_theme_handler', |
| 614 |
), |
| 615 |
$output, |
| 616 |
null, |
| 617 |
array( 'upgrade' => true ) |
| 618 |
); |
| 619 |
$output_obj = $output; |
| 620 |
mainwp_get_actions_handler_instance()->do_action_mainwp_install_actions( $websites, 'install', $output_obj, $type, $post_data, true ); |
| 621 |
|
| 622 |
/** |
| 623 |
* Action: mainwp_after_plugin_theme_install |
| 624 |
* |
| 625 |
* Fires after plugin/theme install. |
| 626 |
* |
| 627 |
* @since 4.1 |
| 628 |
*/ |
| 629 |
do_action( 'mainwp_after_plugin_theme_install', $output, $post_data, $websites, $type ); |
| 630 |
|
| 631 |
/** |
| 632 |
* Filter: mainwp_bulk_upload_install_result |
| 633 |
* |
| 634 |
* Fires after plugin/theme install. |
| 635 |
* |
| 636 |
* @since 4.6 |
| 637 |
*/ |
| 638 |
$output = apply_filters( 'mainwp_bulk_upload_install_result', $output, $type, $post_data, $websites ); |
| 639 |
|
| 640 |
wp_send_json( $output ); |
| 641 |
} |
| 642 |
|
| 643 |
/** |
| 644 |
* Clean the upload |
| 645 |
* |
| 646 |
* Do file structure maintenance and tmp file removals. |
| 647 |
* |
| 648 |
* @uses \MainWP\Dashboard\MainWP_System_Utility::get_wp_file_system() |
| 649 |
* @uses \MainWP\Dashboard\MainWP_System_Utility::get_mainwp_specific_dir() |
| 650 |
*/ |
| 651 |
public static function clean_upload() { |
| 652 |
$hasWPFileSystem = MainWP_System_Utility::get_wp_file_system(); |
| 653 |
|
| 654 |
/** |
| 655 |
* WordPress files system object. |
| 656 |
* |
| 657 |
* @global object |
| 658 |
*/ |
| 659 |
global $wp_filesystem; |
| 660 |
|
| 661 |
$path = MainWP_System_Utility::get_mainwp_specific_dir( 'bulk' ); |
| 662 |
if ( $wp_filesystem->exists( $path ) ) { |
| 663 |
$dh = opendir( $path ); |
| 664 |
if ( $dh ) { |
| 665 |
while ( false !== ( $file = readdir( $dh ) ) ) { |
| 666 |
if ( '.' !== $file && '..' !== $file ) { |
| 667 |
$wp_filesystem->delete( $path . $file ); |
| 668 |
} |
| 669 |
} |
| 670 |
closedir( $dh ); |
| 671 |
} |
| 672 |
} |
| 673 |
|
| 674 |
die( wp_json_encode( array( 'ok' => true ) ) ); |
| 675 |
} |
| 676 |
|
| 677 |
/** |
| 678 |
* Plugin & Theme upload handler. |
| 679 |
* |
| 680 |
* @param mixed $data Processing data. |
| 681 |
* @param object $website The website object. |
| 682 |
* @param mixed $output Function output. |
| 683 |
* @param mixed $post_data Post data. |
| 684 |
* |
| 685 |
* @return mixed $output->ok[ $website->id ] = array( $website->name )|Error, |
| 686 |
* Already installed, |
| 687 |
* Undefined error! Please reinstall the MainWP Child plugin on the child site, |
| 688 |
* Error while installing. |
| 689 |
* |
| 690 |
* @uses \MainWP\Dashboard\MainWP_System_Utility::get_child_response() |
| 691 |
*/ |
| 692 |
public static function install_plugin_theme_handler( $data, $website, &$output, $post_data = array() ) { |
| 693 |
if ( MainWP_Demo_Handle::get_instance()->is_demo_website( $website ) ) { |
| 694 |
return; |
| 695 |
} |
| 696 |
if ( preg_match( '/<mainwp>(.*)<\/mainwp>/', $data, $results ) > 0 ) { |
| 697 |
|
| 698 |
$result = $results[1]; |
| 699 |
// phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode used for http encoding compatible. |
| 700 |
$information = MainWP_System_Utility::get_child_response( base64_decode( $result ) ); |
| 701 |
if ( is_array( $information ) ) { |
| 702 |
if ( isset( $information['other_data']['install_items'] ) ) { |
| 703 |
$output->other_data[ $website->id ] = $information['other_data']; // content: install_items themes/plugins. |
| 704 |
} |
| 705 |
} |
| 706 |
|
| 707 |
if ( isset( $information['installation'] ) && 'SUCCESS' === $information['installation'] ) { |
| 708 |
$output->ok[ $website->id ] = array( $website->name ); |
| 709 |
$output->results[ $website->id ] = isset( $information['install_results'] ) ? $information['install_results'] : array(); |
| 710 |
} elseif ( isset( $information['error'] ) ) { |
| 711 |
$error = esc_html( $information['error'] ); |
| 712 |
if ( isset( $information['error_code'] ) && 'folder_exists' === $information['error_code'] ) { |
| 713 |
$error = esc_html__( 'Already installed', 'mainwp' ); |
| 714 |
} |
| 715 |
|
| 716 |
if ( 'not found' === strtolower( $error ) ) { |
| 717 |
if ( is_array( $post_data ) && isset( $post_data['type'] ) ) { |
| 718 |
if ( 'plugin' === $post_data['type'] ) { |
| 719 |
$error = esc_html__( 'Plugin file not found. Make sure security plugins or server-side security rules are not blocking requests from your child sites.', 'mainwp' ); |
| 720 |
} elseif ( 'theme' === $post_data['type'] ) { |
| 721 |
$error = esc_html__( 'Theme file not found. Make sure security plugins or server-side security rules are not blocking requests from your child sites.', 'mainwp' ); |
| 722 |
} |
| 723 |
} |
| 724 |
} |
| 725 |
|
| 726 |
$output->errors[ $website->id ] = array( $website->name, $error ); |
| 727 |
} else { |
| 728 |
$output->errors[ $website->id ] = array( |
| 729 |
$website->name, |
| 730 |
__( 'Undefined error! Please reinstall the MainWP Child plugin on the child site', 'mainwp' ), |
| 731 |
); |
| 732 |
} |
| 733 |
} else { |
| 734 |
$output->errors[ $website->id ] = array( $website->name, 'Error while installing' ); |
| 735 |
} |
| 736 |
} |
| 737 |
} |
| 738 |
|