Half-Elf on Tech

Thoughts From a Professional Lesbian

Author: Ipstenu (Mika Epstein)

  • Why I Pushed Back On Your Plugin

    Why I Pushed Back On Your Plugin

    The talk at WordCamp Ventura was actually called “Top 11 Reasons Your Plugin Was Rejected.” It was supposed to be ten, but Konstantine said “You should make it 11!” and I did but forgot to update the info for him. Bonus reason! You can see all the slides at helf.us/wcventura2014 right now. Video will be up on WordPress.tv soon.

    The truth is, there were only two reasons I actually would ever reject your plugin. If you never replied to our emails about any of the other reasons, we’ve probably rejected you. And if you’re claiming to be someone you’re not in a way we can’t prove, we’ve also rejected you. Let me cover the reasons here, for posterity. My slides are fully accessible, but people learn in different ways.

    And to understand how I made this list, I use aText to auto-reply to things. I just made a note of which ones I used to most, flipped ’em in reserve order, and thus I had a list.

    Trademarks

    This is the funny story one where I rejected Facebook because they used a gmail address and a DropBox URL for their plugin. I looked at it, thought they couldn’t possibly be Facebook, rejected, and got egg on my face. I’d do it again, though, because the point here is that if you’re making a plugin for a company and you’re using the company name, you need to make it clear and easily provable that you are them.

    If you’re doing contract work for, let’s say Pandora, to make an official plugin, you should make a new account on WordPress.org for that. Pandora-Dev or even just Pandora, using a pandora.com email address of course, and then making the plugin downloadable from pandora.com does a lot to make us think you’re real. If you don’t? I may reject you right away.

    Missing readme

    Otto used to let me pend a plugin because there was no readme. The number got so high, he made me stop. Now we only do this if you’re acting as a service or calling files remotely. Akismet and Disqus would require a readme, as would Twitter, but “Hello Dalai” would not. Of course you always should make a readme, but we don’t force you to do so.

    Phoning Home

    Akismet ‘phones home’ to it’s own servers to process your comments as spam or ham. That’s not what I mean here. We don’t permit plugins to phone home to your own server unless they’re acting as a service.

    A plugin that simply validates a license and ‘unlocks’ functionality that’s already in the plugin is not a service. A plugin that sends an email or message to your own servers when the plugin is installed and/or uininstalled is also not a service. A plugin that calls out to maxcdn or Amazon S3 for your JS and CSS files is also not a service.

    When you call out to another server you’re generally doing one of the following:

    1. Intentionally tracking the use of your plugin
    2. Creating an unnedded dependancy on another server being accessible in the interest of ‘controlling’ your css/js/images or keeping your plugin smaller
    3. Trying to control who uses your plugin

    None of those are okay. Think about it as a user. If you’re behind a firewall and can’t access Google (which is not an unrealistic situation), and your plugin requires Google’s version of the html5 shiv script, you just broke your plugin for probably the people who needed it most. Well done.

    Don’t do this. Make everything local to your plugin. It will actually run faster.

    Updates

    Related to phoning home is a plugin who calls back to it’s own servers for updates. Would you be surprised to learn that WordPress.org hosted plugins can already serve updates from WordPress.org? Of course not. You’ve seen that helpful alert on a site before. This is usually a hold over from self-hosting a plugin, or hosting it on Github, but it still needs to be removed.

    One of our guidelines is that you actually use the WordPress.org hosting to, you know, host your plugin. It’s not a directory for spamming, it’s for using to deploy too.

    Encryption

    Using encryption methods like base64() or p,a,c,k,e,r to hide your code or otherwise make it human-unreadable breaks our rule of “No obfuscated code.” It’s fine to compress your code and minify, but it’s not okay to hide it. All code must be human readable for inclusion in this repository.

    This is because we feel the spirit of GPL means that anyone can easily look at your code to reverse engineering what it does and expand on it. Easy being subjective of course, but you get the idea. Hiding your code is useless. It doesn’t help the community at all.

    GPL

    Speaking of… I don’t care your thoughts on GPL. I really don’t. What I care about is this: In order to be hosted on the WordPress.org repository for plugins, every single bit of code in your plugin must be compatible with the GPLv2 (or later) license. This isn’t negotiable, it’s not up for debate. It’s above and beyond what the GPL requires, and we know that. Which is why I just don’t care how you think we’re ‘interpreting the GPL wrong.’ That isn’t my point at all.

    You want to be hosted on WordPress.org? Your code must be 100% compatible with GPL. Deal with it.

    Calling wp-load or wp-blog-header or wp-config

    Including wp-config.php, wp-blog-header.php, wp-load.php, or pretty much any other WordPress core file that you have to call directly via an include is not a good idea and we cannot approve a plugin that does so unless it has a very good reason to load the file(s). It is prone to failure since not all WordPress installs have the exact same file structure.

    Usually plugins will include wp-config.php or wp-load.php in order to gain access to core WordPress functions, but there are much better ways to do this. It’s best if you tie your processing functions (the ones that need but don’t have access to core functions) into an action hook, such as “init” or “admin_init”.

    If you’re trying to use it because you need to access WordPress functions outside of WordPress, we’d actually much rather you didn’t do that at all. Your plugin should be inside WordPress, only accessible to people who are logged in and authorized, if it needs that kind of access. Your plugin’s pages should be called via the dashboard like all the other settings panels, and in that way, they’ll always have access to WordPress functions.

    Security

    Sanitize your post calls, sanitize your SQL queries, use the right code, and be smart. Don’t reinvent the wheel. This is the hardest one to get right and we miss a lot of things, but we want all instances where $_POST data is inserted into the database, or into a file, to be properly sanitized for security. And when you’re making database calls, it’s highly important to protect your code from SQL injection vulnerabilities via prepare() or other functions.

    This is just hard but we do try very hard to catch them all.

    Including your own copy of jQuery

    Please stop this.

    WordPress includes its own version of jQuery and many other similar JS files. If your code ‘requires’ an older version, fix your code to work with the one that comes with WordPress. Having ‘your own version’ means you run the risk of breaking everyone else’s plugins and themes, which makes you a bad person. Stop it. Use the ones with WordPress. It keeps your code smaller and your plugin smaller. Also if everyone uses the built in ones, then the first time one of you enqueues it, the faster everyone else’s code will run. Really. It’s magic.

    Calling wp-content directly

    When you hardcode in paths, or assume that everyone has WordPress in the root of their domain, you cause anyone using ‘Giving WordPress it’s own directory’ (a VERY common setup) to break and you make me cry. In addition, WordPress allows users to change the name of wp-content, so you would break anyone who choses to do so.

    Oh, and don’t worry about supporting WordPress 2.x or lower. We don’t encourage it nor expect you to do so, so save yourself some time and energy. Remember! If we stop supporting WP 3.8 and older, then people have to upgrade to use our plugins! Everyone wins!

    Not answering an email

    If you never reply to an email we sent you about why we pending your plugin, yes you got rejected. In order to keep the queue low and manageable, we reject plugins after seven days from our first reply (not your submission). This can also happen if you’re working with one of us on your plugin code and it takes a long time. This happens when a plugin is complicated, or if there’s a language barrier, or if we just can’t understand why you’re not making the changes we asked for.


    Did I reject your plugin and you still don’t understand why? Have a weird question about plugins? Ask away in the comments!

  • Git The Master Race

    Git The Master Race

    I was working on a project, a side project for fun with a friend, and she expressed a slight worry. We weren’t using any versioning on our theme or mu-plugins code. Or anything else for that matter. There were three of us. We thought about using GitHub until I pointed out I had git on my server, where I was hosting it all.

    In many ways I don’t use git like a ‘normal’ person, or so I’ve been told. I don’t have public git repo of everything because some of it is just private. I don’t even have a public GUI interface for people to file issues on my private code. Public code? Sure, and I use GitHub for it. Personal stuff is not up there, and I don’t care to make it.

    What I do instead is, since I do have Git installed on this server, is allow each user account to make a git repository folder off their home folder. Everyone has ~/repositories/ and in there they can store their code!

    Here are the ones for mine:

    ~/repositories/ipstenu-code.git/
    ~/repositories/ipstenu-mu-plugins.git/
    ~/repositories/mothra.git/
    ~/repositories/scripts.git/
    ~/repositories/slides.git/
    

    The two that start ‘ipstenu’ are for the website ipstenu.org and all it’s children. Mothra is some server scripts I want to keep backed up, scripts are user scripts, and slides are my slides.

    But how do I get there, and how do I keep everything synced up? First is the basic setup for git:

    cd ~/repositories/
    mkdir projectname.git
    cd projectname.git
    git --bare init
    

    From here it’s a simple git clone, too:

    git clone user@example.com:/home/user/repositories/projectname.git
    

    But… I have that project named ipstenu-mu-plugins. When I’ve checked in code, do I manually copy the files over? Of course not.

    When you go into that git folder where I ran the init, you see this:

    [~/repositories/ipstenu-mu-plugins.git]# ls
    ./  ../  branches/  config  description  HEAD  hooks/  index  info/  objects/  refs/
    

    If you go into the hooks folder, you get a list of files:

    ipstenu@ipstenu.org [~/repositories/ipstenu-mu-plugins.git/hooks]# ls
    ./                      commit-msg.sample   pre-applypatch.sample      pre-push.sample
    ../                     post-update         pre-commit.sample          pre-rebase.sample
    applypatch-msg.sample  post-update.sample  prepare-commit-msg.sample  update.sample
    

    You’ll notice I only have one file that isn’t a .sample: post-update

    That’s my secret sauce.

    #!/bin/sh
    export GIT_WORK_TREE=~/public_html/wp-content/mu-plugins
    git checkout -f master
    

    This just uses git checkout, forces the master branch, and dumps the files where I want them. I set it up for each repo when I’m ready to start deploying, and then my dev process is this.

    1. Pull master and all remote branches to make sure I’m up to date
    2. Make a new branch to develop
    3. Push the new branch to origin when I’m sure it’s right
    4. Merge the new branch into master
    5. Push master

    And in that moment, the push will copy my files live.

    Since I don’t ever do dev work in master, this is safe for me. It’s five steps, but I actually have a script to run that first one every single day, so that’s almost step zero. When I work with other people, I always make a backup local branch of master as ‘last known good’ just so I can roll back fast if I’ve been phenomenally stupid. This is usually a date like “GOOD_20141117”, which I know is different from my actual release labels, that are always “REL_1.2.3” style. If it’s a weird thing, like when I was folding Ninja Forms in my site, it was “NINJAFORMS_1.0” because I wanted to be clear what that dev branch was for.

    The Master Race - Doctor Who

    By the way, if you need to set up a shared repository, you should read Kovshenin’s “How To Create a Remote Shared Git Repository”. I don’t, since everyone logs in using SSH keys to the account (so on my shared project, everyone uses ssh projectaccount@projectdomain.com) since they actually need that access anyway.

  • jQuery Toggling

    jQuery Toggling

    I was working on some basic code where I wanted a div to show or hide based on a link. This is simple stuff, but it took me a while to remember it since it’s actually baked into MediaWiki (where I normally use it).

    First up is my HTML code:

    		<h2 class="suggestions-header"><a href="javascript:toggle_visibility('suggestionscontainer');">Suggestions? Click Here!</a></h2>
    		<div style="display:none;" class="sugestions-container" id="suggestionscontainer">
    			<p>I will display when clicked!</p>
    		</div>
    

    Like I said, this is basic stuff. I can get more into it and do things like change the text of the title when you click, but for now this suffices.

    Now for the jquery:

    /**
     * Custom jQuery to toggle visibility
     */
    jQuery( document ).ready(
    
    	function toggle_visibility(id) {
    	       var e = document.getElementById(id);
    	       if(e.style.display == 'block')
    	          e.style.display = 'none';
    	       else
    	          e.style.display = 'block';
    	}
    );
    

    This code got tossed into a toggle.js file and then enqueued with wp_enqueue_script, with a jquery dependancy. Done and done.

    I’m sure this could be done with pure CSS, but I believe in release and iterate.

  • Mailbag: .htaccess Magic with Subdomains and Subfolders

    Mailbag: .htaccess Magic with Subdomains and Subfolders

    From Ginger:

    Hiya, I enjoy your blog and humor within

    In case you still do posts from the “mail bag” — I have seen mention of .htaccess on your site and I’m curious how it relates to the subject of redirects. For example, in my day job we have a site that has two ways to access an external support site.

    So, we want to redirect: www.example.com/support and support.example.com to the same external support site. In the past, I would go to our host and edit the DNS to redirect on these URLS to the external site. Is that the best way or should I be handling this in the .htaccess file now that we’re on WordPress?

    Depends on how lazy I am.

    DNS is great because I can just send support.example.com over, but this only works if the external site lets me do that. I can point my domain at tumblr.com all I want, yet until I add my custom domain to their settings, the URL won’t work. This is why your domain mappings in Multisite don’t always work, folks. You have to tell WordPress, the name servers, and the server that the domain lives there. If you can? Super simple for the subdomain, but not for the subfolder.

    Which brings us to .htaccess:

    Apache 2.2

    RewriteCond %{HTTP_HOST} ^example\.com [NC]
    RewriteRule ^support(.*)$ http://supporturl.com/ [L,R=301]
    
    RewriteCond %{HTTP_HOST} ^support\.example\.com [NC]
    RewriteRule ^(.*) http://supporturl.com/ [L,R=301]
    

    Apache 2.4

    <If "%{HTTP_HOST} == 'example.com' ">
    	RedirectMatch ^support(.*) http://supporturl.com/
    </If>
    
    <If "%{HTTP_HOST} == 'support.example.com'">
    	RedirectMatch (.*) http://supporturl.com/
    </If>
    

    Now someone will note that specifying the HTTP_HOST for example.com is silly, but I disagree. This lets me use http://foo.example.com/support/ to redirect somewhere else. I don’t worry about the www part because I always force no-www on all my domains. Saves me steps later.

    Oh and I’m glad Ginger likes my humor. I don’t know how to turn it off!

  • WIRED Doesn’t Use Multisite

    WIRED Doesn’t Use Multisite

    At WCSF this year, WIRED engineer Kathleen Vignos talked about moving WIRED from 35ish blogs to one blog.

    They didn’t use multisite at any point along the way.

    Now part of this was that back in 2008, when they started, the concept of multisite wasn’t really there. But that left them in a strange world with 35 separate blogs, separate installs, and an psychotic update system that was headachy and roundabout and involved 35 separate sites. But you could understand why they didn’t in the past, since there wasn’t a way to do it back then, but it brings up the question today.

    Why not multisite now?

    That was my question after her talk, and I promise you angels sang from the heavens when she said that multisite was intended for siloing data, and she needed to share data between ‘subjects.’ So for them, to have categories and just post articles in the appropriate ones (yes, plural) was exactly what they needed.

    I have been saying this for a few years now. Multisite is great, except when it’s not, and there are reasons to use it and reasons to not. WIRED properly looked at their sites and said “We need to share data, Multisite may not be the best.” They also said “We need to make it easier to add users to a site, so maybe not Multisite.” Every single reason they picked to not use Multisite was 100% exactly the right one.

    Multisite is simply not what you want if you need to share data between sites and you’re on a big site. Had WIRED used Multisite, they would have been miserable and have to write not just plugins to migrate the data, but ones to join the tables and display data in an ongoing way. What a pain.

    Kathleen talked about the hurdles of merging the sites, and the tools they invented in order to make their Pangea happen. They had to worry about logical things, like keeping User A out of a category, and made use of plugins like Restrict Categories to do just that. Custom fields in the author profiles were use to assign a ‘default beat,’ and they made extra roles to allow people to manage the sites. They used template files to make various categories look different, which is often the main pain point.

    By doing this, they were allowed to share and segregate data in an efficient and effective way.

    WIRED wins my hat-tip for the best talk at WCSF about Multisite, simply by not using it.

    You can see the slides here:

    And the video here:

    [wpvideo n4wrIVIU]

  • Karuta

    Karuta

    The idea of WordPress Karuta is based on the Karuta (カルタ) game in Japan. Karuta means, essentially, card game and yet is a very popular game to play competitively. The cards are written with the Ogura Hyakunin Isshu, which are 100 famous poems, and the game is played very simply. The poem is read and the first person to find the card of the poem and tap it gets the card. In the end, the most cards wins. It’s also really wild to watch.

    http://www.youtube.com/watch?v=nKAmZxVhQww

    At WordCamp Tokyo they introduced me to WordPress Karuta.

    WordPress Karuta Cards

    The game is simple. The black cards are to be asked aloud and you grab the pink card with the answer.

    I now have all the data from the 2013 and 2014 cards and the plan is to make a GlotPress site where we enter all the Japanese original data and translate it so anyone, anywhere, can make the cards to play and teach. Yes, teach.

    If you’re an American, think of it like Jeopardy the card game and pretend you Alex Trebeck is saying this: “Display the URL of the individual pages, such as posts or fixed page.”

    And you go, “Oh! the_permalink!!”

    But instead you grab a card.

    This would let people learn in a fun way, as it forces you to think about the meaning behind the code. It’s easily extendable past just code, you can ask questions about plugins. For example, an answer might be ‘WordPress SEO’ to a question of ‘A plugin that allows you to connect to Google Analytics, Google Webmaster, Yahoo sites, and also edit your robots.txt file.’

    I’m going to work with Markus and Shin to translate this so everyone can try their hand at WordPress Karuta!