Half-Elf on Tech

Thoughts From a Professional Lesbian

Author: Ipstenu (Mika Epstein)

  • Migrating from CMB to CMB2

    Migrating from CMB to CMB2

    I didn’t plan to, the first time. I’d inherited a site that I offered to help someone clean up and they had CMB2. They didn’t actually. They had CMB, the original. This was a while ago. Looking at their site, I realized they had one (yes, one) custom meta box, so I removed CMB and coded in that one meta box and called it a day.

    Flash forward a while. A long while. I have a site that was mostly built out by someone else, and it worked great except on mobile. After trying to update content on the site on my iPad and getting frustrated to the point of angor, I re-did the theme as Metro Pro (yes, it’s that site), and folded in a lot of the meta boxes into mu-plugins, so we could keep them no matter what the theme.

    But again, she’d used CMB. Not CMB2. And since I know CMB2 has a lot more features, I decided to upgrade. Three hours later, I had it done and had it done rather nicely.

    Decide how to install CMB2

    I did it as an mu-plugin – Look. It’s a library. I have my font library (aaah!) in there as well. This is how I organize things. I don’t want people disabling it on accident, so by having it in my Must Use folder, only people with SSH or Git access can screw with it. This is a protection thing.

    I tossed the cmb2 folder in there and whipped up a fast cmb2.php bootstrap file:

    if ( file_exists( dirname( __FILE__ ) . '/cmb2/init.php' ) ) {
    	require_once dirname( __FILE__ ) . '/cmb2/init.php';
    } elseif ( file_exists( dirname( __FILE__ ) . '/CMB2/init.php' ) ) {
    	require_once dirname( __FILE__ ) . '/CMB2/init.php';
    }
    
    // Extra Get post options.
    function cmb2_get_post_options( $query_args ) {
        $args = wp_parse_args( $query_args, array(
            'post_type'   => 'post',
            'numberposts' => -1,
        ) );
        $posts = get_posts( $args );
        $post_options = array();
        if ( $posts ) {
            foreach ( $posts as $post ) {
              $post_options[ $post->ID ] = $post->post_title;
            }
        }
        asort($post_options);
        return $post_options;
    }
    
    // Handle the CSS for this
    function cmb2_site_scripts( $hook ) {
    	if ( $hook == 'post.php' || $hook == 'post-new.php' || $hook == 'page-new.php' || $hook == 'page.php' ) {
    		wp_register_style( 'cmb-styles', plugins_url('/cmb2.css', __FILE__ ) );
    		wp_enqueue_style( 'cmb-styles' );
    	}
    }
    add_action( 'admin_enqueue_scripts', 'cmb2_site_scripts', 10 );
    

    You’ll notice that’s more than just bootstrapping. This is the other reason I wanted it as an MU plugin. The first part with the require_once is the call for CMB2. I could simplify it since the folder is lowercase, but it’s fine as is. The second part with function cmb2_get_post_options is so that I can use the names of all my posts as options in a dropdown. I didn’t invent this code, it’s from the CMB2 documentation. The last bit of function cmb2_site_scripts is just to make sure my custom CSS gets loaded on the right pages (I wanted to change the layout of some things).

    Convert the Calls

    This was the weird part. I’d never really used CMB before. CMB2, through various things including reviews, I’m pretty familiar with the general aspects of it, though not all the specific calls. From CMB to CMB2, the major change was that instead of multiple nested arrays with a return, the code was wrapped in a function that had an array, but then it had callbacks.

    This:

    	$meta_boxes[] = array(
    		'id'         => 'chars_metabox',
    		'title'      => 'Character Details',
    		'pages'      => array( 'post_type_characters', ), // Post type
    		'context'    => 'normal',
    		'priority'   => 'high',
    		'show_names' => true, // Character field names on the left
    		'fields'     => array( ... )
    	);
    
    	return $meta_boxes;
    

    became this:

    	$cmb_characters = new_cmb2_box( array(
    		'id'            => 'chars_metabox',
    		'title'         => 'Character Details',
    		'object_types'  => array( 'post_type_characters', ), // Post type
    		'context'       => 'normal',
    		'priority'      => 'high',
    		'show_names   ' => true, // Show field names on the left
    	) );
    

    You can totally see how one transmuted into the other, right?

    The biggest change is the 'fields' => array( ... ) section, which is totally missing from the new version. Remaking the fields was trickier since some changed a great deal. And some changed in fantastic ways.

    Here’s the original actor name field:

    			array(
    				'name' => 'Actor Name',
    				'id'   => $prefix . 'actor',
    				'type' => 'text',
    			),
    

    And here is the new one:

    	$cmb_characters->add_field( array(
    		'name'       => 'Actor Name',
    		'desc'       => 'Include years (in parens) for multiple actors',
    		'id'         => $prefix . 'actor',
    		'type'       => 'text',
    		'repeatable' => 'true',
    	) );
    

    I’ve added in two things. First is the desc (description), which was needed because I was adding in the repeatable field! Sometimes actors are replaced, and with that in mind we’d been using ‘Foo (2013), Bar (2014-2015)’ and so on. But now with repeatable fields we could easily add in a new line for every actor. Problem solved!

    Why not hand code?

    Because the Fields API is a sack of wet, smelly, rotting, hair. It’s actually worse than the Settings API. I can’t wait for the Fields API plugin to hit release candidate and have a UI built in. Until then, hand coding more than one meta box is a headache. Making three groups with three to eight fields in each with cross dependencies? A nightmare.

    Simply put, CMB2 does it well, obviously, and simply. The code is easy to understand and implement. I wish it was in core. It’s around 3 megs, but 2 of them are from translations, so it’s really not as horrible as all that.

  • Dependency Disaster

    Dependency Disaster

    Over the last few weeks and months, the nightmare that is WordPress plugin dependency hell has waxed and waned with the ire of a thousand burning suns. It flared up when I, perhaps naively, posted a reminder of a rarely called upon guideline to not submit Frameworks for hosting on WordPress’s official plugin repository.

    This brought up the perfectly valid arguments that these repositories are useful as they allow for deployment and updates that were hitherto unavailable when rolled up into one package. And at its heart, I understand their point and agree with them as to the benefits. But since WordPress core doesn’t have true plugin dependencies at this time, it’s exceptionally complicated and a hassle to include them.

    Personally, I feel that the NPM or Composer style development of plugin is the way to go. Development. Not deployment. With few exceptions, I feel the best way to release a plugin is all in one, rolled up together. The exceptions are, of course, plugins that are add-ons to others, like a plugin that adds a new email integration hook to MailChimp, or a new payment gateway for WooCommerce.

    The rest of our plugins should be self contained, reliant on naught but ourselves. I have two plugins which contain the same AWS SDK libraries, written in a way to check if the library is already loaded and to make sure it only loads what’s needed. Why did I do that? Because then someone can have one or the other or both without conflicts.

    The user doesn’t have to care about dependancies. They are invisible. That is as it should be. Users don’t have to care.

    But there’s also a danger with dependancies, as recently came to light in the JS world. Azer Koçulu liberated his modules from NPM after the threat of a trademark based lawsuit had NPM remove one of his projects.

    Sidebar: Open Source has no right to impinge on trademark law. Period. However some lawsuits are frivolous and daft and should be contested. Sadly most communities (NPM, WordPress.org, etc) do not have the money or resources to fight that battle for a developer. If you chose to fight, please contact the EFF.

    As is his right, Azer pulled all his packages from NPM. The fall out from this package removal is that a lot of automated builds failed. This has to do with the way Composer is often bundled. Instead of a wrapped up package like an exe or a dmg, it’s a stub that reaches out and downloads all its requirements on the fly. Just like the TGM Plugin Installer. Right? And what happens when those requirements are missing? The build fails.

    Perhaps worse, by unpublishing the name slugs used can be taken over by anyone else, and used to push more nefarious code. This did not happen. NPM checked everyone and verified they were as decent as one can before handing over the old names to new owners.

    My first thought was “Could this happen to WordPress?”

    Yes and no. First up, we don’t reuse names. If you have the plugin ‘foobar’ and ask to have it closed, the name is still reserved. In extremely rare cases we’ve turned over names to trademarked owners (like how Facebook owns the facebook slug) but always with communication of both parties and always with awareness to how many users might be impacted.

    But could we pull a plugin for trademark infringement and screw up package dependancies? You bet your ass.

    We’ve been lucky that all legal parties involved in similar arguments have been accepting of the ‘grandfathered’ ruling. That’s why we still have plugins with slugs like ‘google-analytics-by-joe’ out there. But it’s also why we don’t allow any more. And yes, when a plugin with a unique name is submitted, we do take the time to check if it’s already trademarked. To spare people this drama.

    But yes. It could totally happen. And since we have to name our dependancies and rely on those slugs, there’s no easy way out.

    I suggest reading the Hacker News thread on the matter. They weigh both sides of the issue, and show you how the pros and cons make this even more complex.

  • The Pressure to Succeed as a Woman Who Codes

    The Pressure to Succeed as a Woman Who Codes

    I feel a disproportionate amount of pressure to succeed in coding.

    I call it disproportionate because it’s only about 1/3rd of my career. The other two are support/training and public speaking. And while I used to have a fear of public speaking, I’ve somehow managed to discard that and I’ve got no concerns at all about screwing up on stage. I might. My talk might flop. My training might not be understood or adopted. My support may be wrong.

    But what scares me to the point of tears is coding.

    It’s not that I’m bad at it. Intellectually I think that I’m pretty good. I’m not the greatest in the universe, but that’s a realistic stance as opposed to anything else. And I enjoy playing with it, inventing new things, seeing how they work, helping people solve problems with code. It’s honestly fun.

    Looking at the Stack Overflow Developer Survey I noticed that only 5.8% of the participants identified as female. Taken a different way, 92.8% of people had no problem saying they were men. Now, SO is aware of the disparity, and mentioned this:

    Our survey results demonstrate a dramatic disparity in tech among men and women. In fact, we know women make up a more significant proportion of the developer workforce than this suggests. According to Quantcast, about 12% of Stack Overflow’s readers are women. (We don’t actively track gender internally.)

    I have a personal theory that gamification appeals more to men than women. This stems from reading about Richard Bartle’s player types way back in the 90s. It was a big thing in MUDs and MUSHes, and the Bartle Test is essentially a series of questions that can be used to identify the classification of a player into one of four types: Killers, Achievers, Socializers, or Explorers.

    Now it helps if you’ve read a little of Hearts, Clubs, Diamonds, Spades: Players who Suit MUDs, but you can get by with the Wikipedia article. The main point is that we can classify people into player ‘types’ based on what they enjoy doing and how they like doing it.

    In general, winning and hacking are associated with Killers and Achievers, while helping and curating fall under Socializers and Explorers. And when I say it like that and you look at things like programming vs support forums (of which I do consider Stake Overflow), lines start to be drawn. These lines are carved in stone when you consider some of the research gamerDNA did into what kinds of player played what kinds of World of Warcraft characters, and what their genders were.

    What does all this have to do with the unrealistic expectations on women who code?

    If one buys in to the hype and typecasting, then one would say that women (nurturers) are more likely to be socializers and explores. Regardless of if this is accurate, there certainly is an expectation on women that they are ‘mothers’ and, from that, they are often unconsciously perceived of being a specific player type. And when someone steps out of what people feel their norm is, they’re often set upon.

    This is not solely endemic to women, of course. Men who express emotions publicly, like crying for example, are also set upon by others for not being manly enough. And that is precisely my point. People who don’t fit the stereotypes of what gender is get pushed back. People who act ‘out of character’ are looked upon as odd.

    Okay, so why do women keep feeling pressured? Because shit like this happens:

    You can look up the ‘fake geek girl’ phenomenon on your own. The fact is that it applies to anything not stereotypically female that a woman does. And it means that, in order to be taken seriously as a coder, we have to achieve great things or all we’ve done is prove we’re only good for the ‘fluff’ of support.

    Eddie Izzard makes a joke in his “Dress to Kill” routine about men who wear dresses and heels:

    You know, if a woman falls over wearing heels, that’s embarrassing, but if a bloke falls over wearing heels, then you have to kill yourself. It’s the end of your life. Its quite difficult.

    And while we laugh at it, the truth is that ‘abnormal’ behavior is treated with incredibly high expectations. Unrealistic ones. Unfair ones.

    I don’t have an answer to this, and for now women shoulder the burden of being expected to be greater than men of identical backgrounds, simply because of how we were born.

  • Chart.js Category Statistics

    Chart.js Category Statistics

    One of the sites I work on is using the Metro Theme by StudioPress Themes for WordPress. And on that site, I have a page dedicated to some odd stats based on the categories and tags and custom taxonomies.

    What I have is a post type ‘shows’ and a custom taxonomy called ‘clichés’ and from that I was easily able to generate a percentage of how many shows use the cliché of queers in law enforcement (38%) or how many have the death of a queer (also 38% right now). But that wasn’t enough. We wanted ‘pretty graphs’ and for that I needed a tool like Chart.js and a little PHP magic.

    How to Chart.js?

    Chart.js is a super cool and super responsive and super flexible way to include a chart. And using it is incredibly easy once I figured out that I could just use inline script tags. A very basic chart that would show you how many days each month has looks like this:

    <script src="Chart.js"></script>
    <canvas id="barDays" width="600" height="400"></canvas>
    
    <script>
    var barDaysData = {
    	labels : ["January", "February", "March", "April", "May", "June", "July", "August", "September", "November", "December"],
    	datasets : [
    		{
    			fillColor : "#7d3255",
    			strokeColor : "#532138",
    			data : ["31","28","31","30","31","30","31","31","30","31","31"]
    		}
    	]
    }
    
    var barDays = document.getElementById("barDays").getContext("2d");
    new Chart(barDays).Bar(barDaysData);
    </script>
    

    If you’re using WordPress, you’ll want to use wp_enqueue_script to call it. Here’s what I did for my theme:

    wp_enqueue_script( 'chart.js', get_bloginfo('stylesheet_directory').'/inc/js/Chart.min.js' , array( 'jquery' ), CHILD_THEME_VERSION );

    But that’s the basics of it. Once I understood that, I was good to go.

    The Code

    Before I can do anything, I need to make sure I have the data I needed. What I wanted was a list of all the shows that were published and a list of all the cliches, ordered in the way I need them. The order is simply comma separated values, enclosed in quotes, enclosed in brackets:

    labels : ["January", "February", "March", "April", "May", "June", "July", "August", "September", "November", "December"],
    

    And the data is similar:

    data : ["31","28","31","30","31","30","31","31","30","31","31"]
    

    Since I’m lazy, I checked that the array worked if it ended in a , and it did! That means my PHP looks like this:

    $count_shows = wp_count_posts( 'post_type_shows' )->publish;
    $cliches = get_terms('cliches');
    
    $barshow_labels = '';
    foreach ( $cliches as $cliche ) {
    		$barshow_labels .= '"'.$cliche->name.'",';
    }
    
    $barshow_data = '';
    foreach ( $cliches as $cliche ) {
    		$barshow_data .= $cliche->count.',';
    }
    

    And my js looks like this:

    <script>
    var barShowsData = {
    	labels : [<?php echo $barshow_labels; ?>],
    	datasets : [
    		{
    			fillColor : "#7d3255",
    			strokeColor : "#532138",
    			data : [<?php echo $barshow_data; ?>]
    		}
    	]
    }
    
    var barShows = document.getElementById("barShows").getContext("2d");
    new Chart(barShows).Bar(barShowsData);
    </script>
    

    You may notice the simple call of <?php echo $barshow_data; ?> in there? That’s where it outputs the data I sorted out in the PHP section. Done. I’m could put it more inline, but I liked to separate them as much as I could.

    Putting it in the theme

    This is a Genesis theme so while I am making use of the Genesis loop, the call to get_template_part can be used by anyone. I’ll explain in a moment. First, here’s the page template:

    <?php
    /**
    * Template Name: Lezbian Stats Template
    * Description: Used as a page template to show page contents, followed by a loop
    * to show the stats of lezbians and what not.
    */
    
    // Show Dead count below the content:
    add_action( 'genesis_entry_footer', 'lez_stats_footer', 9 );
    
    function lez_stats_footer() {
    	get_template_part( 'stats' );
    }
    
    genesis();
    

    This works like any other page template. You make a page, you select the template, and it loads this custom design.

    The magic sauce is in get_template_part( 'stats' ); which calls the file stats.php and that file has all the code you saw above. This means I can edit my post with all the explanations I want, and then it always outputs the stats on the bottom. By calling the Genesis code in the bottom, I retain all of it’s magic while pulling in what I want.

    The Result

    The graph of cliches about queer women on TV

    Looks nice, doesn’t it? I’m quite fond of it.

  • Project Bloat

    Project Bloat

    Can we have a serious talk about project bloat?

    During the framework kerfluffle, I remarked that I hated seeing a 10 line plugin needlessly include a framework like CMB2 because of the size of plugin it created. Someone remarked that if the library helped them write something in ten lines instead of 100, wasn’t that better?

    And the answer to this is maybe.

    My issue is not using a library when the library is the best solution. My issue is people defaulting to use a library before they think about if it is the best solution.

    And my point is really quite simple and obvious to a large number of developers. I’ve touched on it time and again. I’ve told you how I handle packaging my vendor folders. Simply put, I think that before you include anything in your project, you should evaluate it’s merits and flaws.

    Look. There are always, and will always be, good reasons to use a library. There’s never a reason to use a library thoughtlessly, and that’s what I see every day. By ‘thoughtlessly’ I meant someone who has a plugin that adds one setting, a custom meta field let’s say, into all posts. And in order to do that, they wrap ACF into their plugin.

    For one field.

    One.

    Literally one.

    Jackie Chan WTF Meme Face

    And I get it, I really do. The settings API is a bag of wet hair, and the fields API needs love (so much props to Scott Clark for his work there), and figuring out how to do things can be a comprehensive battle of trial and error vs ‘How much hair do I have left?’ And yes, I do use some of those libraries, like CMB2 and ACF, when the need calls for it. When I’m making a massive custom tool or theme and I need to do a million things. But …

    What I don’t do is use it for one field. Sure I could, but that would make my plugin very large and to no real benefit except it’s ‘easier’ for me. And even that is questionable. When I do use them, and yes I do, I do so thinking about the weight I add to my project.

    A pause here. I say this a lot, the weight of a project.

    Everyone seem to assume I only mean the size (in MB) of a project. I don’t. When I say the ‘weight’ of a project I mean the file sizes, of course. Making your 10kb plugin over 500kb just to add one field (I’m being literal here, folks) is sketchy at best. Making it over a meg is borderline ignorant. But I also mean the weight of how it impacts the speed of the site. Will having the library called make a site slower? It might. And I also mean the weight of technical debt. Am I going to update the plugin and the library every single time? This is my responsibility now, and I have to test and test and ensure I don’t break anything.

    The weight isn’t just the size, it’s the time sink. It’s everything that has to go into keeping a library included in a way that doesn’t conflict with anything else. It’s managing my time so I can test and evaluate changes. It’s making sure I push code that won’t break on new versions of my main project (i.e. WordPress). It’s making sure my changes don’t break other co-projects (like WordPress plugins and themes), by assuming they’ll always work on the newer versions. Backwards compatibility isn’t a requirement for all projects, but when it is, you bear that weight too.

    And the weight is also the fact that I’m robbing myself of a greater understanding of WordPress core. Using a library isn’t ‘cheating’ but it does mean I might be less capable of debugging a conflict, if it’s due to the library.

    That’s the real weight of a library included in your project. If you’re not considering it when you add a library, you’re doing yourself a massive disservice.

  • Composer and WordPress’ Plugin Preflight Check

    Composer and WordPress’ Plugin Preflight Check

    When you upload a plugin to WordPress.org’s repository, it does some pre-flight checks to make sure the code is okay. More than once it’s caught a missing ; for me. But one day it caught this:

    PHP error in: myplugin/tags/0.6/aws/Doctrine/Common/Proxy/ProxyGenerator.php:
    Errors parsing myplugin/tags/0.6/aws/Doctrine/Common/Proxy/ProxyGenerator.php
    

    I stared for a moment, Googled to be sure, and sighed when I figured out that what was happening was my library was a PHP 5.6+ version and that didn’t pass the 5.4 checks.

    Regardless of how annoying this is, it’s not too hard to fix. No, I’m not going to tell you how to avoid the scan, nor am I going to talk about the stupidity of the scan. Instead I’d like to tell you how to get around this problem.

    It’s so easy, too.

    You see, my issue is that I use Composer to build my resource libraries and in my composer.json file, I have this:

    "require": {
    	"aws/aws-sdk-php": "2.7.*",
    	"doctrine/orm": "*",
    	"monolog/monolog": "*"
    },
    

    And for what it’s worth, this is great. I have it download all my libraries. Then I have it run a script to copy over just what I need to my aws folder and I have Git and SVN ignore the vendor folder. Everyone wins! The problem is that Composer sees that my laptop is running PHP 5.6 and so it installed version

    Fix PHP on Your Computer

    Since I use Homebrew on my Mac, this is super easy for me.

    $ brew unlink php56
    $ brew install php54
    

    Then when I re-run composer update it will install what I need.

    The problem here, though, is that this is tied to a specific computer, and if a coworker downloads my stuff and plans to fork it, they’re SOL and merges fail and it’s sad times all around. So with that in mind, uninstall 5.4 and go back to 5.6.

    If you have a problem with installing 5.6, run it this way:

    $ xcode-select --install
    $ brew unlink php54
    $ brew install php56
    

    Fix PHP in Composer

    I like this fix better. Put this above your require statement and you’ll force Composer to build based on PHP 5.4:

    "config": {
    		"platform": {
    		"php": "5.4"
    	 }
    },
    

    Now we’re cooking with fire. This works for everyone, it forces Composer to download 5.4 compatible libraries, and my very long transmission worked.

    Is This Perfect?

    Obviously not. There are going to be cases where your code absolutely has to be the code for PHP 5.5 and up. The latest version of the AWS SDK is v3, for example. But it’s for 5.5 only. I personally don’t feel there’s enough of a buy-in for PHP 5.5 and up yet to make an issue of it. And having no check at all won’t fly.