Half-Elf on Tech

Thoughts From a Professional Lesbian

Category: How To

  • Self-Update Your Plugins

    Self-Update Your Plugins

    When your plugin is hosted on WordPress.org, this isn’t a problem at all. But if you’re selling your own work, or hosting it on a non WPORG resource, there are other concerns. You see, if you host a plugin on WordPress.org, your plugin can’t have it’s own updater script. You have to use the default .org updater. This is just fine, except when you have an add on that you want to be pay-only. Then what?

    Take a look at Easy Digital Downloads. You can get the main plugin from WordPress.org, and if you buy add ons from their site, they get magical updates too! How did they do that? They put an updater script in the main plugin which is then called by the paid extensions. You can even use their Software Licensing add ons to run your own updates on your server! If you want to sell on their site, they’ll help you take care of that too.

    Todd Lahman also has an WooCommerce API manager, so if you’re using WooThemes, you’ve got that covered too.

    Success on a mountain top

    Speaking of self hosting, if you’re hosting your own code on Github, then you want to use Andy’s Github Updater. While it’s not allowed on .org (sorry Andy), this will let you push updates from your GitHub or Bitbucket hosted WordPress plugins and themes.

    My buddy Norcross has his own free updater for you as well.

    You can also look at services like Auto Hosted or WP Updates, both of which promise to make it even easier and faster for you.

    Jeremy Clarke has a automatic theme/plugin updater as well if you still want to be self hosted.

    If you’re using ThemeForest, there’s the Envato WordPress Toolkit, which your users (not you) will need to install on their sites to get updates. I don’t know if there’s a way to include an updater in your packaged theme or plugin, but that toolkit needs to be all over the place for users. That it’s not brings all the issues you see with their products being out of date.

    There are hundreds of other ways around this. And really, there’s no excuse to not keep your plugins and themes up to date, no matter where they live. Keep those users updated and make it easy for them to do it! What resources do you use when self-hosting a plugin or theme, to keep it on the up and up, and keep everyone updates?

  • Mapped Domains And Google Search

    Mapped Domains And Google Search

    The other day I was surprised to learn that Google still looks for tech.ipstenu.org

    Kind of.

    If you go search for it, Google still believes that URL is a real thing: https://www.google.nl/search?q=site:tech.ipstenu.org

    Some of those URLs were made long after I mapped the domain, by the way. And yes, of course I have a 301 redirect for the subdomain.

    <If "%{HTTP_HOST} == 'code.ipstenu.org' || %{HTTP_HOST} == 'tech.ipstenu.org' ">
        RedirectMatch 301 (.*) https://halfelf.org$1
    </If>
    

    What’s going on here? Strictly speaking, Google’s right and stupid. The URLs are correct, but Google should be honoring the 301 redirect. Because it’s not, you have to tell it not to trawl your subdomains and use a robots.txt file, just for your mapped subdomains.

    First we’ll need to make a special robots.txt file, like robots-mapped.txt, and put the following in it:

    User-agent: *
    Disallow: /
    
    User-agent: Googlebot
    Noindex: /
    

    This tells Google to sod off. Then you need to specify when to use this special file, and that brings us to the lands of options. Since .htaccess is a top-down file, that is it reads from the top of the file down, you can get away with this:

    RewriteCond %{HTTP_HOST} = (code|tech).ipstenu.org
    RewriteRule ^robots\.txt$ /robots-mapped.txt [L]
    

    Just have that above any redirect rules for other things. But what if, like me, you’ve got Apache 2.4?

    <If "%{HTTP_HOST} == 'code.ipstenu.org' || %{HTTP_HOST} == 'tech.ipstenu.org' ">
        RedirectMatch 301 ^/robots\.txt /robots-mapped.txt
        RedirectMatch 301 (.*) https://halfelf.org$1
    </If>
    

    Of course, that sends tech.ipstenu.org/robots.txt to https://halfelf.org/robots-mapped.txt which is scary but still works, so don’t panic.

    Another way to do it would be to have a massive rewrite for all my subomains:

    # All Mapped
    <If "%{HTTP_HOST} == 'code.ipstenu.org' || %{HTTP_HOST} == 'tech.ipstenu.org' || %{HTTP_HOST} == 'photos.ipstenu.org' ">
        RedirectMatch 301 ^/robots\.txt /robots-mapped.txt
    </If>
    

    I will note, it should be possible to have (code|tech).example.com work in there, instead of all those OR statements, but I’ve yet to sort that out (corrections welcome in the comments!).

    The last step is to fight with Google Webmaster Tools. Add your subdomains and you should get this on the robots.txt checker:

    Example of robots.txt for tech.ipstenu.org in Google Webmaster

    If you don’t, don’t panic. Go to the Fetch as Google page and tell it to fetch robots.txt. That will force it to recache. Once you have it right, ask Google to remove the URL from their index, and in a few days it’ll sort out.

    It’s very annoying and I don’t know why the 301 isn’t honored there, but oh well. At least I can make it work.

  • Did You Know …. Gravatars

    Did You Know …. Gravatars

    I we helping someone debug their gravatar recently. There was a long back and forth about your WordPress.com vs WordPress.org account when he couldn’t log in, and once we sorted that, we wanted a way to check if the Gravatar was actually working. Lo! There’s an easy way:

    https://en.gravatar.com/site/check/

    You can put in anyone’s email and get their Gravatar, which is a great check for people on, say, WordPress.org complaining theirs isn’t working when it totally is, had they used the right email.

    There are some things I wish Gravatar had, though, like the ability to drag-and-drop new avatars instead of the old click-here-to-select interface that feels so very, very, old now.

  • Featured Image Size

    Featured Image Size

    I’m particular about a lot of things, including my excerpts and featured images. The biggest problem I have is remembering what my featured image size should be. You see, I do slap up a custom image, just for that, most of the time, and remembering that the size should be 900×220 every day is something I just can’t do. So I lamented, as I checked for the 99th time, that I should be able to pull in the size!

    What I want is this:

    Example of featured image meta box with the size indicated

    And yes, I did it with this in my functions.php for my theme:

    //* Add new image sizes
    add_image_size( 'featured-image', 900, 220, true );
    
    //* Change Featured Image to remind me what the size is
    add_filter( 'admin_post_thumbnail_html', 'helf_admin_post_thumbnail_html' );
    function helf_admin_post_thumbnail_html( $content ) {
    
    	// Get featured image size
    	global $_wp_additional_image_sizes;
    	$featured_image = $_wp_additional_image_sizes['featured-image']['width'].'x'.$_wp_additional_image_sizes['featured-image']['height'];
    
    	// Apply
    	$imagesize = '<p>Image Size:' . $featured_image . 'px</p>';
    	$content = $imagesize . $content;
    
    	return $content;
    
    }
    

    The trick there is I have to know the name of my featured image. Since I use Genesis, it’s usually named ‘featured-image’ but it could be anything. That also means on my Theme Settings I have this set:

    Genesis Content Archives

    And that has to match. So, since I am running Genesis, it’s a quick change to put in this check instead:

    add_filter( 'admin_post_thumbnail_html', 'helf_admin_post_thumbnail_html' );
    
    function helf_admin_post_thumbnail_html( $content ) {
    	// Define what the name of our featured image size is
    	$genesis = get_option('genesis-settings');
    	$genesis_image_size = $genesis['image_size'];
    
    	// Get featured image size
    	global $_wp_additional_image_sizes;
    	$my_featured_image = $_wp_additional_image_sizes[$genesis_image_size]['width'].'x'.$_wp_additional_image_sizes[$genesis_image_size]['height'];
    
    	// Apply
    	$imagesize = '<p>Image Size: ' . $my_featured_image . 'px</p>';
    	$content = $imagesize . $content;
    
    	return $content;
    }
    

    The only thing I couldn’t get to work was an if-check around the filter so I could make sure I really am running Genesis. Future improvements, I suppose.

  • Marrying Multisite

    Marrying Multisite

    While there’s really no practical difference, server usage wise, between 100 separate sites and a multisite with 100 sites, a lot of us prefer to use Multisite for a variety of reasons. And today, assuming you have thought long and hard about those reasons, let’s talk about how to take 100 sites and fold them into one multisite. And yes, this will suck. If you read about how to break up a multisite, you may already have an inkling of the pain you’re about to embark on.

    Donna Noble, my second most favorite companion, strikes a pose

    Make A Temporary Site

    The first thing that makes it hard is that you have to keep your existing site up and running while you import it, no matter how you chose to import. So regardless of if you’re moving subdomains or subfolders, you need to make a temporary site. I like to keep the site names similar, and the same length because it’s easier for me. So if I’m moving a site with the slug ‘donnanoble’ then I’m going to make the new site on my network named ‘donnanobl1

    There’s a practical reason for this. When I’m all done with everything, I can do a search/replace with any tool to change it back to ‘donnanoble’ and I don’t have to use a tool like the interconnectit Search/Replace DB script that has serialization safe super powers. If you use WP-CLI, the built in wp search-replace tool has this already, and I’d be using that personally. The point is that you will be renaming everything at the end to the original name eventually.

    Bring in the Content

    I personally do this via the WordPress Import/Export feature.

    Now look, I know you can port over the tables and rename them but … I wouldn’t. Why? The users. The tables for the users have to be pulled over with the right user meta, and you would have to marry the wp_users and wp_usermeta tables in a way that no user ID was duplicated. Frankly, I don’t think it’s really possible to do that well. If I had to, I would actually manually create the new users on my Multisite and make a note of that new ID. Oh and of course the user names can’t both be admin. You can’t have two Doctors at once. Well. You can. And I’m sure they all use the same username, but you’re using WordPress and not a TARDIS, so if two users have the same username, then either they’re going to be the same user or you’re going to have to make one a new account.

    Meta Crisis Donna Noble

    There are number of you thinking about how many people use ‘admin’ as their username, and yes, that’s exactly what I’m talking about. But if we’re lucky and doctor11 and doctor10 used different login IDs on their sites, then you’re just going to need to copy over the one line in wp_users for that:

    The Doctor - WP_USERS

    See how he has an ID of 10? That has to match all of these:

    Sample of wp_usermeta

    They don’t match right now, do they? Nope. The Doctor has an ID of 10, but the snippet I took from his site was for a user ID of 2, so I have to edit everything in wp_usermeta. Next, I have to rename my tables for wp_posts, wp_postmeta, etc etc over to wp_x_posts and so on, to make them match the new site ID. Oh and don’t forget wp_user_roles! You have to fix that for your new site ID too! And then reattribute all your posts!

    example of WP_POSTS with the user ID

    You see this slope and how it’s getting really slippery really fast? That’s why I won’t do it. It’s certainly possible, but it’s neither simple nor easy nor safe. Importing and exporting via WP’s built in tools has only two downsides as I see it:

    1. Your users have to make new passwords
    2. You have to reconfigure your theme and plugin settings

    That first one doesn’t bother me. The second one doesn’t either, since not all the plugins and themes work the same way on Multisite, so I probably want to take the time to do it all cleanly anyway. That does mean that I can’t automate things, but at the same time, I’m not particularly sure I want to. Taking each site one at a time will take longer, but it will let me be careful and test everything every step of the way.

    Either way, once you have the site content in place, and your site settings look and feel how you want them to, it’s time to do a flip.

    Flip The Sites

    Take your original site, donnanoble, and rename it. If it’s a subdomain, turn off whatever weirdness you did in your panel to map the subdomain. For most types of server panels, having both named subdomains and a wildcard can live happily together, because the ‘real’ subdomain will supersede the wildcard. If not, you’ll need to change that subdomain to point to the location of your main install of WordPress. So if you’re in /public_html/donnanoble/ then that becomes /public_html/ on it’s own.

    Either way, you have this real folder on your server called donnanoble and that needs to be renamed to anything else. At this point, I tend to use donnanoble-disabled because it is. Also it’s not supposed to work anymore.

    Once you’ve broken donnanoble, it’s time to go into your network admin, go to the sites page, and edit the donnanobl1 site. Rename that to donnanoble, and check the box to change both home and site URL. Oh, and remember I mentioned search and replace before? Run that now. Change donnanobl1 to donnanoble all over the whole database.

    I told you it wasn’t super easy

    Donna Noble making a silly face

    If you’re like me, you now have a bit of a headache, thinking about doing this 100 times. It’s one of those things that should conceivably be easier than it is, but right now WordPress really only has a way to export content and not settings (which is pretty much why we have such nightmares segregating content and code).

    It may be plausible to use tools like BackupBuddy to import, but you still will find yourself at a tense moment when you have to flip the real and temporary sites around.

  • The Revolution of .htaccess and Multiple Domains

    The Revolution of .htaccess and Multiple Domains

    I mentioned this in a post about jiggering Google and Multisite WordPress, and my buddy Jan went “WOW!” So I’ll start with the best thing ever in Apache, to me at least. Apache 2.4 allows for real if/else statements in .htaccess.

    Benjamin Franklin's glasses - because revolution jokes are funny

    In 2012, I wrote about how I did a lot of request header detection in order to make myriad blocks of checks to sort out my .htaccess anarchy. As I explained here, I have to do a check for the domain for each and every rewrite rule:

    Why did I duplicate the RewriteCond? Typically, you cannot use multiple RewriteRule statements following a single RewriteCond. That means for ever call I make to a domain, I can use but one rewrite rule. There are ways around that, but none of them worked well for me.

    It’s ugly on Apache 2.2. Since that time, however, I’ve moved to Apache 2.4, and the world is vastly different thanks to If/Else calls!

    Let’s take this old section I had from my move (about 6 years ago) from blog.ipstenu.org to ipstenu.org, as well as some permalink changes and a change to my uploads folder:

    # Ipstenu Moves
    RewriteCond %{HTTP_HOST} ^blog\.ipstenu\.org
    RewriteRule ^(.*) https://ipstenu.org/$1 [L,R=301]
    RewriteCond %{HTTP_HOST} ^ipstenu\.org
    RewriteRule ^blog/([0-9]{4})/([0-9]{2})/(.*)$ https://ipstenu.org/$1/$3 [L,R=301]
    RewriteCond %{HTTP_HOST} ^ipstenu\.org
    RewriteRule ^blog/(.*)$ https://ipstenu.org/$1 [L,R=301]
    

    Taking each block at a time, the first was easy:

    <If "%{HTTP_HOST} == 'blog.ipstenu.org'">
        RewriteRule ^(.*) https://ipstenu.org/$1 [L,R=301]
    </If>
    

    Pretty simple. If the host is blog.ipstenu.org, redirect. And it mostly worked. Except where http://blog.ipstenu.org/dsfasfsdf sent me to https://ipstenu.org/home/ipstenu/public_html/dsfasfsdf … Which isn’t good! The fix here is that you use RedirectMatch instead of RewriteRule, which gives us this!

    <If "%{HTTP_HOST} == 'blog.ipstenu.org'">
    	RedirectMatch (.*) https://ipstenu.org$1
    </If>
    

    Excellent, then on the second one which becomes this:

    <If "%{HTTP_HOST} == 'ipstenu.org' ">
    	RedirectMatch ^/blog/([0-9]{4})/([0-9]{2})/(.*) https://ipstenu.org/$1/$3
    	RedirectMatch ^/blog/(.*) https://ipstenu.org/$1
    </If>
    

    What’s the difference here? Well, RewriteRule is handled by Apache’s mod_rewrite, while Redirect is handled by mod_alias. I know I have mod_rewrite on, but I don’t know why it insists on tossing in the path statement.

    However I can assure you that these ifs work perfectly. I’m using them right here on this site. My whole .htaccess is wrapped with them.