Half-Elf on Tech

Thoughts From a Professional Lesbian

Author: Ipstenu (Mika Epstein)

  • Obviously Oblivious

    Obviously Oblivious

    So I was asked this…

    @binarygary: .‭@Ipstenu‬ I know you aren’t the patent office…but have you ever declined a plugin for “obviousness”?

    I replied, not in jest, that I had declined some for obliviousness.

    Gary’s plugin was obvious in that it did exactly what it was purported to do, and it did it well. And it had a puny name. I quite liked it and approved it pretty quickly. But the crux of the question is interesting. Have I ever rejected plugins for being too obvious?

    Not that I can remember. In fact, I kind of love the plugins that do exact what they claim to do. Like Rickroll which turns your videos into Rickroll or Logout Roulette which gives you a one in ten chance of being logged out. Those are simple and obvious and a little stupid, but they’re perfectly obvious and only the oblivious would be confused.

    An obvious plugin is possibly the best kind of plugin. My buddy Otto once remarked that well named functions don’t need documentation. If you have a function named reset_the_loop it’s pretty obvious what it does. Now you might need to add some docblox to explain how to use it and what parameters you can pass through to it, but in and of itself, it resets the loop!

    On the flip side, here’s rts_reset which is actually a function I saw recently in a plugin. Okay, what does that do? It was in a class named RTSCode which didn’t help at all. And there was no inline documentation. After a while, I traced everything back and sorted out what the heck the code was doing (it was reseting a query, but only if you passed specific params back).

    In general, a WordPress theme and plugin should be painfully obvious. It’s open source, it’s code anyone can look at, and yes, it should be stupid easy to understand what it does and why. That’s the meaning behind ‘open’ in so many ways. Open for everyone. Open to be forked and learned from and studied and made more perfect. Or at least more fun.

    I like obvious things. Obvious is good.

  • More Chart.js Fun

    More Chart.js Fun

    The statistics page on my TV database site is pretty fun. It’s the one I learned how to use Chart.js for in the first place.

    I wanted to add in some pie charts, but first I upgraded the code to the 2.0-beta and refined the PHP on my stats. Originally I just had some pretty basic bar charts for category statistics. Now I have some pie charts to show characters by role (by which I mean are they a main character, a guest, or a recurring character).

    Better Category Stats

    Let’s talk about some better PHP first. The stuff I had before worked, but it could have been better. Here’s the better PHP:

    $count_characters = wp_count_posts( 'post_type_characters' )->publish + wp_count_posts( 'post_type_characters' )->draft ;
    $tropes = get_terms('chartags');
    
    $trope_terms_array = array();
    foreach ( $tropes as $trope ) {
    	$trope_terms_array[$trope->slug] = array( 'count' => $trope->count, 'name'  => $trope->name, 'url' => get_term_link( $trope ) );
    }
    

    What I did here was take the data and make a single array for it which gives me the data structured as follows:

    Array
    (
        [addict] => Array
            (
                [count] => 2
                [name] => Addict
                [url] => http://example.com/tropes/addict/
            )
    
        [athlete] => Array
            (
                [count] => 3
                [name] => Athlete
                [url] => http://example.com/tropes/athlete/
            )
    )
    

    This makes my array much smaller and simpler to run through. Next I changed how I call the data in my javascript:

    	labels : [<?php
    		$unset = array('foo','bar','baz');
    		foreach ( $unset as $item ) {
    			unset($trope_terms_array[$item]);
    		}
    
    		foreach ( $trope_terms_array as $trope ) {
    			echo '"'.$trope['name'].'", ';
    		}
    	?>],
    

    The unsetting at the top is a quick run to remove the tropes I don’t need for this chart because I’m displaying them in the pie chart. See? It all comes together!

    Pie No. 1 – Sexuality

    There are two pie charts. One is checking how many characters are gay, straight, or bisexual. I’m sure eventually I’ll be add asexual, but that isn’t today. Anyway, that chart is surprisingly simple. Since I’d already improved the PHP call for category stats, and sexuality is saved as a character taxonomy, I was able to do this simply as follows:

    <script>
    // Piechart for sexuality stats
    var pieSexdata = {
        labels: [
            "Gay",
            "Straight",
            "Bisexual"
        ],
        datasets: [
            {
                data: [ <?php echo '
    	            "'.( $count_characters - $trope_terms_array['straight']['count'] - $trope_terms_array['bisexual']['count'] ).'",
    	            "'.$trope_terms_array['straight']['count'].'",
    	            "'.$trope_terms_array['bisexual']['count'].'"
    	            '; ?>],
                backgroundColor: [
                    "#7d3255",
                    "#327A7D",
                    "#32557D"
                ],
                hoverBackgroundColor: [
                    "#B18499",
                    "#BCD4D5",
                    "#ABB9CA"
                ]
            }]
    };
    
    var ctx = document.getElementById("pieSex").getContext("2d");
    var pieSex = new Chart(ctx,{
        type:'doughnut',
        data: pieSexdata,
        options: {}
    });
    </script>
    

    The default assumption is that any character being added is a homosexual. The reason ‘straight’ is there is for a character who was presented as gay, but that turned out to be a fantasy sequence. Thanks, Roseanne. With that in mind, calculating the number of gay characters was a matter of subtracting the straight and bisexual. And yes, I named the chart pieSexdata on purpose.

    Pie No. 2 – Character Role

    The second pie chart was a lot harder. You see, I’d chosen to save the ‘role’ as a custom meta field in the post. There’s a dropdown for ‘Main’ or ‘Recurring’ or ‘Guest’ and it defaults to ‘None’ if you don’t fill it out. Right now everyone has a role but I coded in a failsafe.

    This code took me a while to sort out, but as soon as I realized how simple it was, I made a loop so I didn’t have to repeat code:

    $roles = array( 'regular', 'recurring', 'guest' );
    $roles_array = array();
    foreach ( $roles as $role ) {
    	$args = array(
    		'post_type'       => 'post_type_characters',
    		'posts_per_page'  => -1,
    		'post_status'     => array( 'publish', 'draft' ),
    		'meta_query'      => array(
    			array(
    				'key'     => 'chars_type',
    				'value'   => $role,
    				'compare' => '=',
    			),
    		),
        );
    	$thisrole = new WP_Query($args);
    	$roles_array[$role] = $thisrole->post_count;
    }
    

    This produces a nice array:

    Array
    (
        [regular] => 147
        [recurring] => 37
        [guest] => 23
    )
    

    I wanted it to be an array since I can see this expanding sooner or later. The pie chart code looks very much the same as the one for sexuality, and all that’s really different is how I’m calling the data and doing the math for how many characters have no listed role.

        labels: [
            "Main Character",
            "Recurring Character",
            "Guest Character",
            "No Role"
        ],
        datasets: [
            {
                data: [ <?php echo '
    	            "'.$roles_array['regular'].'",
    	            "'.$roles_array['recurring'].'",
    	            "'.$roles_array['guest'].'",
    	            "'.( $count_characters - $roles_array['guest'] - $roles_array['recurring'] - $roles_array['regular'] ).'",
    	            '; ?>],
    

    What’s Next?

    Things are shaping up nicely, but I want to add in better labels. I’d like if they show the percentage when you hover over them on pie charts, and if they could link to the taxonomy pages for the bar charts. But I haven’t quite sorted out how to do that yet.

    I also have to blame Tracy for this, because she’s the one who wanted stats like that in the first place.

  • Fauxgo and Rickroll

    Fauxgo and Rickroll

    April Fools is today. I hate April Fools ‘jokes’ as pretty much all of them are cruel.

    Now that we have that out of the way, I’d like to tell you about two plugins I created that are pretty much useless but educational.

    Rickroll

    Released in the WordPress.org plugin directory, this plugin changes all your videos to the official Rickroll video. All. Your. Videos. The point it was made for is that you really can run a filter to do some pretty impressive things with videos. Including replace them. You can take the logic of this plugin and apply it by filtering (say) all videos embedded in comments made by a specific person. That would really mess with them. Or you could possibly call YouTube’s api, check the rating of the video, and if it’s over a certain amount, show a default instead.

    Download: WordPress.org – Rickroll

    Fauxgo

    This plugin replaces the WordPress logo with a Fauxgo. Why? Someone complained to me that you couldn’t rebrand WordPress entirely. So I did. The thing about this plugin was that it was deucedly complicated to make work right. Most of the trouble was the CSS is ‘weird.’ But once you have it installed, everything looks different ‘ish’ and suddenly you’re not sure what the logo is anymore.

    I plan to edit this and write it as using an SVG icon instead of the icon font.

    Download: Github – Fauxgo

  • 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.