Skip to content

Instantly share code, notes, and snippets.

@panoslyrakis
Created November 23, 2017 10:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save panoslyrakis/d8e43285b6dbb5bc7a29f9f6008ab081 to your computer and use it in GitHub Desktop.
Save panoslyrakis/d8e43285b6dbb5bc7a29f9f6008ab081 to your computer and use it in GitHub Desktop.
[WordPress MultiSite General] - Fix shared terms in multisite
<?php
/**
* Plugin Name: [WordPress MultiSite General] - Fix shared terms in multisite
* Plugin URI: https://premium.wpmudev.org/
* Description: A custom solution to fix shared terms in multisite
* Author: Panos Lyrakis @ WPMUDEV
* Author URI: https://premium.wpmudev.org/
* License: GPLv2 or later
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'WPMUDEV_MS_Shared_Terms' ) ) {
class WPMUDEV_MS_Shared_Terms {
private static $_instance = null;
public static function get_instance() {
if( is_null( self::$_instance ) ){
self::$_instance = new WPMUDEV_MS_Shared_Terms();
}
return self::$_instance;
}
private function __construct() {
add_action('network_admin_menu', array( $this, 'network_page' ) );
add_action( 'admin_footer', array( $this, 'load_raw_js' ), 10 );
add_action( 'wp_ajax_wpmudev_get_network_shared_terms', array( $this, 'blog_shared_terms_ajax' ), 10 );
add_action( 'wp_ajax_wpmudev_split_blog_shared_terms', array( $this, 'blog_split_terms_ajax' ), 10 );
}
public function network_page() {
add_submenu_page(
'settings.php',
__( 'Shared Terms' ),
__( 'Network Shared Terms' ),
'manage_network_options',
'wpmudev-ms-shared-terms',
array( $this, 'page_layout' )
);
}
public function page_layout(){
?>
<div class="wrap" style="width: 45%;float: left;">
<div class="card header-card">
<h1><?php _e( 'Network Shared Terms' ); ?></h1>
<em><?php _e( 'From here you can monitor shared terms across network sites' ); ?></em>
<!--<div class="notice notice-warning"> <?php _e( 'It\'s important you keep a backup of these tables first!' ); ?> </div>-->
</div>
<div class="card content-card">
<table class="wp-list-blogs widefat fixed striped sites">
<tr>
<td>Blog id</td>
<td>Blog name</td>
<td>Shared terms</td>
</tr>
<?php
$sites = $this->get_sites();
foreach( $sites as $site ){
$site_details = get_blog_details( $site->blog_id )
?>
<tr class="blogs-row blog-id-<?php echo $site->blog_id; ?>">
<td><?php echo $site->blog_id; ?></td>
<td><?php echo $site_details->blogname; ?></td>
<td><div class="wpmudev-term-item-wrap" data-blog-id="<?php echo $site->blog_id; ?>"> - </div></td>
</tr>
<?php
}
?>
</table>
</div>
</div>
<div class="wrap" style="width: 45%;float: right;">
<div class="card wpmudev_blog_report">
</div>
</div>
<?php
}
public function blog_shared_terms_ajax(){
check_ajax_referer( 'wpmudev_get_network_shared_terms', 'security' );
$blog_id = (int)$_POST['blog_id'];
$terms = $this->blog_shared_terms( $blog_id );
$return = array(
'success' => true,
'terms_count' => count( $terms )
);
wp_send_json( $return );
}
public function blog_shared_terms( $blog_id ){
$blog_id = (int)$blog_id;
return $this->get_shared_terms( $blog_id );
}
public function get_shared_terms( $blog_id, $limit = null ) {
switch_to_blog( $blog_id );
global $wpdb;
$terms = array();
$terms_query = "SELECT `term_id` FROM {$wpdb->term_taxonomy} GROUP BY `term_id` HAVING COUNT(*) > 1";
if( ! is_null( $limit ) && is_numeric( $limit ) ){
$limit = (int) $limit;
$terms_query .= " LIMIT {$limit}";
}
$term_ids = $wpdb->get_col( $terms_query );
if ( ! empty( $term_ids ) ) {
$terms = $wpdb->get_results(
"SELECT tt.term_taxonomy_id, tt.term_id, t.name, tt.taxonomy, tt.count
FROM {$wpdb->term_taxonomy} AS tt
INNER JOIN {$wpdb->terms} AS t ON tt.term_id=t.term_id
WHERE tt.term_id IN (" . implode( ',', $term_ids ) . ')'
);
}
restore_current_blog();
return $terms;
}
public function blog_split_terms_ajax(){
check_ajax_referer( 'wpmudev_get_network_shared_terms', 'security' );
$blog_id = (int)$_POST['blog_id'];
$step = (int)$_POST['step'];
$split_terms = $this->blog_split_terms( $blog_id, $step );
$split_terms_count = count( $split_terms );
$return = array(
'success' => true,
'terms_count' => $split_terms_count,
'terms_splited' => $split_terms
);
if( $split_terms_count < $step || $split_terms_count <= 0 ){
$return[ 'done' ] = true;
}
wp_send_json( $return );
}
public function blog_split_terms( $blog_id, $limit ){
$terms = $this->blog_shared_terms( $blog_id, $limit );
$split_terms = array();
if( ! is_array( $terms ) || empty( $terms ) ){
return array();
}
switch_to_blog( $blog_id );
foreach( $terms as $term ){
$new_term_id = _split_shared_term( $term->term_id, $term->term_taxonomy_id );
if( ! is_wp_error( $new_term_id ) ){
$split_terms[] = $term->name;
}
}
restore_current_blog();
return $split_terms;
}
public function load_raw_js(){
$screen = get_current_screen();
if( 'settings_page_wpmudev-ms-shared-terms-network' != $screen->id ){
return;
}
$nonce = '';
?>
<script type="text/javascript">
(function($){
$(document).ready(function(){
WPMUDEV_MS_Shared_Terms.init();
});
var WPMUDEV_MS_Shared_Terms = {
blog_ids: [],
blog_ids_with_shared_terms: [],
blog_counter: 0,
terms_step: 10,
init: function(){
this.get_blogs()
this.get_blogs_shared_terms()
},
get_blogs: function(){
let blogs = [];
$( '.wpmudev-term-item-wrap' ).each(function(){
blogs.push( $(this).data('blog-id') );
});
this.blog_ids = blogs;
},
get_blogs_shared_terms: function(){
if( this.blog_counter >= this.blog_ids.length ){
this.blog_counter = 0;
WPMUDEV_MS_Shared_Terms.split_network_terms();
return;
}
let blog_id = this.blog_ids[ this.blog_counter ];
const blog_ids_number = this.blog_ids.length
let blog_counter = this.blog_counter;
this.blog_counter++
var data = {
action: 'wpmudev_get_network_shared_terms',
security: '<?php echo wp_create_nonce( "wpmudev_get_network_shared_terms" ); ?>',
blog_id: blog_id
};
$.post(ajaxurl, data, function(response) {
if( response.success ){
let el = $( '.blogs-row.blog-id-' + blog_id + ' .wpmudev-term-item-wrap' );
el.html( ' ' + response.terms_count + ' ' );
if( response.terms_count > 0 ){
WPMUDEV_MS_Shared_Terms.blog_ids_with_shared_terms.push( blog_id );
$( '.blogs-row.blog-id-' + blog_id + ' td' ).css( 'background','#d57776' );
}
}
if( blog_counter < blog_ids_number ){
WPMUDEV_MS_Shared_Terms.get_blogs_shared_terms();
}
else{
//It shouldn't reach here
//WPMUDEV_MS_Shared_Terms.split_network_terms();
}
});
},
split_network_terms: function(){
let blog_id = WPMUDEV_MS_Shared_Terms.blog_ids_with_shared_terms[ this.blog_counter ]
this.blog_counter++
if( this.blog_counter > this.blog_ids_with_shared_terms.length ){
alert( 'FINISHED' )
}
else{
this.split_blog_terms( blog_id )
}
},
split_blog_terms: function( blog_id ){
var data = {
action: 'wpmudev_split_blog_shared_terms',
security: '<?php echo wp_create_nonce( "wpmudev_get_network_shared_terms" ); ?>',
blog_id: blog_id,
step: this.terms_step
};
$.post(ajaxurl, data, function(response){
if( response.success ){
if( response.done ){
WPMUDEV_MS_Shared_Terms.split_network_terms();
//console.log( response.terms_splited );
WPMUDEV_MS_Shared_Terms.print_report( blog_id, response.terms_splited );
}
else{
WPMUDEV_MS_Shared_Terms.split_blog_terms( blog_id );
}
}
})
},
print_report: function( blog_id, terms_splited ){
let blog_report = $( '.wpmudev_blog_report' );
let term_names = '';
for( let i = 0; i < terms_splited.length; i++ ){
term_names += '<div>' + terms_splited[i] + '</div>';
}
blog_report.append( '<h3>BLOG ID: ' + blog_id + '</h3>' );
blog_report.append( '<div style="margin-bottom: 20px; padding:10px; border: 1px solid #ddd;">' + term_names + '</div>' );
}
}
})(jQuery);
</script>
<?php
}
public function get_sites(){
$sites = get_sites();
return $sites;
}
}
add_action( 'plugins_loaded', function(){
$GLOBALS['WPMUDEV_MS_Shared_Terms'] = WPMUDEV_MS_Shared_Terms::get_instance();
}, 10 );
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment