Half-Elf on Tech

Thoughts From a Professional Lesbian

Author: Ipstenu (Mika Epstein)

  • Yes, You Can Use Enqueues

    Yes, You Can Use Enqueues

    One of the battles I face with plugins is explaining to people that they really do need to use wp_enqueue_scripts() for their code. And often I get an argument back that they can’t because they need to include parameters.

    Hold on to your hats. You totally can.

    The Misconception

    It’s easy to get confused with code. There are so many different ways to solve the same problem, we get twisted around. Let’s say that you wanted to include the following script in your website:

    <script src="https://mycoolsite.com/widget.js" async></script>
    

    That’s pretty straightforward in WordPress:

    wp_enqueue_script( 'my-widget', 'https://mycoolsite.com/widget.js', array( 'jquery' ), 1.0.0 );<
    

    But. What if you wanted to add this as well:

    <script type="text/javascript">
        var _widget_options = {
            theme: 'slow' // Choose from 'fast', 'stop', and 'slow'. Remove this property to get the default theme.
    };
    </script>
    

    Now you clearly have to hand-code this into WordPress. Right?

    Wrong!

    Use Inline Scripts!

    You may have heard about wp_add_inline_script before. If not, don’t feel bad. What this does is add extra, inline, code to an already enqueued script.

    Which means that to add the extra code, you do this:

    wp_add_inline_script( 'my-widget', 'var _widget_options = { theme: "slow" }', 'before' );
    

    Which will echo out exactly what you need.

    The cool thing about this, is what if you want your plugin to have a lot of options? Like you want to use the value for an option to determine what your script should do?

    $my-widget-inline = 'var _widget_options = { theme: "' . get_option( 'my-widget-theme' ) . '" }';
    wp_add_inline_script( 'my-widget', $my-widget-inline, 'before' );
    

    And now you’ve got flexibility.

    Keep In Mind…

    First, the name of the script matters. If you enqueue it as ‘my-widget’ then you call it as ‘my-widget’ as the first parameter in your inline script.

    Second, you can change ‘before’ to ‘after’ if you need it to be after the script.

    Third, as with all things, make sure you only load your javascript when you must. No one likes a slow site because you’re loading your javascript on every page when it only needs to be on a specific custom post type.

  • Git Attributes: Control Your Vendor Folders

    Git Attributes: Control Your Vendor Folders

    When you’re developing code, a lot of the time you have vendor or bower_component folders that you don’t need. That is, you don’t need them for the code, but you do for the development.

    A year ago I explained how I handle my vendor folders. Essentially, I use SVN to ignore things so they don’t get uploaded to WordPress. And that’s great but

    What about Git?

    Enter Git Attributes

    The .gitattributes file lets you define attributes for paths. What that means is you can assign an attribute to a file which will then impact how various Git operations occur.

    Operations are things like checking your code out or pushing a release (something familiar to Githubbers). Basically an operation is when Git does a ‘thing.’ Whatever that thing will be. And the Attributes file allows you to specify what happens to specific files (or folders) when that thing happens.

    How Do You Use It?

    There’s a lot more to it than this, but if your goal is to exclude vendor folders and .git files from your zips to send them off to people, then you’ll want to have your .gitattributes file look like this:

    /vendor/ export-ignore
    .gitattributes export-ignore  
    .gitignore export-ignore
    

    This results in when you use GitHub and tell someone to download the zip from it, it will exclude those files.

    What Else Can I Do With It?

    Have a problem with line endings because one person on your dev team uses Windows? gitattributes can help.

    Need to make a change like that for everyone on a system? Or maybe you want to make sure you never include those vendor and documentation folders? The Pro Git Book says this:

    Attributes for all users on a system should be placed in the $(prefix)/etc/gitattributes file.

    Before you ask, unless you changed it, $(prefix) is nothing for pretty much everyone. You may have a /usr/local/git/etc/ location though.

  • The Unbearable Uniqueness of Functions

    The Unbearable Uniqueness of Functions

    PHP 7.2 is on the horizon and one of the battles that we’re still facing is how to name our functions and classes. In WordPress, this is especially hard because we have to consider how our plugins and themes will be used in the global landscape.

    Everything Must Be Unique

    If you’ve written a self-contained PHP app, you know that you can’t give two functions the same name. So you have function enqueue_scripts and function enqueue_styles and function embed_content but you can’t declare them twice. Names must be unique within an app.

    When you consider the fact that all plugins and themes are third-party add-ons to WordPress, the naming situation gets messier. You can’t, for example, use function get_the_excerpt() because WordPress is using it. So you have to introduce prefixes to your plugin (let’s call it “Caffeinated”) like this: function caff_get_the_excerpt()

    That works well until someone creates an add-on to your plugin, call it “Decaffeinated”, and they need to use function decaff_get_the_excerpt() which isn’t so bad, but “Tea Caffeinated” has to either use a prefix of tea_caff_ or caff_tea_ and the more you travel down the road, the messier it gets.

    Prevent Collisions

    The whole point of this exercise in naming is, you see, to prevent collisions between your code and the parent projects you’re working with. You can’t use __ as a function prefix, for example, because that’s magical in PHP land. You can’t use wp_ or wordpress_ in WordPress, because … well. You’re not WordPress.

    But preventing collisions gets long and messy and convoluted and you end up with prefixes like edd_stbe_ which is unique but can be difficult to remember what it’s for. That’s why, thankfully, we have the option of a little more selective naming.

    Selective Uniqueness

    Back in PHP 5, the object model was rewritten to allow for better performance and more features. And this allows us to make Classes which contain our functions, named whatever we want:

    class Caffeinated {
        function get_the_excerpt() { ... }
    }
    new Caffeinated();
    

    This is extended to the add-on plugins, So we could have class Decaffeinated and class Caffeinated_Tea but within the classes, our functions are more simply named. Also we can call functions from one class into another, like Tea could call Caffeinated::get_the_excerpt() and easily filter that function.

    Why is this good? Well it lets you keep the function names simple, but the class name distinctive and thus easier to remember.

    Simple Names are Better

    One of the cardinal rules about domain names is that shorter is better. The same goes for functions and classes, to a degree. As Otto likes to say, a well named function doesn’t really need documentation. And one of the ways you can get a well named function is by putting it in a well named class. You can also use Namespaces.

    Namespaces are magical. By adding namespace Caffeinated; to your plugin file, for example, you can then have a classname of class Settings and not have to worry about collisions, because your class name is prefixed automatically by the namespace. This extends to functions, as you can us function admin for admin settings in the Settings class, in the Caffeinated namespace. And to call that? Use Caffeinated\Settings::admin();

    There’s a lot more you can do with Namespaces, of course, but using them to stop your code from crashing into other people’s, while still keeping names obvious, unique, and memorable? Well they’re pretty nifty.

    Remember: What’s Your Global?

    At the end of the day, the big thing to remember is what your globals are.

    • Outside of a class or namespace, a function is a global.
    • Outside of a namespace, a class is a global.
    • Outside of a namespace, a namespace is global.

    Yes, you can have sub-namespaces. But the point is that top-level whatever you pick, be it a function, class, or namespace, must be named uniquely and distinctly and, in my opinion, relative to the code it’s in. Naming things generically ends in tears as they’ll probably conflict.

  • Fight The Future

    Fight The Future

    Life in the Slow Lane

    Imagine a world where you couldn’t read these posts because your ISP didn’t like one I made about how to download video from your DVR?

    Imagine an internet where a site like LezWatch TV was blocked because someone was homophobic?

    That’s what could happen.

    Americans, please contact your representatives now. Non Americans? Social media please and thank you.

    Still not sure about this?

  • FacetWP, JSON API, and WP_Query Searches

    FacetWP, JSON API, and WP_Query Searches

    One of the ways that FacetWP works is that it adds <!--fwp-loop--> to the source of your outputted page when it detects you used a search query and it can’t find it’s usual classes. This is so that it’s various features like refreshes and so on. It’s a good thing.

    At least it is until you’re trying to use a WP_Query based search to find titles “like” something, and you find your JSON output prefixed…

    Mostly Harmless

    Most of the time when you see <!--fwp-loop--> in the source code, you don’t care. It doesn’t impact anything and it helps Facet work. This is especially important when you have a ‘weird’ theme or plugins that mess with output.

    The issue is that this is how Facet decides if you need that output:

    $is_main_query = ( $query->is_archive || $query->is_search || ( $query->is_main_query() && ! $query->is_singular ) );
    

    Most of the time, that makes perfect sense. It just happens that I’m calling search in a place where that output is a bad idea. Like this:

    {“id”:6294,”name”:”Alex”,”shows”:”Witches of East End”,”url”:”https:\/\/tv.lezpress.dev\/character\/alex\/”,”died”:”alive”}

    Whoops.

    Annoying, But Not Impossible, To Fix

    After bashing my head in for a while, I grep’d the code for Facet, found where it was being set, and then read the help document on facetwp_is_main_query which told me that I could filter the function.

    In this case, I needed to set the value to false to get it to stop outputting, so I used this:

    add_filter( 'facetwp_is_main_query', function( $is_main_query, $query ) { return false; }, 10, 2 );
    

    Be careful where you put that by the way. If you put it on all pages, you’ll break your Facets. I put it in the function that generates the JSON output which limits it heavily, just as I want it to.

  • Review: Do The Twist

    Review: Do The Twist

    When I got ready to go to WordCamp Europe this year, I realized I needed a new adapter. I had one, and it worked, but it also was highly imperfect as it required me to charge everything through my laptop. You know that drill, right?

    Like a lot of road warriors, I travel with about four USB plugs and it’s a mess. It’s always looking for good plugs in a hotel room, and hoping I can charge everything. I used to have a cheap USB hub, but it shorted out. Cheap. I knew what I needed, and it was a charging ‘station.’ But I wanted one that would work ‘universally.’

    The Drama Of Plugs

    I don’t actually remember how I found this. It may have actually been an ad that popped up when I was searching for chargers. I’d been thinking about getting a multi-outlet travel power strip with a couple USB ports. My constant worry with those is the 3-prong US outlet isn’t actually universal here. I’ve been in a lot of nice hotels that don’t have them. Worse, converting from 3-prong to European outlets has, in summer at least, caused a power short.

    Seriously, I blew out the power on my floor in Spain once. Sorry.

    OneAdaptr to Bind Them

    And then I ran into OneAdaptr. At first I was skeptical of the idea. While I had a universal adapter, the sort you can plugin anything into and get anything back out of, this was slightly different.

    If you’ve got a Mac laptop, you’re familiar with the odd way you can change your power adapter to use the 2-prong or grab an extension and use a 3-prong. Backpacking off that concept, the Twist+ adapter lets you plugin your laptop right into the base, while leaving you four USB outlets.

    Example of the twist adapter

    This is the TWIST+ World Charging Station. And I’m a super fan.

    How I Use It

    First, yes, I use it entirely as intended, plugging my laptop and all my devices in. But I actually use it more as a USB hub. Shoving it into my purse, I was able to whip it out at a dinner with friends and plug all our devices in to charge. One of them had a 3-in-1 USB charging cable, and we ended up with 6 devices all plugged in and charging.

    This works well with my ‘style’ as I tend to plugin laptops to charge while I shower and clean up at the end of the day. By the time I’m done, the laptop is charged and goes away, and the hub gets plugged in at my nightstand to charge a Watch, a phone, and an iPad. It could even do another phone without breaking a sweat. And in the absolute worst case? I could plug in my laptop and get two more ports.

    If you just want a USB hub, they (will soon) have a World Charging Station which looks about perfect for a lot of things.