Half-Elf on Tech

Thoughts From a Professional Lesbian

Author: Ipstenu (Mika Epstein)

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

  • Sharing Content with Static Sites Dynamically

    Sharing Content with Static Sites Dynamically

    When I wrote how to serve content to Hugo, I did so using something that was mostly static. You see, that code requires someone to push a new version of the Hugo site to rebuild the pages.

    Now let’s be serious, who wants to do that?

    The Concept

    Sadly, you can’t just include a PHP file in Hugo (or any static site builder) and have it echo content. Their whole point is to be static and not change. And my problem is that I immediately ran into a week where I knew the message on the header was going to be changing daily.

    Ew, right? Right. So I looked at that which I should be embracing deeply. Javascript. Or in this case, jQuery and the getJSON call. Yes, that’s right, with jQuery you can call JSON and output it where you want.

    I do not recommend doing this for full page content. This is only vaguely smart if you’re trying to output something small that loads fast and isn’t going to mess up your site if someone has javascript disabled.

    The Code

    <script>
    	$.getJSON( "https://example.com/wp-json/wp/v2/pages/14363", function (json) {
    	    var content = json.content.rendered;
    		document.querySelector('.wpcontent').innerHTML = content;
    	});
    </script>
    
    <div class="utility-bar">
    	<div class="wrap">
    		<section id="text-16" class="widget widget_text">
    			<div class="widget-wrap">
    				<div class="textwidget">
    					<div class="wpcontent"></div>
    				</div>
    			</div>
    		</section>
    	</div>
    </div>
    

    What that code does is it grabs the JSON, sets the variable content to the value of the content’s ‘rendered’ setting. Then using document.querySelector, it tosses in the HTML to my class for wpcontent and I’m done.

  • Why I Write About What I Code

    Why I Write About What I Code

    I was asked this the other day. Obviously sometimes I write about technology in general, or software I find and like, but a great deal of the posts here are about how I figure things out. And the reason I do that is, simply, it makes me a better writer and a better coder.

    Want to write better?

    There’s nothing that will make you a better write than writing. You will learn your voice, your tone, and your flavor of writing only if you write. It doesn’t matter if your writing is bad at first. By writing more and more and more you will only get better and better at the process, and more comfortable doing it.

    Getting into the habit of writing, where it’s an every day occurrence in your life, is imperative if you want to write better. It’s a talent, yes, but it’s also a skill. And if you don’t practice skills they get rusty. If they get too rusty, they break and you give up.

    Want to code better?

    The fastest way to get better at code is to read and review other people’s code and try to figure out how they did what they did. The reason I can continue to think as sharply as I do about plugin reviews is that I do it every day. Every. Single. Day. I look at 30 to 100 plugins, review the code as written by just as many developers, reverse engineer what they’ve done, and I start to understand better. I peer review people’s code, day in and day out.

    But nothing makes you a better code than coding. Obviously. And yet there’s one thing most people miss. You see, the critical review of your own code is absolutely necessary if you want to become a better coder. And in the absence of peer reviewed code, the best thing to do is rip it apart yourself.

    Can you explain your code?

    That’s it. That’s the magic. If you can explain your code, why you did what you did, why it does what it does, then you are at the step of critically reviewing your code. The number of times my code has improved because I’ve blogged about it is uncountable. As I write my post, I find myself typing “I used the function X because…” and I stop. Why did I use that function?

    It’s in the questioning of my own actions that I begin to understand my own internal logic. You know, the part of your brain your parents and teachers helped you form. Those early days of logic where you learned fire was hot and one plus one was two, you also developed your own style of thinking.

    Can you explain why?

    My father likes to tell me I used to do my math backwards, from left to right, before my school taught me otherwise. On occasion, I still do it that way because I want to look at my math from a different perspective. Talking about why I do that changes my understanding of the process. The solution was always the same, but the process of getting there is vastly different.

    When I talk about why I chose the path I did, I do more than just verbalize to myself what I’ve done, I teach someone else that there’s an answer and there’s a way to their answers as well. I’ve shown a path.

    I write to understand myself

    Above all else, I write to understand myself. Only by doing that can I improve at anything.

  • FacetWP and Genesis Pagination

    FacetWP and Genesis Pagination

    If you use StudioPress’ Genesis themes, you may be used to that pretty numerical pagination instead of ye olde previous and next buttons. And if you use FacetWP, you may have found out you need to use their pagination to make things work right.

    Thankfully this can be fixed thanks to two people’s previous work.

    Replace the Navigation

    First we look to Sridhar Katakam who came up with an elegant way to replace the normal Genesis post navigation. The code is nearly the same, I just single-lined the returns:

    // Replace Genesis' Pagination with FacetWP's.
    // Context: Posts page, all Archives and Search results page.
    // @author Sridhar Katakam - http://sridharkatakam.com/facetwp-genesis/
    add_action( 'loop_end', 'MYSITE_replace_genesis_pagination' );
    function MYSITE_replace_genesis_pagination() {
    	if ( ! ( is_home() || is_archive() || is_search() ) ) return;
    	remove_action( 'genesis_after_endwhile', 'genesis_posts_nav' );
    	add_action( 'genesis_after_endwhile', 'MYSITE_facet_posts_nav' );
    }
    function MYSITE_facet_posts_nav() {
    	echo facetwp_display( 'pager' );
    }
    

    The nice part about this is that if you’re not using FacetWP on that page, it reverts to the default pager. I’m not doing a check on if Facet exists because I have this in a giant block that does it for me. If you need to, though, the code would be this:

    if ( function_exists( 'facetwp_display' ) ) { 
        add_action( 'loop_end', 'MYSITE_replace_genesis_pagination' ); 
    }
    

    And yes, you should always check if the plugin is loaded before you break things.

    Style the Navigation

    The styling magic comes from a slight fork of Matt Gibbs’ code to remove pagination if there’s only one post:

    // Style pagination to look like Genesis
    // @author Matt Gibbs
    // https://gist.github.com/mgibbs189/69176ef41fa4e26d1419
    function MYSITE_facetwp_pager( $output, $params ) {
        $output = '<div class="archive-pagination pagination"><ul>';
        $page = (int) $params['page'];
        $total_pages = (int) $params['total_pages'];
    
        // Only show pagination when > 1 page
        if ( 1 < $total_pages ) {
    
            if ( 1 < $page ) {
                $output .= '<li><a class="facetwp-page" data-page="' . ( $page - 1 ) . '">&laquo; Previous Page</a></li>';
            }
            if ( 3 < $page ) {
                $output .= '<li><a class="facetwp-page first-page" data-page="1">1</a></li>';
                $output .= ' <span class="dots">…</span> ';
            }
            for ( $i = 2; $i > 0; $i-- ) {
                if ( 0 < ( $page - $i ) ) {
                    $output .= '<li><a class="facetwp-page" data-page="' . ($page - $i) . '">' . ($page - $i) . '</a></li>';
                }
            }
    
            // Current page
            $output .= '<li class="active" aria-label="Current page"><a class="facetwp-page active" data-page="' . $page . '">' . $page . '</a></li>';
    
            for ( $i = 1; $i <= 2; $i++ ) {
                if ( $total_pages >= ( $page + $i ) ) {
                    $output .= '<li><a class="facetwp-page" data-page="' . ($page + $i) . '">' . ($page + $i) . '</a></li>';
                }
            }
            if ( $total_pages > ( $page + 2 ) ) {
                $output .= ' <span class="dots">…</span> ';
                $output .= '<li><a class="facetwp-page last-page" data-page="' . $total_pages . '">' . $total_pages . '</a></li>';
            }
            if ( $page < $total_pages ) {
                $output .= '<li><a class="facetwp-page" data-page="' . ( $page + 1 ) . '">Next Page &raquo;</a></li>';
            }
        }
    
        $output .= '</ul></div>';
    
        return $output;
    }
    add_filter( 'facetwp_pager_html', 'MYSITE_facetwp_pager', 10, 2 );
    

    This is somewhat obvious. It adds in <li></li> around each page item, and also wraps the entire block in the default Genesis code of <div class="archive-pagination pagination"><ul></ul></div> to produce the default Genesis display.

  • Will You Help Me Sell My Plugin?

    Will You Help Me Sell My Plugin?

    I get asked this a lot. It comes with the territory, but people ask me to help them monetize their plugins all the time. And my answer is always the same.

    No

    As much as I am a strong advocate of people making money off of WordPress, and as much as I support plugin and theme devs in their work, I’m not out here to help you run your business. While I do spend time thinking of ways to get people to pay for services and software, I don’t prioritize it, and most of my ideas are just that. Ideas.

    Really what people are asking for is my ideas and my free work. And to that, I say no.

    Business Help Isn’t Free

    If you wanted to hire me to help, to look at your code and to assist you in coming up with business strategies, based on my experience in the WordPress world, that’s a different matter. That gets a ‘no’ because I don’t have the time to dedicate to that work. I have a full time job that I do like, and I have some volunteer work I enjoy, and I have a very addictive side project. Since I enjoy being married, I don’t take on extra work right now. I don’t need the money.

    But the point here, if you can’t tell, is that yes, I would expect you to pay me for my work.

    I’m No Good At Sales

    Of course, keep in mind the fact that I’m a terrible salesman. I don’t like exaggerating what a product can do, I don’t like even suggesting a lie. I downplay. And that’s because I don’t like it when people promise the moon and only deliver low Earth orbit. I want realistic goals and possibilities. Can you do anything with this plugin? Sure. But it comes at a cost and I feel people should know that cost.

    I’m Hard to be Bought

    Everyone may have a price, but my price is rarely money. I know this sounds weird, since I said I expect people to pay me for my work. You see, asking me to do you a favor for free doesn’t really happen. But also, asking me to do you a favor for pay won’t happen.

    And by this I mean reviews.

    I’ve been asked, many times, to review people’s themes and plugins and post about it here. And in general, I say no. I review the things I use and like because I use and like them. I’m driven by usability. If I like your ‘thing’ and I think people should hear about it, I’ll talk it up. If your thing is free or for sale, I don’t care. What I care is if your thing was what I needed and wanted, and I liked it.

    I Won’t Help You Sell

    That’s not my deal. It’s not my deal on this blog. I’ve never been bought off for a review, I’ve never been asked “Would you review this product of mine?” unless I’ve already been known to use it. And even then, I’ve told people “You don’t want me to review it. I like it, but you have some bad bugs.”

    I’m honest. I’m direct. I’m incurably truthful.

    You probably don’t want me to help you sell your stuff, but if I really like it, I may anyway.