Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

Setting up a WP multisite instance - the client has an existing ontology / set of categories that they want to classify all content across the set of blogs. Also the desire is that any new categories would be added at the 'network blog' level and synced to the other blogs.

What's the best way of doing this?

share|improve this question
    
i guess making categories assigned to a global variable and then import on theme init. –  kaiser Mar 16 '11 at 23:13
4  
I think this question is the same as Share one taxonomy across multiple blogs in 3.0. That question did not get a good answer however. It is an interesting question, I'll offer a bounty for it. –  Jan Fabry May 27 '11 at 20:23
add comment

4 Answers 4

up vote 11 down vote accepted
function __add_global_categories( $term_id )
{
    if ( get_current_blog_id() !== BLOG_ID_CURRENT_SITE || ( !$term = get_term( $term_id, 'category' ) ) )
        return $term_id; // bail

    if ( !$term->parent || ( !$parent = get_term( $term->parent, 'category' ) ) )
        $parent = null;

    global $wpdb;

    $blogs = $wpdb->get_col( "SELECT blog_id FROM {$wpdb->blogs} WHERE site_id = '{$wpdb->siteid}'" );
    foreach ( $blogs as $blog ) {
        $wpdb->set_blog_id( $blog );

        if ( $parent && ( $_parent = get_term_by( 'slug', $parent->slug, 'category' ) ) )
            $_parent_ID = $_parent->term_id;
        else
            $_parent_ID = 0;

        wp_insert_term( $term->name, 'category',  array(
            'slug' => $term->slug,
            'parent' => $_parent_ID,
            'description' => $term->description
        ));
    }

    $wpdb->set_blog_id( BLOG_ID_CURRENT_SITE );
}
add_action( 'created_category', '__add_global_categories' );

This will run whenever a category is added on the main site. A few caveats/points worth mentioning;

  • If you have a lot of blogs, this function may get pretty intensive.
  • On average, we are running anywhere between 5 to 8 queries (possibly more) per blog - depending on the speed of your database, this function may need to be chunked.
  • Only newly added categories are 'synced'. Updating and deleting categories are not (code will need to be revised).
  • If a newly added category has a parent, and the parent cannot be found within the multisite blog in question, the category will be created with no parent (this should only be the case if the parent category was created before this function was installed).
share|improve this answer
1  
Is there - or could there be - a plugin that does this? Along with edits and deletions? And a settings page to choose which taxonomies and which child sites to apply it to? –  Marcus Downing Apr 20 '11 at 9:02
    
In fact, would you object if I used your code as the starting point to write a plugin? –  Marcus Downing Apr 20 '11 at 9:10
    
No problem whatsoever - my answers fall under stack exchange's license, the cc-wiki with attribution required :) –  TheDeadMedic May 5 '11 at 15:47
add comment

Oh, sunday procrastination...

https://github.com/maugly/Network-Terminator

  • Alows to bulk add terms across network
  • You can select what sites will be affected
  • Works with custom taxonomies
  • Doesn't delete
  • Doesn't sync

This is something I've done in a last few hours and I have no time for more testing now. Anyway - it works for me! .)

Give it a try. There's also a 'test run' feature implemented so you can check the result before actually doing something.

Update -> Screenshots:

Before action:

Before action

After test run:

After test run

