Half-Elf on Tech

Thoughts From a Professional Lesbian

Author: Ipstenu (Mika Epstein)

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

  • Still Don’t Disable Right Click

    Still Don’t Disable Right Click

    Back in 2011, I wrote about not disabling right-click. That page still gets a reasonable amount of traffic and it's time for a brief revisit.

    The Only Way to Protect Data Is Not To Have It Online

    Let's start with the lesson everyone needs to learn. There remains but one and only one way to protect your data online. There is only one sure-fire way to make sure your photos aren't stolen, your videos aren't leaked, and your content isn't ripped off. Don't put anything online that you're not alright with having taken from you. This sucks. I know. This is pretty horrid life advice, but the fact is that as soon as you put something up on the Internet, and people like it, they will take it. Worst, they'll claim it as their own. I really hate that one.

    You Can Still Protect Content

    This isn't all bad news. You can still have content that is protected from re-use, it not actual theft, but you have to be intelligent about it. You have to think about what you're protecting and why. Protecting all the images that viewers see on your site is a lost cause. There are just too many ways to download them.  Instead, it's a matter of cutting your losses, protecting only what must be protected, and then intelligently guarding what's left. And here are my simple rules for content protection:
    1. Watermark images you don't want reused
    2. Server protect folders that store downloadable data (i.e. .htaccess )
    3. Hide the URLs for downloadable data
    That's it. Three rules.

    But What About…

    No. What? You want me to talk about how Instagram protects images from right-clicks and, thus, downloads? You want me to point out that even Wix tells you how to protect right-click? You think I should tell people how Getty images uses code to watermark and right-click protect? It doesn't matter. As Wix so rightly points out, anyone who knows how to view source code could get the images anyway. And trust me, people who want your images will work hard and learn that. They'll quickly figure out how to get around it. You can get around Getty images, but they do the most important thing of all. They know you're going to take their low-resolution images. They're okay with that loss kind of – I don't recommend it as they'd sued people over re-use. But they will absolutely take you down if you 'steal' their high resolution images, because the only way to do that is to make an account with them and purchase. They out and out hide the images from anyone who didn't buy them. They're locked behind a user-account. The lesson you can take away is this: The only winning move? Is not to play.