Half-Elf on Tech

Thoughts From a Professional Lesbian

Tag: wordpress

  • Encrypt My Site, Please!

    Encrypt My Site, Please!

    By now everyone running a website has heard about how Google gives sites running SSL a bit of a bump with search rankings. It’s been a year since they started doing that. The bump is not significant enough to impact most people, but making all the things HTTPS is still a good idea.

    It’s really all about security. I personally use HTTPS for the backend of my WordPress sites. Logins and wp-admin are all secure. The same is true for my MediaWiki site and my ZenPhoto gallery. I access things securely because the data I transmit could be important. Sure, it’s just passwords and such, but then you look at my site where I sell eBooks.

    That site is on the same server, the same account, and the same WordPress install as this one. You bet your ass I’m making it all secure. But this comes at a cost.

    The invention of SPDY aside, HTTPS is rarely as fast as HTTP. It can be difficult to set up caching or implement terminations like via Pound or Nginx in order to cover for the fact that Varnish doesn’t cache SSL. These things aren’t impossible to do. They’re just harder. And they’re generally going to be slower than plain old HTTP.

    The question has never been if they can or cannot be done, but if they can by entry-level people. Certainly we can say “If they’re not using SSL for all the things, they’re not ready for a great volume of business” and use it as a demarcation for things. And when we’re communicating our private lives, we should certainly consider this. But then, this site, where only I log in?

    Do you need SSL? Would it make you feel better or more secure? All you can do is comment. Do you need the feel-good? Do I need the extra security? If I decide yes, then I have to consider the weight this puts on my site. I have to consider how best to cache the content.

    I also have to think about how to get a certificate and SSL certs can be the biggest Internet scam out there.

    It’s how much for a multi-domain, including subdomain, SSL cert a year? A few hundred? It’s a bigger hassle than the EU Vat drama. It’s expensive, it’s a hassle to get set up, and install. Now thankfully, next month we’re expecting Let’s Encrypt to show up and they’ll make the cost less prohibitive. It doesn’t make the drama of installing the certs any better, but it’ll lower the bar for people who are trying to make things secure.

    Yes, you can get StartSSL for free, but it’s not as simple as all that. When all you need is one certificate, it’s only about $10 a year and that’s fine. When you start getting into the need to secure all the things, it’s a mess.

    What has to happen next, though, is for sever software to step up. Apache and nginx are both far faster now than they have been, but they’re our ultimate breakpoint. PHP has to push itself to handle things better and faster, lest we run over to HHVM. We are getting better of course, but if we want everyone to be on HTTPS, we have to make it easy.

    Not easier.

    Easy.

    The bar is still too high for the majority of people, and that’s a problem. Either we start offering hosting services to handle this or we start making the software easier. But we can’t just say “Oh, it’s simple to make your site HTTPS and fast.” because it’s not.

  • Making a WP-CLI Plugin

    Making a WP-CLI Plugin

    I love wp-cli. It makes my life so much easier in so many ways.

    I’ve added in some basic commands to some of my plugins because it makes things easier for others. And as it happens, adding wp-cli commands to your plugins isn’t actually all that hard. But did you know you don’t have to?

    The Basic Code

    For our example I’m going to make a command called halfelf and it’s going to have a sub-command called ‘stats’ which outputs that the HalfElf is alive. And that looks like this:

    WP_CLI::add_command( 'halfelf', 'HalfElf_CLI' );
    
    class HalfElf_CLI extends WP_CLI_Command {
    
    	/**
    	 * Get HalfElf Stats
    	 *
    	 * ## EXAMPLES
    	 *
    	 * wp halfelf stats
    	 *
    	 */
    	public function stats( ) {
    		WP_CLI::success( __( 'HalfElf is currently alive.', 'halfelf' ) );
            }
    }
    

    The docblock controls the output for the help screen, which is possibly the most brilliant thing about it.

    Of course, all that does is make a command that doesn’t rely on any WordPress plugin, which is cool. Here’s a different example. In this one, I’m triggering a command to my logger function to reset the backup log or to view it:

    
    	/**
    	 * See Log Output
    	 *
    	 * ## OPTIONS
    	 *
    	 * empty: Leave it empty to output the log
    	 * 
    	 * reset: Reset the log
    	 *
    	 * wp dreamobjects logs
    	 * wp dreamobjects logs reset
    	 *
    	 */
    
    	public function log( $args, $assoc_args  ) {
    		if ( isset( $args[0] ) && 'reset' !== $args[0] ) {
    			WP_CLI::error( sprintf( __( '%s is not a valid command.', 'dreamobjects' ), $args[0] ) );
    		} elseif ( 'reset' == $args[0] ) {
    			DHDO::logger('reset');
    			WP_CLI::success( 'Backup log reset' );
    		} else {
    			file_get_contents( './log.txt' );
    		}
    	}
    

    Because wp-cli runs as WordPress, it has access to WordPress commands and functions.

    But. Where do we put this file?

    In a WordPress Plugin

    If you want to use that code in a WordPress plugin, you put it in a file called wp-cli.php (or whatever you want) and then call it in your main WordPress plugin file like this:

    if ( defined( 'WP_CLI' ) && WP_CLI ) {
    	require_once( 'wp-cli.php' );
    }
    

    If you do that, I would recommend putting this at the top of your wp-cli.php file.

    if (!defined('ABSPATH')) {
        die();
    }
    
    // Bail if WP-CLI is not present
    if ( !defined( 'WP_CLI' ) ) return;
    

    That will prevent people from calling the file directly or in other ways.

    In the case of my DHDO code, I added in this check:

    if( class_exists( 'DHDO' ) ) {
    	WP_CLI::add_command( 'dreamobjects', 'DreamObjects_Command' );
    }
    

    That means if (for whatever reason) DHDO can’t be found, it prevents you from doing things.

    On It’s Own

    But. That first command doesn’t need a plugin, does it? So if it doesn’t need a plugin, could I still use them? The answer is of course. The wp-cli.php file is the same, but where you put it changes. This will all be done in SSH. You could do it in SFTP if you wanted.

    In your home (or root) directory we have to make a folder called .wp-cli – please note the period, it’s like your .htaccess file. Except it’s a folder. In there you’re going to make a folder called commands and in that folder we’ll put another one for our commands. Like if I’m putting my HalfElf commands out there, I’d make a folder called halfelf and in there I put my command file command.php

    That gives me this: ~/.wp-cli/commands/halfelf/command.php

    However that doesn’t act like plugins or themes or mu-plugins, you have to add the command to another file. I know, I know. Make a file called config.yml and put it in .wp-cli so you have this: ~/.wp-cli/config.yml

    The content of that file is this:

    require:
      - commands/halfelf/command.php
      - commands/some-other/command.php
    

    And that’s it! Now you’ve got some command line tools for your WordPress site!

  • Name Collisions

    Name Collisions

    Many many years ago I played MUSHes. One of the games was PernMUSH (which apparently is inactive now). PernMUSH took place on the world of Pern, and you had the chance to be a dragon rider. Which was kind of the Thing to Be ™. One of the ‘quirks’ of the game was that every character had to have a unique name, and so did each dragon. When I started playing, I didn’t really understand this. Today I know that it’s because of name collisions.

    A “name collision” is a problem not solely endemic to computers, but it comes up there an awful lot, whereby you must have a unique identifier to know what each ‘thing’ is. For example, in WordPress every post has two unique identifiers. It has a post ID, which is a number given to the post when it’s stored in the database. If you use ‘ugly’ permalinks, you’ll see this as example.com/?p=123 – that 123 is the post ID. But if you use pretty permalinks (like I do here — example.com/my-cool-post/) then you have to have only one ‘post’ with that name.

    You, literally, cannot have two posts with the same ID or name. Makes sense, right?

    On PernMUSH we had everything have a unique ID as well as a unique ‘nice’ name. But then when dragons were introduced, you had to give them unique names as well. This was not for frivolous reasons nor pretty special snowflake ones. While it was perfectly understandable to have a hundred rooms named “Bedroom,” the code for the dragons allowed them to all talk to each other and send private messages. They were, basically, our cell phones. Dragon Ath had to be able to talk to dragon Bth, and in order to ensure that worked properly without everyone having to type dtu #12724=message we had to have the code written such that someone could type dtu bth=message and that meant each name had to be unique.

    This would have been fine and dandy as it was except for one small problem. PernMUSH wasn’t the only MUSH based on Pern. There was also a game called SouCon, which took place on the Southern Continent. And transfers between the games were allowed. This added in a wrinkle that now PernMUSH and SouCon had to be sure that everyone on both games had a unique name and dragon name.

    It was quickly determined that they wouldn’t bother with human names. If J’cob on SouCon came to visit PernMUSH, which already had a J’cob, then SouCon’s J’cob would use a different name like Jy’cob. But for whatever reason it was decided that the dragon names on both games were going to be unique. Thus the “All The Weyrs List” was created. That list (which still exists at dragons.pernmu.com ) was a mostly honor system site where you would email in your ‘hatching records’ with who’d impressed and to what dragon and what color and who were the parents. The list would be updated. Then the next time anyone had a hatching, they’d search that page for the dragon names they wanted to use. If the name was there, then then couldn’t use it. Done.

    Of course this wasn’t perfect. Anything based on the honor system is bound to have a few bad eggs. After 10, 15, 20 years, the ability to give people the name they ‘want’ starts to chaff against the tacit agreement not to repeat a name. At some point, I know some games gave up and let people have whatever name they wanted, and transfers could cope.

    What does all this have to do with anything?

    On the WordPress.org servers, where we list all the plugins approved by the team, each plugin has a unique slug that cannot be changed. I have a plugin called Impostercide, which has the slug of impostercide and it’s the only one. No one else can submit a plugin with that name. For the most part, this worked fine. If someone else wanted to make a plugin with that name, they were free to do so but it just wouldn’t be on WordPress.org and that was okay.

    Then we shot ourselves in the spirit of making life easier. Today WordPress updates your plugins and themes by using an API that calls back to the wordpress.org servers. That API check sees if Impostercide on your install of WordPress is older than the one on wordpress.org and, if so, alerts you to update. You press a button and your plugin is updated. It’s magic. It’s gold. It’s great. If you’re that person who wrote your own plugin, not on wordpress.org, you can hook into the update code and have it update from other servers. It’s brilliant.

    Except what if you’re that person who has their own plugin named Impostercide? The obvious answer is that you can just rename your folder and off you go. That doesn’t fix the thousands of people who just upgraded themselves to my version, though. They’re having a bad day. Also what if someone submits a plugin called impostercide-two? Now you have the same problem all over again. Other people will tell you to bump the version to something the real Impostercide will never use. But again, that doesn’t hold up since what if Impostercide does?

    The actual fix is to tell WordPress not to check for updates for that specific plugin.

    The awesome Mark Jaquith posted about this in 2009. You can code a plugin to tell WordPress to not check for updates for it. This does put the onus on people who are writing the plugins not hosted on wordpress.org though, which is and isn’t fair. There’s a movement to allow a new plugin header to prevent these things in trac ticket 32101, which boils down to the idea that if those non-org hosted plugins can flag themselves as ‘I’m not from .org’ then the API stops trying to update them.

    I think that it would be a good idea to have an easy way for people to flag their plugins as not being hosted. The alternative would be an honor system method, where everyone registers their plugin slugs and all submissions to wordpress.org is checked against that. But that falls apart quickly the day one person forgets to do it. With a way to easily kill the API check, we can allow non-org hosted plugins to very simply protect themselves, and their users, from being stomped on.

    As for the risk that someone might edit their own locally installed copy of Jetpack to have that header because they’re tired of updates, well, we can’t stop you from shooting yourself. I just hope people are smart enough to understand that you don’t edit core and you don’t edit plugins and you don’t edit themes. You make child themes, you use other plugins, and you use filters and hooks.

  • Varnish Cache and Cache-Control

    Varnish Cache and Cache-Control

    In our quest for speed, making websites faster relies on telling browsers when content is new and when it’s not, allowing them to only download the new stuff. At their heart, Cache Headers are what tell the browser how long to cache content. There’s a special header called Cache-Control which allows each resource to decide it’s own policy, such as who can cache the response, when, where, and for how long. By default, they time we set for the cache to expire is how old a visitor’s copy can be before it needs a refresh.

    A lot of the time, I see people setting Cache-Control to none and wondering why their site is slow.

    Since I spend a lot of time working on DreamPress, which uses Varnish, I do a lot of diagnostics on people with slow sites. One of my internal scripts checks for Cache-Control so I can explain to people that setting it to none will tell Varnish (and browsers) literally not to cache the content.

    The way it works is that they actually set things to ‘no-cache’ or ‘no-store.’ The first one says that the content can actually be cached, but it’s going to check and make sure the resources haven’t changed. It’s not really ‘no-cache’ but ‘check-cache.’ If nothing’s changed, there’s no new download of content, which is good, but it’s still not caching.

    On the other hand, ‘no-store’ is really what we think about when we say not to cache. That tells the browser and all intermediate caches that every time someone wants this resource, download it from the server. Each. Time.

    What does this have to do with Varnish? Well here’s the Varnish doc on Cache-Control:

    no-store: The response body must not be stored by any cache mechanism;

    no-cache: Authorizes a cache mechanism to store the response in its cache but it must not reuse it without validating it with the origin server first. In order to avoid any confusion with this argument think of it as a “store-but-do-no-serve-from-cache-without-revalidation” instruction.

    Since Cache-Control always overrides Expires, setting things not to cache or store means you’re slowing down your site. Related to this, if you set your Max-Age to 0, then you’re telling visitors that the page’s cache is only valid for 0 seconds…

    And some of you just said “Oh.”

    Out of the box, WordPress actually doesn’t set these things poorly. That generally means if your site kicks out those horrible messages, it’s a plugin or a theme or, worst of all, a rogue Javascript that’s doing it. The last one is nigh-impossible to sort out. I’ve only been able to do it when I disable plugins and narrow down what does it. The problem is that just searching for ‘Cache-control’ can come up short when things are stashed in Javascript.

    But there’s some kind of cool news. You can tell Wordpress to override and not send those headers. I’ve not had great success with using this when it’s a script being an idiot, but it works well for most plugins and themes that seem to think not caching is the way to go.

    From StackExchange:

    function varnish_safe_http_headers() {
        header( 'X-UA-Compatible: IE=edge,chrome=1' );
        session_cache_limiter('');
        header("Cache-Control: public, s-maxage=120");
      if( !session_id() )
      {
        session_start();
      }
    }
    add_action( 'send_headers', 'varnish_safe_http_headers' );
    

    And yes, it works on DreamPress.

  • Uniqueness Matters

    Uniqueness Matters

    This email gets sent a lot to plugin devs lately:

    All plugins should have unique function names, defines, and classnames. This will prevent your plugin from conflicting with other plugins or themes.

    For example, if your plugin is called “Easy Custom Post Types”, then you might prefix your functions with ecpt_{your function name here}. Similarly a define of LICENSE would be better done as ECPT_LICENSE.

    Please update your plugin to use more unique names.

    And once in a while someone asks why we care so much.

    There are 38,308 active plugins in the WordPress.org repository. If every one of them uses a global define of IS_PLUGIN_SETUP then they will all conflict with each other. If half use a script handle of plugincss then all those plugins will stomp over each other when it comes to enqueuing the CSS.

    It’s literally a numbers game.

    Every day we get at least 30 new plugin submissions to WordPress.org. That means every day at least 30 new potential conflicts show up. And it’s not just plugins. In WordPress 4.2, a new function was added: get_avatar_url()

    This was a great idea that saved people countless hours of work. Unless they logged in to see the error Fatal error: Cannot redeclare get_avatar_url() prance across their screen.

    Now in this case, theme authors had previously been told to include/make themselves, but was later added to core. All theme devs hosting on WordPress.org were notified and it was posted on the change blogs. But not everyone remembers to check those. And not everyone updates their themes right away. In a way, this probably could have been communicated better, but had the themes called their function mythemename_get_avatar_url() then this wouldn’t have been a problem.

    Prefix everything. Make it unique to your plugin or theme. WordPress is ‘home free’ and shouldn’t have to, but you should.

  • Mailbag: Multisite Subdomains Live Where?

    Mailbag: Multisite Subdomains Live Where?

    Heather is confused, and I don’t blame her:

    I am want to use subdomains in my multisite. 1. Install WordPress in the subfolder and set it up to run from root before you create your subsites. 2. You should not use www in your URL ….. Where exactly do need to change this? Settings/ General ( that’s how i saw it in your book) or in my file manager, having to change it in many different files…. ( saw and read this from other internet sources).

    Let’s take this by the numbers.

    1. Install WordPress in the subfolder and set it up to run from root before you create your subsites.

    If (and that’s a big if) you want to install WordPress at example.com/wordpress but have the URL look like example.com then you must do this before you activate Multisite. Can it be done after? Yes. But you will go insane.

    1. You should not use www in your URL

    If you’re using subdomains, just don’t. The issue where WordPress breaks if you use the www here is not to do with WordPress so much as the variant hosts out there and how they handle the www/non-www redirects. Save yourself a headache. Don’t use www. You don’t use www. Yes, I know Google does. They don’t care so long as you’re consistent.

    In both cases, on your single site install of Wordpress, you go to the General panel. The value for Site Address (URL) is what you want people to see when they visit your site. The one for WordPress Address (URL) is where WordPress is installed.

    Make sure they both match in terms of schema and www. Then change the Site Address from http://example.com/folder to http://example.com and save it.

    The official directions are on the codex – Giving WordPress it’s own Directory. There’s a bit more when it comes to moving a couple files, but really that’s it. Once it’s done and working, go ahead and activate Multisite.

    By the way, I always get the WordPress Address and Site Address confused. It’s not just you.