Half-Elf on Tech

Thoughts From a Professional Lesbian

Tag: multisite

  • Adding Per Site Multisite Options

    Adding Per Site Multisite Options

    johnc- said in IRC the other day, regarding the use of get_option API for WordPress “our standard practice is to use get_option to enable site specific features, if the feature needs to be unavailable for other sites then it gets broken into a separate plugin for clarity”

    diceSo to explain this for those who blinked a little we need some examples, and really this depends what you’re writing.

    We got to this point in the conversation while folks were watching my “Don’t Use WordPress Multisite” presentation from WordCamp SF. During the presentation, I mentioned that generally, when I want to write a function for a specific site on Multisite, I wrap it around a ‘If site 1, then …’ and put it in it’s own plugin file in mu-plugins. That leaves me with files like halfelf-functions.php so if I ever split the site out (see? I’m always thinking ahead) I know what file to copy.

    But that’s not the only way about it. Another way is to put all the functions in a file, and then wrap the actual filters and actions around a get_option call. Why would I want to do this instead of a separate function file? The question of portability comes up primarily. Exporting site options is not the easiest thing in the world on a Multisite, but there are cases, like my Capital H Dangit! function, where this would make sense. In general, I always want DreamHost to have a capital H, so since 99% of my sites have that on, I could, instead, use an option, since if I ever moved the one site that doesn’t use it, I just won’t bring the function over!

    Currently have wrapped that function around an ‘if site 2, then don’t run’ check, which works fine. But if I wanted to move that to options, it would go like this:

    
    // Add the default option of capital h to yes, and autoload
    add_option( 'helf_capital_H_dangit', 'yes', '', 'yes');
    
    if ( get_option( 'helf_capital_H_dangit' ) == 'yes' ) {
        foreach ( array( 'the_content', 'the_title', 'comment_text' ) as $filter )
            add_filter( $filter, 'capital_H_dangit', 11 );
    }
    
    function capital_H_dangit( $text ) { 
        [... code here ...]
    }
    

    This is pretty basic. It adds an option called helf_capital_H_dangit, auto-loads, and defaults to on for everyone. That was the easy part. The hard part is determining how to control it.

    One option is an interface where I can check a box on, say, General Settings > Writing > Formatting (right under the smilies check box would be perfect), but since I knew this was something I was going to want to control as the super-admin (that is, I don’t want the other people on my network to turn it off), I went in to the back end of my site at /wp-admin/network/site-info.php?id=2 (since this is site ) and searched for ‘Helf’

    Screen Shot 2013-08-21 at 2.21.41 PM

    I edited it to ‘no’ and saved. Boom. I can use DreamHost and Dreamhost here.

    Now this isn’t something I’d do for everything. In fact, my actual halfelf-functions.php file looks like this:

    global $blog_id;
    
    if ( $blog_id == 2 ) {
    
    	remove_filter( 'the_content', 'capital_P_dangit', 11 );
    	remove_filter( 'the_content', 'capital_H_dangit', 11 );
    
    	// I Make Plugins Filters
    }
    

    All the per-site filters are right there turned off as I want them. It’s not a lot of effort that way, and it’s still easy to pick up a site and drop it somewhere else.

    Businesswoman in Front of DoorsWhich is better? I don’t know. The real test would be to do some hardcore speed checks and see if checking for the blog ID is faster than checking for an option. I think the speed benefit gains would come from only calling this when needed, but for the limited world in which this is used, it should be fine. Also, keep in mind what both johnc- and I are saying, but in different ways: remember the 80/20 rule.

    In my opinion, if you’re making a feature that will be used by 80%+ of the sites on your Network, get_option is probably the easiest bet. If you’re making a feature that’s going to be used by 20%- of the sites, then a separate plugin (with a site_id check) is the way to go. Of course, you could do an option and default it to ‘no’ as well, but that brings up an interesting level of things to remember if you ever move a site.

    If you’ve got a more efficient way of doing the same thing, or even just a different way, speak up! More options are always better.

    Oh and no, we’re not going to sneakily install this on DreamPress, but if I did, it would also capitalize DreamPress, DreamCompute, and everything else out there. But I won’t.

  • Breaking Up Multisite

    Breaking Up Multisite

    This is by no means the be-all and end-all of how to break up a Multisite. These are, however, methods I’ve used to move Multisites around into brand new places. As always, if you have another method, feel free to explain in the comments, and link back to your own tutorials!

    brokeback-mountainYou see, Multisite is great at some things, but breaking up is crazy hard to do. If you want to just disable multisite, it’s not too bad, four steps, and the hardest is to delete the right tables. And if you want to move a whole multisite, it’s not terrible either.

    But. What happens when you want to move only one site on the network?

    Usually I see this happen when someone is developing a site for someone else, and thinks it’ll be ‘easier’ to do it on their Multisite. After all, the site will be ‘visible’ but clearly a development site, and remote clients can take a look all they want. The minority of people I see doing this for just themselves, knowing the site won’t ever need to be on a Multisite, but taking the ‘easy’ way out. And to them I suggest developing locally, as domain.dev, and then a blanket search/replace on ‘domain.dev’ for ‘domain.com’ when you’re ready to move. Then there is a small group of people who have a multisite installed on localhost for development, which … no. Don’t. It’s localhost. Spin up a new instance of WordPress.

    And still, while I lament the shortsighted nature of these things, there are clear-cut use-cases for this that people just can’t predict. Like the day you wake up and realize that Ennis and Jack can stay on brokebackblog.com, but maybe you should move the Hulk.(Ang Lee directed both movies.) Now you have a dilemma. Do you rebrand brokebackblog.com as angleefilms.com? Maybe you just domain map brokebackblog.com/hulk to hulksmashblog.com or maybe, maybe, you don’t want to run the Hulk blogs at all, but your friend Eric does. Certainly there are always options to splitting up a Multisite, yet for the sake of this post, you have decided that Eric (who has bought hulksmashblog.com) should have the whole site, all the posts and users, and you don’t want it on your server at all!

    Now what?

    Uber Easy: Export and Import

    This is straightforward. Install your new stand-alone WordPress instance, export the posts from brokebackblog.com/hulk, import them into hulksmashblog.com, customize the theme and plugins, done. If you don’t have a lot of users, this is the best bet. Yes, you’ll lose a lot of time resetting all the plugins and theme configs, but you probably had to do some of this anyway. All your comments come with, all your images too, so it’s going to be straightforward.

    A couple more things to keep in mind. User passwords will need to be reset, which is trivial in my experience, and a good idea anyway if you want to enforce good passwords. Many new themes are getting great at allowing you to export theme settings, so that may ease the pain as well. The plugin settings really are the biggest hassle to me, but in the long run, I’ve found that having to reset them isn’t horrible since the new home usually is a little different from the old one.

    Finally, you’ll probably need to search/replace your posts to compensate for the new image location. I prefer Velvet Blues Update URLs, but sometimes I use .htaccess to redirect instead. If you’re moving from an older Multisite, your images will all point to /files/, but newer ones are in /wp-content/uploads/sites/#/ instead. Of course, wp-cli make it even easier, and I use it all the time when moving people at work.

    $ wp search-replace brokebackblog.com/hulk hulksmashblog.com
    

    That’s right now my favorite command. It updated everything, with serialization handled safely, and I was done. If I can’t use that, I’ll grab the interconnectit search/replace tool (not just for WordPress) and run that instead, but for me, I install WP-CLI pretty much everywhere now. It’s just so easy!

    Ugly Complex: Database Dancing

    brokeback-mountain-20051213061537535When you’ve got a more complex situation, like a heavily customized and themed site, with lots of users and content, then you may have to do this the hard way. As before, make your new stand-alone instance of WordPress. Copy down all the plugins and the theme from your multisite, same as before. Instead of importing the content via an XML file, though, we’re going to import the following database tables as well as all the media images. Remember, no import, no media import, so you must SFTP them all over.

    Then the DB Tables you need are as follows:

    wp_x_*
    wp_user
    wp_usermeta
    

    This means you need to know your site number (not too hard, you know how to make them show up, right?), but don’t think it stops here! Now you have to rename tables. There are two directions to go. One is to rename all the wp_x_ tables to wp_, and the other is to rename the other two tables to wp_x_user and wp_x_usermeta instead.

    Either way you get to fuss even more. And don’t forget what I talked about in Recovering Your Cape: If your tables are named wp_x_ then you MUST have a field called wp_x_user_roles in wp_x_options, or no one will have any permissions at all. This almost makes it easier to think “Well I should just add in _x right?” You’d think, but then you’re stuck with this funny prefix you have to account for in your wp-config.php file, and you also have to consider what if hulksmashblog.com later wants to make itself a multisite. Be nice to the next guy. I would rename the tables, and then run a search/replace for wp_x_ and wp_ using wp-cli or that script.

    Now you’re still not done though. You actually moved over all of your users. That means you have a bunch that don’t have any posts. Go to the /users.php screen and sort by number of posts. Nuke everyone who doesn’t have any posts. Of course… what if they had comments and you want to keep that? Sadly that’s not listed. The comments table isn’t tied in to the users table in a easy to calculate way. But remember, deleting a user won’t delete the comment.

    Finally, remember you changed the domain name? Do that again, like you did with an import export.

    To The Pain: Moving Your Main Site

    brokeback_mountain_2005_6728_wallpaperOw. Ow. Okay, Jake, here’s where we get messy. There are just too many options to consider, so let’s look at them briefly.

    First, if you want to keep the main site at its current location (domain etc), then you want to actually move all the other sites and then disable multisite.

    However, if you want to keep the domain as a multisite and give the main site it’s own, new, home, you’ll want to switch out the main site for a subsite (detailed in WordPress Multisite 110 – around page 80), and then move it per one of the other ways… except remember the site number stays as ‘1’ which is to say ‘none’ so you’ll be moving wp_* and only the ones for the site, not the network (which you can’t delete unless you feel like breaking everything).

    Finally, and this one boggles my mind, you want to keep the multisite, and all the sites, but separately. You can see there’s no quick fix for this. Move ’em all manually, and have a beer when you’re done, cause it ain’t fast.

    Worse….

    There’s more? Just a little bit. Keep in mind that any network settings won’t copy over, so W3TC and WordPress SEO, just to name two popular plugins, have network wide settings. Those don’t magically come with, you’ll have to re-build all of that. With W3TC, you should be able to export the settings, but maybe not. Other plugins too may prove problematic. What about BuddyPress? That would pretty much have to be a table-copy over. At least bbPress should be easier, as it’s all CPTs.

    Obviously the more layers you get into with this, the messier it gets. Me? I try to do the age old export/import whenever possible.

  • WCSF Video: Don’t Use WordPress Multisite

    WCSF Video: Don’t Use WordPress Multisite

    [wpvideo LYqducp0 width=”800″]

    Too many people see Multisite as a silver bullet that can do everything they need, only to find out they’ve bitten off more than they can chew, and now they have a site that is too big, too complicated, and too much of a hassle. Understanding what Multisite does out of the box, what it’s best at, and where it’s easily extendable will help you build the right site.

  • Recovering Your Cape

    Recovering Your Cape

    One of the odder “hacks” out there is one where the person, once they get in, de-frocks your Super Admin on a Multisite. This isn’t always a hack, sometimes it’s just a simple mistake.

    To quote my friend Jen Mylo:

    1. People give away admin rights like logo-encrusted keychains at a car show and then the new admins abuse the power.
    2. Someone who has admin rights deservedly but doesn’t know code makes a mistake.

    […]

    Some people make bad decisions about who to give admin roles.

    There’s an extra level of problems with making everyone and their pet monkey a super-admin on Multisite. You may think it’s a great thing, because now someone else can add new users, install plugins, edit themes and plugins, and of course, use iframes and PHP and such in widgets.

    tumblr_md8hekGkk31qc184to1_500We run a Multisite at work, and they let me ‘secure it up’ recently. The first thing I did was demote pretty much everyone except five of us to ‘Editor.’ I told them all that I’d done this, and if they found something they couldn’t do, tell me, and I’d fix it. At this point, I’ve changed only three people to Admin, and dropped even more to ‘Author.’ Why? Because they don’t need to have high levels of access to do what they need to do! The admins on the site can tweak theme settings, play with widgets, and add ‘existing users.’ Everyone else? They just write content. Heck, most of them don’t even need to be Editors, but we gave them that level so they could help us copy-edit other posts. Two people complained “I need Super Admin access!” and I gave them my best Enda: NO CAPES.

    Limit your admins, and there is less of a chance someone will accidentally remove access from the wrong person.

    So now that that’s out of the way, how do you get it back?

    Normally, reinstating an admin account is pretty easy. You go in via mySQL, pop open the wp_usermeta table, find your ID, and toss this in for meta_value for wp_capabilities: a:1:{s:13:"administrator";b:1;} That won’t restore all the roles, if you happen to be using Role Scoper, or some other management tool, but if you’ve got that, you can do anything. If you’re using WP-CLI, wp user update 1 --role=administrator (assuming you’re user ID 1).

    Screen Shot 2013-06-21 at 11.34.20 AM

    There’s a sidebar/caveat to this. Sometimes this doesn’t work, and it happens if you change your DB prefix. So normally you have the prefix wp_ and the table wp_options. In that table you have a option named wp_user_roles and everything works. But then you make a new site, and you pick a different DB prefix, maybe you heard it was more secure, or maybe you wanted both tables in the same DB. Either way, now you have wp_wdssrr_options instead, and when you copy over your old options content, no one can log in. It’s because you have to rename that option to wp_wdssrr_user_roles

    Screen Shot 2013-06-25 at 10.00.51 AM

    I just had a site with this problem last week.

    NomadTrip_7091 On the other hand, getting back Super Admin access is less straightforward, but by no means is it impossible.

    1. Go into wp_sitemeta and look for site_admins.
    2. In there you will see something like this: a:1:{i:0;s:7:"Ipstenu";}
    3. If your userID is ‘superman’ then it would be a:1:{i:0;s:8:"superman";}

    Capitalization and stringlength matter. Add one user, and use that to correctly restore power to the others.

    Can you do this via WP-CLI? Yes, if you’re on the latest versions. Kind of. You can get a list of super admins via wp network-meta get 1 site_admins and in theory wp network-meta update 1 site_admins USERNAME would work except that the data is serialized. I opened a ticket with WP-CLI, and it’s a ‘plugin territory’ issue right now, so I’ll have to see if I can code it myself.

  • Speaking at WordCamp San Francisco – 2013

    Speaking at WordCamp San Francisco – 2013

    It’s true! I’ll be speaking at WordCamp San Francisco again this year.

    Screen Shot 2013-06-21 at 12.39.45 PM

    Last year I talked about supporting WordPress and how you can give back. This year, the subject of my talk is “Don’t Use WordPress Multisite.” I wrote a post here about that in 2011, and while quite a lot of it remains true, I still see hundreds of people who think Multisite is the cure to all that ails ’em.

    I love it, but it’s not everything and a side of fries. But I’m not going to give away the talk here, and it’s not just going to be a copy of that post. So feel free to read it, offer comments, and meet me where I left my harp: Sam Frank’s Disco.(This is a very bad joke I’ll tell you if you want.)

  • Multisite Stands Alone

    Multisite Stands Alone

    NKOTBWhile I wrote up a lot of reasons why you shouldn’t use Multisite, the truth is I really like it and find it well suited to my needs. But one of the big problems with it is that everyone’s network setup is different. Many times, when people ask for help in the forums, I have to sketch out the bare ideas of what to do and why. This brings people to their biggest complaint in Multisite: Why isn’t there a plugin for this already?

    First and formost, Multisite is still ‘new’ for the mainstream. Thelonius, the 3.0 release, is only two and a half years old! WordPress 1.0 came out in 2004, just as a reminder. 3.0 is when Multisite was folded into full WordPress, and it’s not been there very long, but it’s changed a lot since the start. In 2010, when 3.0 came out, there were 10,000 plugins in the repository. Today we’re at 22,000 and growing every day. When it comes to single site WordPress, the plugin world is mature and populated. Of those 22,000, about 300 are specific for Multisite. That’s a pretty small number when you look at the over 1000 plugins that do something with Twitter. Of course, most plugins work with Multisite anyway, but the ones that are Multisite specific are the ones to look at here.

    A plugin is developed to fit a need. A good developer tries to keep the plugin simple and adaptable, so as many people as possible can use it for as many situations as suit their needs. Doing that has a lot of weird scope creep, of course, and if you consider that we do have 1000 twitter related plugins, you may understand why. Plugins fit a need, and when they don’t we extend/fork/hack the plugin to fit our specific need. Multisite, in and of itself, is fitting a need, and while that need is very specific, it’s also very broad. There are myriad reasons to use Multisite, and because of that, those 300 plugins that are built specifically for Multisite have to meet all of our needs. Of course, that’s not how it works.

    While the majority of themes and plugins work just fine on Multisite, the ones people get in arms about are the ones that are supposed to be ‘for’ Multisite. These plugins should do more, but not too much. They should meet my specific needs, as well as all of yours and hers and his too. There should be a plugin for everything. Why am I the only person who wants this? I walk away from those arguments a lot, or I point out “You’re not the only person who wants it, but you’re possibly the only person who wants it in that way.”

    Plugins are not the silver bullet for everyone. Your site may be a werewolf, mine a zombie, and his a vampire. Each one has their own needs and because of that, their own requirements. So let’s be direct. The whole reason you can’t find the perfect plugin is because no one’s a mind reader. The reason you can’t find everything you want in one plugin is because you didn’t write it (or have it written).

    What does that mean? Multisite is still young, and those 300 Multisite specific plugins aren’t all Multisite specific first of all. At least a third are listed as Multisite because they work on Multisite. For example, bbPress is tagged ‘multisite’ but it wasn’t built ‘for’ Multisite. On the other hand, Networks for WordPress is built for Multisite, and nothing else.

    The best way to tell if a plugin is built just for Multisite is to see if it set ‘Network:true’ in the code. If you open up the code of the plugin, you can see this in the header:

    Now, not all Multisite plugins are meant to be Network enabled, but only plugins that are for Multisite will be Network only like that, so it’s one way to make sure that plugin is intended for Multisite. The downside to that is expressed via something like BuddyPress, which if you use on a Multisite must be network activated, but you don’t have to use it on Multisite. This means the check isn’t perfect.

    NKOTB 2010The point to all this is that Multisite’s still the new kid in town. It isn’t perfect, and it is still evolving and changing in pretty dramatic ways. Also, I find it pretty cool to watch it grow. But the reason you can’t find all the plugins you want with it is really simple: They haven’t been written. You may actually be the first person who wants something done in that specific way, and with the myriad new methods Multisite gives us to do amazing things, there’s a lot of room for different options.

    What should you do if you’re not a coder and want something that’s never been done? Well, learn to code. Or hire a coder. I wish there was another way, but when you want that special one-off toy that really isn’t suitable for everyone, you’re going to need to meet the challenge head out. None of this is meant as an excuse, by the way, but an explanation. It’s just not done. Yet.