Half-Elf on Tech

Thoughts From a Professional Lesbian

Tag: development

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

  • 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.
  • Expect the Unexpected

    Expect the Unexpected

    The other day, while reviewing a plugin, I told someone that their code was okay, but it could be better.

    They had this:

    if ( $_POST['value'] == 1 ) {
        $variable = yes;
    }
    if ( $_POST['value'] == -1 ) {
        $variable = no;
    }
    

    And I said they should do this:

    $variable = ( $_POST['value'] == 1 )? 'yes' : 'no';
    

    They asked why, since the only possible input were 1 and -1.

    Users Are Weird

    It’s hard to explain why users are so weird, but they are. Any time you have post data that a user can input, a user will find a way to intentionally or accidentally put in bad data. I think perhaps the best way to explain it is that users are like toddlers. You can baby proof your house, but they’ll figure out how to get into the flour and suddenly your kitchen looks like an episode of Cutthroat Kitchen and good luck cleaning it up.

    The point is this. Even if your data is only meant to be a 1 or a -1, you have to think beyond what the code should be and assume it will, one day, be what it’s it.

    Broaden Your Mind

    The basic rule of any input screen is that users will do what they do. They just will. They use code in ways you didn’t imagine, and that’s okay. And even if you have a check box, which logically cannot be altered beyond checked or un-checked, someone will do something outside your expectations.

    The easiest way to understand it is to think about hackers. The whole reason we sanitize checkbox data is not that we expect a user to make a phenomenal mistake, but we expect a hacker to show up and try to back-door our work. We cannot trust that every user has good intentions. This is even more common in WordPress, since anyone can download your code, examine in for weaknesses, and then attack.

    Angry People Do Bad Things

    If I had a nickel for every time I heard “But an admin would never…” I’d be rich.

    A good admin would never, intentionally, break their own system, this is true. But an admin who was just fired, and hasn’t had their credentials revoked yet? Oh gosh, can they ever be evil. When a person was fired at a job I once had, they went into the test lab, took all the diskettes, and tossed them in the dumpster. The protocol for handling people being fired was changed that day, but all it took was one angry admin, and we had to go dumpster diving for 3.5″ floppy disks.

    No, it wasn’t fun.

    Trust No Data

    I never trust data. Not even on code only I use. I always assume I can be tricked into doing something dangerous, or that I’ll make a mistake while using a system. Humans make mistakes. You can’t trust them to be right all the time, and you can’t trust them to be good all the time.

    That means it becomes our responsibility, as developers, to do the following:

    1. Make sure the data entered is sanity-checked
    2. If it’s not sane, fallback to a safe default or throw a good error

    But never, ever, trust anyone to be right all the time. Especially you.

  • Grandchildren Themes

    Grandchildren Themes

    I’m a fan of Genesis themes. They look nice, they’re secure, and they’re well coded. A lot of things I have to reinvent in other themes are done out of the box in Genesis.

    But they’re not perfect.

    Frameworks Beget Children Themes

    The problem with Genesis themes is that if you use them, you’ll end up using a Child Theme and not Genesis. Unlike boilerplate themes like Underscores, you’re not meant to edit the theme itself but make a child theme.

    For the most part, this doesn’t bother me. I don’t generally edit the child themes, except in two cases. Both of my fan sites run highly modified versions of the default themes, and one of them uses the amazing Utility Pro theme by Carrie Dils.

    And that was my problem. I knew Carrie was working on a new version which would have some amazing updates. And I? I had forked her theme.

    Marrying Forks

    Merging my fork to her new theme had, generally, not been an issue. I’ve updated it a dozen times already and I just run a tool to find the diff between the files. I’m a Coda fan, and I use Comparator to check out the differences between files. Doing this is time consuming and annoying, however, and generally leads to people not making changes they should.

    As time went on, I made fewer and fewer changes not because I didn’t want to, but because I had gotten increasingly smarter. Why edit out what I could de-enqueue, for example?

    Grandchildren Plugins

    The solution to my woes was a grandchild. Except instead of a grandchild theme, I made a plugin. Actually I have an mu-plugin called “Site Functions” and in that file is this call:

    if ( 'Utility Pro' == $theme->name ) {
    include_once( dirname( __FILE__ ) . '/utility-pro/functions.php' );
    }
    

    That file has 300-ish lines of code, which sounds like a lot now that I look at it. Except it boils down to 6 actions and 7 filters:

    add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
    add_action( 'genesis_after_entry_content', array( $this, 'genesis_after_entry_content' ), 15 );
    add_action( 'wp_head', array( $this, 'header' ) );
    add_action( 'genesis_before_comment_form', array( $this, 'before_comment_form_policy' ) );
    add_action( 'genesis_before_comments', array( $this, 'before_comments_ads' ) );
    add_action( 'genesis_setup', array( $this, 'theme_setup' ), 20 );
    
    add_filter( 'the_content_more_link', array( $this, 'more_link_text' ) );
    add_filter( 'excerpt_more', array( $this, 'more_link_text' ) );
    add_filter( 'admin_post_thumbnail_html', array( $this, 'admin_post_thumbnail_html' ) );
    add_filter( 'genesis_title_comments', array( $this, 'genesis_title_comments' ) );
    add_filter( 'genesis_comment_list_args', array( $this, 'comment_list_args' ) );
    add_filter( 'comment_form_defaults', array( $this, 'comment_form_defaults' ) );
    add_filter( 'genesis_footer_creds_text', array( $this, 'footer_creds' ), 99 );
    

    Everything I did editing the theme, I can do in those 6 actions and 7 filters. It’s positively amazing. For example, I mentioned dequeueing? I don’t like using Google Fonts if I don’t have to, so I remove them. But I also needed to change the backstretch arguments to properly force my image in the right location, so I can do this:

    wp_dequeue_script( 'utility-pro-fonts' );
    wp_dequeue_script( 'utility-pro-backstretch-args' );
    wp_enqueue_script( 'utility-pro-backstretch-args',  WP_CONTENT_URL . '/mu-plugins/utility-pro/backstretch.args.js', array( 'utility-pro-backstretch' ), '1.3.1', true );
    

    That removes the fonts and backstretch arguments, and then adds my own in. And yes, I know my method of calling mu-plugins is not great. I do it this way because I have symlinks, and plugins_url() manages to call that URL instead of the one I want it to.

    The Benefits

    Doing my code this way means it can’t be deactivated. It also is called by checking the theme, so if that changes then the files stop being called. I keep my own work under version control, letting me go back any time I need to. I’m no longer duplicating Carrie’s work either, speeding up my development time.

    It’s a win all around.

  • Local: For When You Don’t Need The Kitchen Sink

    Local: For When You Don’t Need The Kitchen Sink

    The app formerly known as Pressmatic was bought by Flywheel and converted to be Local.

    I’d been wanting to try Pressmatic for a while, but had some ethical concerns about paying when I knew the owner wasn’t paying his other employees. At this point, however, the damage has been done in a way I can live with, so I downloaded Local to play with.

    Local Is an App

    The best thing about Local is that it’s an app. Vagrant is awesome, but it’s 100% command line, and while I’m fine with that, not everyone else is. The learning curve for VVV is steep and, given what you can do with it, it’s not a bad thing. I love it but it can be overkill when I want to work on my plugins. Local is an app, it looks like a Mac app and behaves like a Mac app, so it makes it more obvious how I use it and what I do with it.

    Syncing Data

    My biggest issue with VVV (and VVV2) is I can’t sync folders from Vagrant to my desktop. This is a workflow issue and I know it. For me, I have dedicated folders for my plugin development, all saved in ~/Development/wordpress/plugins-git/ (with a folder per plugin obviously). That makes it easy for me to script updates by saying “For every git repository in this folder, do a pull.”

    Since I do my development work on multiple computers, having as much of this automated as possible is important for my sanity, no matter how much Sara Lance tries to destroy it. Every time I log in to my computer, it runs the update which pulls everything down and syncs.

    And all that means, for VVV, I have two options.

    1. checkout a git repository into the plugin locations for my site and edit those, syncing them back up.
    2. manually copy files over every time I update them

    But with Local, I can use the add-on Volumes which lets me map a folder on Local’s virtual machine to my local desktop. Now it’s not perfect, but with this script by Andy Fragen, I was able to set up my site with actual honest to goodness symlinks:

    [gist]https://gist.github.com/afragen/748e4780b6057d4c41cf9e466557042a[/gist]

    Now I just edit my repositories and magically they’re updated on Local. Faster development for the win.

    (My own fork of Andy’s code is available here on Github – I made some changes but not much.)

    Conclusion

    I use both.

    VVV is great. I love it when I’m working on WordPress core, or god help me, WordPress.org itself.

    But when it’s just me developing my own software and testing? I like Local. It’s good.

  • Datepicker and a Widget

    Datepicker and a Widget

    Last week, I worked on making a plugin that would safely and smartly allow for a date selection, and not permit people to put in junk data. I had my code ‘clean’ and only accepted good data, there was one question remaining. How do I make it look GOOD?

    Let’s be honest, pretty data matters. If things look good, people use them. It’s that simple. This let me play with another aspect of coding that I don’t generally look at. Javascript.

    What Code Do I Need?

    There are a lot of ways to tackle this kind of problem. If you wanted to just list the months and days, and have those be drop-downs, you could do that. The option I went with was to have a calendar date-picker pop up, as I felt that would visually explain what the data should be.

    To do that I needed a date picker jQuery script (which is included in WordPress core) and a second script to format the output.

    My Script

    This part is really small:

    jQuery(function() {
        jQuery( ".datepicker" ).datepicker({
            dateFormat : "mm-dd"
        });
    });
    

    All it does is force the format to be “mm-dd” – so if you picked the date, that’s what it would be.

    Enqueuing the Scripts

    In order to make sure the scripts are only loaded on the widgets page, my enqueue function looks like this:

    	public function admin_enqueue_scripts($hook) {
    		if( $hook !== 'widgets.php' ) return;
    		wp_enqueue_script( 'byq-onthisday', plugins_url( 'js/otd-datepicker.js', __FILE__ ), array( 'jquery-ui-datepicker' ), $this->version, true );
    		wp_enqueue_style( 'jquery-ui', plugins_url( 'css/jquery-ui.css', __FILE__ ), array(), $this->version );
    	}
    

    The CSS is because, by default, WordPress doesn’t include the jquery UI CSS.

    Calling the Scripts

    In the widget class, I have a function for the form output. In there, I have an input field with a class defined as datepicker, which is used by the jquery I wrote above, to know “I’m the one for you!”

    	function form( $instance ) {
    		$instance = wp_parse_args( (array) $instance, $this->defaults );
    		?>
    		<p>
    			<label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"><?php _e( 'Title', 'bury-your-queers' ); ?>: </label>
    			<input type="text" id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>" value="<?php echo esc_attr( $instance['title'] ); ?>" class="widefat" />
    		</p>
    
    		<p>
    			<label for="<?php echo esc_attr( $this->get_field_id( 'date' ) ); ?>"><?php _e( 'Date (Optional)', 'bury-your-queers' ); ?>: </label>
    			<input type="text" id="<?php echo esc_attr( $this->get_field_id( 'date' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'date' ) ); ?>" class="datepicker" value="<?php echo esc_attr( $instance['date'] ); ?>" class="widefat" />
    			<br><em><?php _e( 'If blank, the date will be the current day.', 'bury-your-queers' ); ?></em>
    		</p>
    		<?php
    	}
    

    Making it Pretty

    To be honest, once I got the JS working, I left the default CSS alone. Why? Because I’m a monkey with a crayon when it comes to design. The default worked fine for me:

    The Default Date Picker

    It does make me think that it would be nice if WordPress included their own customize datepicker colors in the admin colors, but I understand why they don’t. Not everyone or even most people will ever need this.