The plugin linked above adds user interface but pretty much everything important happens in this function:

        <?php function mau_add_network_terms($terms_to_add, $siteids, $testrun = false) {

        // check if this is multisite install
        if ( !is_multisite() )
            return 'This is not a multisite WordPress installation.';

        // very basic input check
        if ( empty($terms_to_add) || empty($siteids) || !is_array($terms_to_add) || !is_array($siteids) )
            return 'Nah, I eat only arrays!';

        if ($testrun) $log = '<p><em>No need to get excited. This is just a test run.</em></p>';
        else $log = '';

        // loop thru blogs
        foreach ($siteids as $blog_id) :

            switch_to_blog( absint($blog_id) );

            $log .= '<h4>'.get_blog_details(  $blog_id  )->blogname.':</h4>';
            $log .= '<ul id="ntlog">';

            // loop thru taxonomies
            foreach ( $terms_to_add as $taxonomy => $terms ) {

                // check if taxonomy exists
                if ( taxonomy_exists($taxonomy) ) {
                    // get taxonomy name
                    $tax_name = get_taxonomy($taxonomy);
                    $tax_name = $tax_name->labels->name;

                    //loop thru terms   
                    foreach ( $terms as $term ) {

                        // check if term exists
                        if ( term_exists($term, $taxonomy) ) {
                            $log .= "<li class='notice' ><em>$term already exists in the $tax_name taxonomy - not added!</em></li>";

                        } else {

                            // if it doesn't exist insert the $term to $taxonomy
                            $term = strip_tags($term);
                            $taxonomy = strip_tags($taxonomy);
                            if (!$testrun)
                                wp_insert_term( $term, $taxonomy );
                            $log .= "<li><b>$term</b> successfully added to the <b>$tax_name</b> taxonomy</li>"; 
                        }
                    }
                } else {
                    // tell our log that taxonomy doesn't exists
                    $log .= "<li class='notice'><em>The $tax_name taxonomy doesn't exist! Skipping...</em></li>"; 
                }
            }

            $log .= '</ul>';    

            // we're done here
            restore_current_blog();

        endforeach;
        if ($testrun) $log .= '<p><em>No need to get excited. This was just the test run.</em></p>';
        return $log;
    } ?>

I will come back and edit this with more info later (if needed).

It is far from perfect (read known issues in the plugin head).
Any feedback appreciated!

share|improve this answer
3  
I like it when people create plugins in response to questions! You deserve the bounty! –  Jan Fabry Jun 3 '11 at 18:40
    
Thanks for your support @Jan Fabry. I'll be happy if someone beside me will actually find this thing useful. –  Michal Mau Jun 3 '11 at 20:15
1  
add comment

TheDeadMedic's answer looks good, but I ended up taking a different approach to the problem. Instead of duplicating the same terms across the many sites, I instead made the other sites use the home site's tables for terms.

add_action('init', 'central_taxonomies');

function central_taxonomies () {
  global $wpdb;

  $wpdb->terms = "wp_terms";
  $wpdb->term_taxonomy = "wp_term_taxonomy";
}

This replaces the table name wp_2_terms with wp_terms, etc. You should of course check in your database to make sure of the exact name of the tables, which might be different if you change your prefix.

You can run this from either a plugin or a theme (though I recommend a plugin). I may get round to publishing a plugin to do this at some point. There are two downsides to this approach:

  • It's only active on child sites that have the plugin activated. There's no way to enforce this from the parent site.
  • It applies to all the taxonomies, not just selected ones.

This approach is flexible - it can be adapted to pull categories from any blog, not just the central one.


Update: I've made this into a plugin, which can be activated site-wide if you need it to be: MU Central Taxonomies

share|improve this answer
    
There's a big problem with this approach: The relations between posts and terms might not be correct. The table term_relationships contains this relation based on post ID and term ID. But there's always chance that posts in subsites have same ID. Changing terms for 1 post might unpredictable affect on another post in another blog. –  Rilwis Nov 22 '13 at 3:58
    
Correct, the term_relationships table shouldn't be included. I spotted and fixed that long ago in the plugin, but never updated this answer to match. –  Marcus Downing Nov 22 '13 at 9:47
add comment

Yes this is possible. I built a plugin like this for WPMU ages ago (http://natureofmind.org/30/default-categories-for-new-blogs/ but no longer supported) more up-to-date would be the following two plugins: http://wordpress.org/extend/plugins/wpmu-new-blog-defaults/ and http://premium.wpmudev.org/project/new-blog-template

share|improve this answer
add comment

protected by toscho Sep 23 '12 at 21:23

Thank you for your interest in this question. Because it has attracted low-quality answers, posting an answer now requires 10 reputation on this site.

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.