Last active
October 6, 2024 15:45
-
-
Save wpmudev-sls/939ab23dc2cfd00049ce30b8d0b76798 to your computer and use it in GitHub Desktop.
[SmartCrawl Pro] Bulk-apply config to subsites
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Plugin Name: [SmartCrawl Pro] Bulk-apply config to subsites | |
* Description: Adds an "Apply subsite config" link in the SmartCrawl network admin menu with a page to bulk-apply settings to subsites | |
* Author: Anderson Salas @ WPMUDEV | |
* Task: SLS-6513 | |
* Author URI: https://premium.wpmudev.org | |
* License: GPLv2 or later | |
*/ | |
add_action( 'plugins_loaded', function() { | |
if ( ! defined( 'SMARTCRAWL_VERSION' ) ) { | |
return; // SmartCrawl is not installed/enabled. | |
} | |
if ( class_exists( 'SmartCrawl_Subsite_Bulk_Config' ) ) { | |
return; // Already loaded. | |
} | |
class SmartCrawl_Subsite_Bulk_Config { | |
const NONCE = 'wds_network_site_bulk_config'; | |
private static $instance; | |
public static function get_instance() { | |
if ( null === self::$instance ) { | |
self::$instance = new self(); | |
} | |
return self::$instance; | |
} | |
public function add_sc_submenu_item() { | |
add_submenu_page( | |
\SmartCrawl\Admin\Pages\Network_Settings::MENU_SLUG, | |
'Apply subsite config', | |
'Apply subsite config', | |
'manage_network_options', | |
'wds_network_site_bulk_config', | |
[ $this, 'admin_page' ], | |
99 | |
); | |
} | |
public function __construct() { | |
if ( is_admin() && 'wds_network_site_bulk_config' === ( $_GET['page'] ?? '' ) ) { | |
add_action( 'admin_enqueue_scripts', function() { | |
wp_enqueue_style( 'wds-app' ); | |
wp_enqueue_script( 'wds-shared-ui' ); | |
}); | |
add_filter( 'admin_body_class', function( $class ) { | |
return ( $class ?? '' ) . ' sui-' . str_ireplace( '.', '-', SMARTCRAWL_SUI_VERSION ) . ' '; | |
}); | |
} | |
add_action( 'network_admin_menu', [ $this, 'add_sc_submenu_item' ], 99 ); | |
add_action( 'admin_footer', [ $this, 'admin_importer_scripts' ] ); | |
add_action( 'wp_ajax_wds_network_site_bulk_config', [ $this, 'ajax_handle_config' ] ); | |
} | |
public function admin_importer_scripts() { | |
?> | |
<script>( function( $ ) { | |
$( '.sc-begin-import' ).click( function() { | |
$( this ).addClass( 'disabled' ); | |
$( '.import-spinner' ).addClass( 'is-active' ); | |
var data = { | |
'_wpnonce' : $( 'form#config-form input[name="_wpnonce"]' ).val(), | |
'config_id' : $( 'form#config-form select[name="config_id"]' ).val(), | |
'sites' : $( 'form#config-form input[name="sites[]"]:checked' ).map(function() { | |
return $(this).val(); | |
}).get(), | |
'action' : 'wds_network_site_bulk_config' | |
}; | |
$.post( ajaxurl, data, function( response ) { | |
if ( ! response.success ) { | |
alert( response.data.error ); | |
} else { | |
alert( response.data.message ); | |
} | |
}).fail( function() { | |
alert( 'An error occurred.' ); | |
}).always( function() { | |
$( '.sc-begin-import' ).removeClass( 'disabled' ); | |
$( '.import-spinner' ).removeClass( 'is-active' ); | |
}); | |
}); | |
var _validate = function() { | |
$( '.sc-begin-import' ).removeClass( 'disabled' ); | |
if ( 0 === $('input.site-checkbox:checked').length || '' === $('select[name="config_id"]').val() ) { | |
$( '.sc-begin-import' ).addClass( 'disabled' ); | |
} | |
} | |
$( '.sc-select-all' ).click( function(e) { | |
e.preventDefault(); | |
$( '.site-checkbox' ).prop('checked', true); | |
_validate(); | |
}); | |
$( '.sc-select-clear' ).click( function(e) { | |
e.preventDefault(); | |
$( '.site-checkbox' ).prop('checked', false); | |
_validate(); | |
}); | |
$('input.site-checkbox, select[name="config_id"]').on( 'change', _validate); | |
_validate(); | |
})( window.jQuery )</script> | |
<style> | |
.label-site, .label-site small { | |
overflow: hidden !important; | |
text-overflow: ellipsis !important; | |
white-space: nowrap !important; | |
display: block !important; | |
max-width: 515px; | |
} | |
</style> | |
<?php | |
} | |
public function admin_page() { | |
$configs = \SmartCrawl\Configs\Collection::get()->get_deflated_configs(); | |
$sites = get_sites(); | |
?> | |
<div class="sui-wrap"> | |
<div class="sui-box" style="max-width:650px;"> | |
<div class="sui-box-header"> | |
<h2 class="sui-box-title"> | |
<span class="sui-icon-widget-settings-config" aria-hidden="true"></span> Apply subsite config | |
</h2> | |
</div> | |
<?php if ( ! is_multisite() ) { ?> | |
<div class="sui-box-body"> | |
<p>This tool is compatible only with multisite installations.</p> | |
</div> | |
<?php } else { ?> | |
<form id="config-form" method="post"> | |
<div class="sui-box-body"> | |
<?php wp_nonce_field( self::NONCE ); ?> | |
<p style="margin-top: 0">Select a config and click <strong>Apply Config</strong> to bulk-apply it to the desired subsites. Do not close this browser tab until the process is done.</p> | |
<div class="sui-form-field"> | |
<label class="sui-label">Config name</label> | |
<select id="config-selector" class="sui-select" name="config_id"> | |
<option value="">Select a config...</option> | |
<?php foreach( $configs as $config ) { ?> | |
<option value="<?php echo $config['id']; ?>"><?php echo $config['name']; ?></option> | |
<?php } ?> | |
</select> | |
</div> | |
<label class="sui-label" style="display:block;"> | |
Target subsites | |
<span style="float:right"> | |
<a href="#" class="sc-select-all" style="display: inline-block; margin-right: 10px">[Select all]</a> | |
<a href="#" class="sc-select-clear">[Clear]</a> | |
</span> | |
</label> | |
<div style="display:block;border: 1px solid #ddd;padding: 15px;max-height: 232px;overflow-y: auto;"> | |
<?php | |
foreach( $sites as $site ) { | |
$site_details = get_blog_details( $site->blog_id ); | |
?> | |
<div style="display:block"> | |
<label for="site_<?php echo $site->blog_id; ?>" class="sui-checkbox"> | |
<input type="checkbox" checked="checked" name="sites[]" value="<?php echo $site->blog_id; ?>" id="site_<?php echo $site->blog_id; ?>" class="site-checkbox" /> | |
<span aria-hidden="true"></span> | |
<span id="label-site_<?php echo $site->blog_id; ?>" class="label-site"> | |
<?php echo $site_details->blogname; ?><br /><small><?php echo $site_details->siteurl; ?></small> | |
</span> | |
</label> | |
</div> | |
<?php } ?> | |
</div> | |
<div class="sui-notice sui-notice-warning" style="margin-top:25px"> | |
<div class="sui-notice-content"> | |
<div class="sui-notice-message"> | |
<span class="sui-notice-icon sui-icon-warning-alert sui-md" aria-hidden="true"></span> | |
<p><strong>WARNING: Any existing config will be OVERWRITTEN.</strong><br />It is highly recommended that you <a href="https://wpmudev.com/docs/hosting/backups/" target="_blank">create a backup</a> and test this tool on a <a href="https://wpmudev.com/docs/hosting/staging/" target="_blank">Staging Site</a> first.</p> | |
</div> | |
</div> | |
</div> | |
</div> | |
<div class="sui-box-footer"> | |
<input type="button" name="submit" id="submit" class="sui-button sui-button-blue sc-begin-import" value="Apply Config" /> | |
<div class="spinner import-spinner" style="float:none; width:auto; height:auto; padding: 10px 0 10px 20px; margin-top: 0; margin-left:0"></div> | |
</div> | |
</form> | |
<?php } ?> | |
</div> | |
</div> | |
<?php | |
} | |
private function do_bulk_config() { | |
$processed = 0; | |
if ( empty( $_POST['config_id'] ) ) { | |
wp_send_json_error( [ 'error' => 'Invalid or missing parameter: config_id' ] ); | |
} | |
$config_id = sanitize_text_field( $_POST['config_id'] ); | |
$sites = []; | |
if ( empty( $_POST['sites'] ) || ! is_array( $_POST['sites'] ) ) { | |
wp_send_json_error( [ 'error' => 'Invalid or missing parameter: sites' ] ); | |
} | |
foreach( $_POST['sites'] as $site_id ) { | |
$sites[] = intval( $site_id ); | |
} | |
if ( empty( $sites ) ) { | |
wp_send_json_error( [ 'error' => 'Invalid or missing parameter: sites' ] ); | |
} | |
$config = \SmartCrawl\Configs\Collection::get()->get_by_id( $config_id ); | |
if ( ! $config ) { | |
wp_send_json_error( [ 'error' => 'Failed to retrieve config_id: ' . $config_id ] ); | |
} | |
$sc_config_controller = \SmartCrawl\Configs\Controller::get(); | |
foreach( get_sites() as $site ) { | |
$blog_id = (int) $site->blog_id; | |
if ( ! in_array( $blog_id, $sites, true ) ) { | |
continue; | |
} | |
switch_to_blog( $blog_id ); | |
$sc_config_controller->apply_handler( $config->get_configs() ); | |
$processed++; | |
} | |
restore_current_blog(); | |
return $processed; | |
} | |
public function ajax_handle_config() { | |
if ( empty( $_POST[ '_wpnonce' ] ) || ! wp_verify_nonce( $_POST[ '_wpnonce' ], self::NONCE ) ) { | |
wp_send_json_error( [ 'error' => 'Invalid nonce.' ] ); | |
} | |
if ( ! current_user_can( 'manage_network_options' ) ) { | |
wp_send_json_error( [ 'error' => 'Not allowed.' ] ); | |
} | |
if ( ! is_multisite() ) { | |
wp_send_json_error( [ 'error' => 'This tool is not compatible with single-site installations.' ] ); | |
} | |
$total = $this->do_bulk_config(); | |
wp_send_json_success( [ 'message' => 'The bulk-config has been completed successfully! (Total sites: ' . $total . ')'] ); | |
} | |
} | |
SmartCrawl_Subsite_Bulk_Config::get_instance(); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment