Half-Elf on Tech

Thoughts From a Professional Lesbian

Author: Ipstenu (Mika Epstein)

  • WordPress Multisite Control

    WordPress Multisite Control

    When you write a plugin for WordPress Multisite, you have three options for how to let users control the plugin options. It comes down to the manipulation of the ways we have to activate a plugin on Multisite, which are per-site or network only.

    I’m a firm adherent of having the network control as much as it logically should, but allowing each site to pick unique features. Never should someone be shocked to find out they’re on a network. A network is, after all, a collection of WordPress sites. Now your collection may or may not be related, but at the end of the day, someone should never be surprised to find out the site they signed up for is on a network.

    With this in mind, I separated the ‘control’ of the plugins into three groups.

    Network Only

    A Network Only plugin is one that should be controlled via the Network Admin. While the Settings API is a terrible bag of wet hair for Multisite, if you have a network plugin, then it should be for the network. The plugins that have no interface at all should be network activated. This is really simple, but in general if you’re adding this feature to your network, you probably want it on for everyone. There are some rare exceptions, but in general, network only is the key.

    Most network only plugins are clever enough to use Network: true in their plugin headers, which makes this much easier. If you think your code should only be activated by the network, use that.

    Per-Site

    A per-site plugin is activated on each site, controlled from each site, and the network admins have no authority save uninstalling the plugin. These plugins are things that each site should decide how to use. When I look at my own sites, I have a few that are like this. Like @Reply Two – when you look at it, you’d think it should be network only, but since it requires some per-site configuration with regards to comments, it’s best left as optional for each site.

    There is no Network: false setting, I’m afraid.

    Network Only Activation with Per-Site Control

    Here’s where it gets sticky, and plugins like Jetpack actually handle this better than most others. Take, for example, something like a plugin that adds features to a specific theme. If that theme isn’t active, the plugin shouldn’t error out. But a lot of us code our plugins to say “If this other plugin or theme isn’t active, don’t activate.” That sounds like a great idea except when you want to have it network activated. In those cases, the checks get weird and don’t run as expected.

    And then you have to consider what should control what. I mentioned Jetpack because it has a network admin screen.

    Jetpack's Network Override

    There you can enforce connections from your network admin, or not, as you see fit.

    Which One Is Right?

    While I’ve postulated this is very simple, it’s not. For example, when you have Jetpack, do I want everyone to edit every setting or just some? I’d want them to have the ability to use the CSS editor per-site, but maybe not VaultPress or Stats. The checks for that code is not as logical as it should be. The whens for running those checks, the priorities and weight given to who is more important, is not obvious.

    I would say that the Network Admins should have final say. But many people don’t agree with me on that. Many people think each site on a network would be best to exist on it’s own and stand alone, a part of a secret.

    And that too deserves room for thought.

  • Boundaries

    Boundaries

    My friend and coworker tipped me on to this post about The Asshole Filter which begs the question: “Why is everyone I deal with an asshole?”

    The post goes on to talk about how the issue is that if we draw a line in the sand but then allow people to cross that line, or worse reward them for doing that, we’re hurting ourself. In the example, a fellow named Fred used to accept personal emails about a project but now asks them to be sent to a group email.

    […] some people use fredsstaff@fredsconvention.tld and some people use Fred’s personal email.

    Who uses the officially designated email address?

    • People who feel strongly about following rules.
    • People who feel following the rules is generally a good idea.
    • People who respect Fred’s request because they’re generally respectful.
    • People who respect Fred’s request because they like Fred personally.
    • People who don’t want to antagonize Fred.
    • People who realize the problem Fred is trying to solve and want to be cooperative to reduce the burden on Fred.
    • People who feel it important to respect role boundaries.
    • People who are concerned that overwhelming Fred will cause their request to get lost.

    Who uses Fred’s personal email address?

    • People who can’t be bothered to learn and follow procedures.
    • People who feel rules are for other people.
    • People who feel they should get to cut in line.
    • People who don’t feel keeping track of what other people prefer is all that important.
    • People who aren’t troubled by the thought of pissing off Fred, either because they don’t care whom they piss off or because they think Fred is of no account.
    • People who feel entitled to get their way.
    • People who feel satisfaction when they find an illicit “shortcut” to getting what they want, that “suckers” are too “chicken” to use.

    In short, the decent, cooperative, law-abiding people all use the departmental email address, even though it doesn’t work a well as they might like, while the assholes continue emailing Fred directly.

    Did that just sound familiar to a lot of you who are thinking “I can just email Mika about plugins…”

    People often ask me why I sound angry when I tell you “Please email plugins@wordpress.org, don’t tweet/DM/Slack me asking for status. Just use the email and sit on your hands a bit.” I’m actually not angry. I’m annoyed. There’s a huge difference.

    Angry me logs off and calls it a day.

    Annoyed me rants a bit to someone who understands, or maybe says something passive/aggressive on Twitter about “Please use the plugins@ email…”

    In both cases, though, I probably waste at least an hour of my time not getting to the things everyone wants be to get to. In both cases, I feel incredibly disrespected and used. Yes, used. Because even when my friends say “Hey I have a quick plugin question…” the answer has once been a quick one. That question? Someone asked if he could adopt the plugin of a friend of ours who had died.

    First of all, that’s just an unexpected question by anyone’s standards (and it’s why we came up with a policy about handling death among developers). Second of all, it’s a touchy subject on it’s best day, so asking how to handle it was respectful. Third… He actually asked if he should just email the group.

    This was someone who clearly understood the reality, the situation, and the fact that there will always be exceptions.

    The sidebar of this issue is that, even if I ask someone to email a group, nine times of out ten it’s me who replied.

    I can give you a really long explanation, including how I plan to use those emails to train up new reviewers so you don’t have to wait on me, but let me ask you this instead.

    • Are you more or less important than everyone else who is waiting for their plugin to be reviewed?

    In general, if you get the ‘snippy’ reply of “Dude stop fucking things up and use the right channel” then I’ve already asked you, at least once, to “please” use the email. I’m very careful to ask nicely since I know there’s no possible way for everyone to know things. Mistakes are totally okay in my book. Intentionally trying to jump a queue just makes you an asshole, no matter your intentions. You’re disrespecting everyone, me and every other plugin developer out there, by demanding you get attended to first.

    Okay.

    So what would be a good reason to ping directly? Well about the only reason people do it that I consider thoughtful and respectful is this:

    Hey it’s been a week and I didn’t hear back about X. Did the email get lost or are you guys super backlogged?

    And maybe…

    I think [plugin reviewer] is treating me unfairly. Can you help or do you know who can?

    Both of those are totally perfect reasons to step off book. One is you not being sure if the email was received. The other is an issue with someone who might read the email.

    But do you see how they’re both asking, briefly, without a lot of drama or accusations, a simple question? Well. Not a simple question. But they’re asking in a way that shows they understand the situation of the world in general, they understand they’re asking for an exception, and they will respectfully accept the answers.

    By the way. The answer to the first one is 90% ‘backlogged’ and 10% ‘goddamn email!’

  • Google Advertising Experiments

    Google Advertising Experiments

    In the time since I’ve gone back to Google Adsense, I’ve had issues with some of their ads. Mostly religion and politics. Big shocker, right? Every once in a while, Google suggest I allow those ads:

    Consider allowing ads from sensitive categories to increase auction pressure and improve performance.

    I usually discard the suggestion, but this time they tried something new to me.

    … you can allow these ads now, or run an experiment to help you decide.

    Experiment?

    There are only two types of experiments right now. One is ad units, where you can adjust templates and ad sizes. The other is what I’m doing, allowing and blocking ads. I clicked on the experiment button, and it set up an A/B test for me, tracking the clicks of each version of my site, to see if anyone actually clicks on those ads.

    Screenshot of the experiment page, showing nothing since it just started

    Initially there was an option to automatically pick the best one, but I don’t know if I want to. I do know that I want to actually see if anyone who reads my sites wants to see political ads.

    The reason I’d blocked them is they were showing right-wing crazy people on my sites, and I’m not that person. They were showing ads I would deem offensive (and you have to work hard to offend me) so instead of reading every single ad, I decided to block all of them, assuming I wasn’t hurting my income too much.

    After this experiment, I’ll circle back and make a more informed decision. I wish there were more things I could experiment on, like specific ads in specific locations, but this ability to just see if the ads are clicked at all is a nice start for a free product.

  • Debugging Unexpected Output

    Debugging Unexpected Output

    It’s going to happen one day. You’re going to get that weird error when you activate your plugin to test it and you will have no idea what it means.

    What error?

    The plugin generated 306 characters of unexpected output during activation...

    Unexpected output.

    The problem is WordPress doesn’t tell you what did it, where, or why, not even if you have debug turned on. You do have debug turned on, right? Well I was stumped on this one. I checked all my PHP calls to make sure I didn’t have whitespace, I looked for any files that were accidentally saved UTF-8, and I checked and double checked my diffs between the good and bad versions.

    What I ended up doing was writing a function that saved the error and output it.

    /* For debugging only */
    if (defined('WP_DEBUG') && true === WP_DEBUG) { 
        function myplugin_activated_plugin_error() {
            update_option( 'myplugin_error',  ob_get_contents() );
        }
        function myplugin_deactivated_plugin_error() {
            delete_option( 'myplugin_error' );
        }
        add_action( 'activated_plugin', 'myplugin_activated_plugin_error' );
        add_action( 'deactivated_plugin', 'myplugin_deactivated_plugin_error' );
        
    	function myplugin_message_plugin_error() {
    	    ?>
    	    <div class="notice notice-error">
    	        <p><?php echo get_option( 'myplugin_error' ); ?></p>
    	    </div>
    	    <?php
    		}
    	if( get_option( 'myplugin_error' ) ) {
    		add_action( 'admin_notices', 'myplugin_message_plugin_error' );	
    	}
    }
    

    That results in a pretty kind of output:

    A pretty version of my errors!

    I like to use the pretty display so I can easily read what, exactly I messed up and how.

  • So Take an Upgrade, Maria!

    So Take an Upgrade, Maria!

    A year ago I asked how do we solve a DB like Maria, and my friend James and I had a good laugh at the long list of issues.

    It’s been a year.

    I’ve upgraded to PHP 7.

    It’s time.

    What about Oracle vs Google?

    Oh you heard about that? Google won a case against Oracle about GPL code in Android which I want to be really happy about, but it illustrates a major flaw in the judicial system. To whit: The player with the deepest pockets wins.

    That case about Java though, not MySQL, which has been a long standing issue with the Open Source Community. The summary? Well it’s kind of like Prohibition. They can try to outlaw it, but we’re going to do our own thing. Which is where MariaDB comes in. It was a fork of MySQL, made in order to stay free and open. I strongly support open source software and so I change to MariaDB.

    What Are The Issues?

    There aren’t as many for MySQL 5.6 vs MariaDB 10.x as I’d thought. In looking at that, I determined it wouldn’t really impact my sites or setup. In fact, I was certain none of it would be an issue.

    How to Upgrade?

    I’m on WHM, so first I made a backup: /usr/local/cpanel/bin/backup --force

    Then I went into WHM and said “Upgrade Maria!”

    I picked the interactive upgrade since I wanted to see what it was doing. Step one went rather quickly and updated everything. It asked me to check my compiled software (which meant two non-WordPress sites that historically act odd when I upgrade). Once that was done, I clicked ‘next’ and was told I didn’t need to do anything else…

    Now what?

    I ran off to GTmetrix and checked my sites. I had two that were PHP 7 and they had no real change. I then changed another one to PHP 7 and Maria and checked it, and got bigger gains. Speed was up and everything, code wise, appeared to work as needed.

    It was entirely a non-event.

  • EasyApache 4

    EasyApache 4

    While we use Ubuntu and Debian things at work, I have a CentOS server that is (as of today) on CentOS 7. Which means not only is it weird and uses yum, but it has cPanel and WHM installed.

    Over the last year or so, cPanel has been working on EasyApache 4 (EA 4). EasyApache is their … easy way to manage Apache and upgrade things. It’s an interface to help make things like your LAMP stack easier to comprehend, and it’s actually pretty nice. EA 3 has been around for a while, and it has serious limitations. Like you have to re-run EasyApache to upgrade PHP (always annoying), and you can’t have multiple versions of PHP. That means when you upgrade PHP to 5.6, everyone is upgraded to 5.6, and damned be the conflicts.

    This … was a problem.

    I have some older code that can use 5.6 but I’ve not been able to fully test it on 7. And I want 7. You don’t even know.

    The actual upgrade process is remarkably painless. I had two errors, one of which was my own doing (don’t try to use opcache if you don’t have opcache installed…) and one was math related. The majority of my settings ported over painlessly.

    AH00316: WARNING: MaxRequestWorkers of 40 is not an integer multiple of ThreadsPerChild of 25, decreasing to nearest multiple 25, for a maximum of 1 servers.

    Obviously the fix there was to change MaxRequestWorkers to 50.

    The interface itself is much nicer. It’s a modern design that is easy to look at with whitespace and tabbing that is natural. The only thing I didn’t like was I couldn’t tell it ‘Install PHP 7 and pick the same options as PHP 5.6 please.’ I ended up copying down what I’d selected for PHP 5.6 and then manually reproducing.

    The provisioning process took a little getting used to, after years of EA 3, but once I had used it a couple times, it felt natural. This can be said of all things. Embrace change, right? It’s also faster, which is very welcome. The longest part is the review process, where it checks for conflicts. This used to happen ‘inline’ with the old deploy, so moving it out just changes the when. I found I preferred it, since I didn’t think “And I’m done!” I knew I couldn’t go forward.

    Initially it installed suphp. I didn’t notice that’s what the default was and found all sorts of errors because of permissions. Errors like this:

    SoftException in Application.cpp:255: File "/home/public_html/index.php" is writeable by group
    SoftException in Application.cpp:613: Directory "/home/public_html/gallery" is writeable by group
    

    I actually knew the fix for this was to run the following in my public_html folder:

    find . -type f -name '*.php' -exec chmod 644 {} \;
    find . -type d -exec chmod 755 {} \;

    And yes, that solved everything. I was logged in as Ms. Groves root anyway, so I bounced through my users and ran it.

    But… did I want to stay on suphp? Turns out EA 4 only supports FastCGI with the FastCGI Process Manager (PHP-FPM), and while I’ve been using that for a while (instead of the dread mod_php). The problem there is that suPHP or CGI PHP handlers don’t support opcache. That meant I either had to suck it up and do the manual install for FastCGI or I could wait for v58 of WHM, which will have a UI.

    I opted to wait and stay on suPHP right now. The domains on my site are pretty fast, thanks to the SSD and a well optimized server. Load time did increase, I won’t lie, but it was pretty negligible. I don’t think it’ll really hurt things at this moment. I did some quick tests on GTmetrix and found my load time for sites on PHP 7 actually decreased.

    And that’s why I wanted PHP 7. It’s just faster.