Half-Elf on Tech

Thoughts From a Professional Lesbian

Tag: wordpress

  • Reordering Sort Order Redux

    Reordering Sort Order Redux

    Earlier this year I talked about removing stopwords from sort queries.

    Sadly I ran into a problem where the code wasn’t working.

    The Original Code

    Here’s the original code.

    add_filter( 'posts_orderby', function( $orderby, \WP_Query $q ) {
        if( 'SPECIFIC_POST_TYPE' !== $q->get( 'post_type' ) )
            return $orderby;
     
        global $wpdb;
     
        // Adjust this to your needs:
        $matches = [ 'the ', 'an ', 'a ' ];
     
        return sprintf(
            " %s %s ",
            MYSITE_shows_posts_orderby_sql( $matches, " LOWER( {$wpdb->posts}.post_title) " ),
            'ASC' === strtoupper( $q->get( 'order' ) ) ? 'ASC' : 'DESC'
        );
     
    }, 10, 2 );
     
    function MYSITE_shows_posts_orderby_sql( &$matches, $sql )
    {
        if( empty( $matches ) || ! is_array( $matches ) )
            return $sql;
     
        $sql = sprintf( " TRIM( LEADING '%s' FROM ( %s ) ) ", $matches[0], $sql );
        array_shift( $matches );
        return MYSITE_shows_posts_orderby_sql( $matches, $sql );
    }
    

    This worked, mostly, but it somehow broke pagination. Every page restarted the order. This had to do with complications with the Genesis theme but more importantly it messed up the order on the back of WordPress and it didn’t play well with FacetWP. So I rewrote it a little to be more specific:

    The New Code

    if ( !is_admin() ) {
    	
    	add_filter( 'posts_orderby', function( $orderby, \WP_Query $q ) {
    		
    		// If this isn't an archive page, don't change $orderby
    		if ( !is_archive() ) return $orderby;
    		
    		// If the post type isn't a SPECIFIC_POST_TYPE, don't change $orderby
    		if ( 'SPECIFIC_POST_TYPE' !== $q->get( 'post_type' ) ) return $orderby;
    
    		// If the sort isn't based on title, don't change $orderby
    		$fwp_sort  = ( isset( $_GET['fwp_sort'] ) )? sanitize_text_field( $_GET['fwp_sort'] ) : 'empty';
    		$fwp_array = array( 'title_asc', 'title_desc', 'empty');
    		if ( !in_array( $fwp_sort, $fwp_array ) ) return $orderby;
    
    		// Okay! Time to go!
    		global $wpdb;
    
    		// Adjust this to your needs:
    		$matches = [ 'the ', 'an ', 'a ' ];
    
    		// Return our customized $orderby
    		return sprintf(
    			" %s %s ",
    			MY_CUSTOM_posts_orderby_sql( $matches, " LOWER( {$wpdb->posts}.post_title) " ),
    			'ASC' === strtoupper( $q->get( 'order' ) ) ? 'ASC' : 'DESC'
    		);
    
    	}, 10, 2 );
    
    	function MY_CUSTOM_posts_orderby_sql( &$matches, $sql ) {
    		if( empty( $matches ) || ! is_array( $matches ) )
    			return $sql;
    
    		$sql = sprintf( " TRIM( LEADING '%s' FROM ( %s ) ) ", $matches[0], $sql );
    		array_shift( $matches );
    		return lwtv_shows_posts_orderby_sql( $matches, $sql );
    	}
    }
    

    First of all, I got smart about only loading this when it needed to be loaded. Next I told it to only sort on archive pages, because I was also outputting recently added lists in other places. Finally I forced it to understand Facet, and that if I wasn’t sorting by alphabetical, it didn’t matter at all.

  • Why I Do This

    Why I Do This

    Every once in a while someone makes a few veiled statements about how I must be on some kind of power trip, and that’s why I took control of the Plugin Review team as the rep. It’s not true.

    Why I am a Forum Moderator

    I was helping people and one of the mods asked if I’d join. I said yes. I’m currently still on the team, but I no longer am super active. I’m kind of on the cusp of the requirements for being a moderator, and if they removed me, I’d be okay with that.

    Why I was the Forum Representative

    We were just deciding who should be the very first reps for teams, and I was asked (along with someone else) if I’d be willing to try to help us figure out how we wanted to do this. I stepped down from that responsibility after a few years to lower my personal stress.

    Why I am a Plugin Reviewer

    I had been reporting a bunch of plugins doing bad things, as well as helping the gents figure out some crazy stuff. They abducted me and asked me to help. I did and bit by bit learned how to properly handle reviews. I keep doing reviews because I enjoy it.

    Why I am the Plugin Review Representative

    No one else wanted to do it and we needed someone to take responsibility and make some changes. Like with the guidelines. The directory etc. I still do it because it’s a needed job.

    But … WHY!?

    None of that answers the real question of why I do this at all though. If it’s not apparent, I literally fell into this job by accident and stuck around. I stick around because I enjoy what work I do and I learn from it. Learning about how people write code, the assumptions they make, teach me more about accidental security than all the time I worked at the Bank.

    But also I believe that any social organization that advocates that the means of production, distribution, and exchange should be owned or regulated by the community as a whole. And to that end, I feel that the only right way to make plugin code reviews, or the forums, work is to get the community self-regulating.

    The problem with that theory is that not everyone is altruistic. If people within the community have a desire contrary to the rest of the community, it causes conflict and drama. Therefore, a true ‘socialist’ society requires people willing to be the ‘baddie’ and say things like “No, you can’t do that.” Basically, we need a parent who’s able to explain to the children why putting their hands on the stove is bad, and why throwing rocks at their friend was mean.

    I certainly don’t think I’m the only person who can do this. I just seem to be one of the few willing to do it in a consistent and continuous fashion. And that’s the reason I stick around. I’m trying to build a future where anyone can do technical code reviews for submitted plugins. Anyone. However that comes with a lot of responsibility for the community.

    While there are many people capable of doing a technical review, and many people competent at explaining bad code to developers, and many people wise enough to handle angry developers, that Venn Diagram has a very small crossover. And if you factor in people willing do to it, it gets smaller.

    For example. Everyone complains about the WordPress Plugin Guidelines being too strict and too vague. Last year I undertook the monumental effort of rewriting them for clarity and fairness. I asked people at multiple WordCamps to help. We sat and discussed what the guidelines meant and why they were worded in the way they were. Then I posted on the Make blog asking people to help.

    Of the few hundred people who complained, less than 20 had anything to say.

    From that, and other times I’ve reached out to the community and asked for help, and the results I’ve had, I feel that people aren’t willing to embrace all the aspects of the job. Yet. That’s why I’m slowly, carefully, working my way through the changes. I’m trying to lower the bar for them, to make them more amenable to join.

    It takes time.

    Yes, but that isn’t WHY!

    Oh right. Why do I do this?

    I review plugins because I legit enjoy seeing the crazy code people come up with. I help in the forums for the same reason. I like seeing what people do, and solving problems. I like writing the code to solve the problems too.

    I’m the plugin rep because it’s a dirty job, but someone has to do it, and I’m okay with being hated by people. I know I’m doing it to make code better and safer for users, to encourage developers to engage in ethical and kind business practices, and because I learn from them too.

    At the end of the day, I do this, all of this, because I can, because I enjoy it, and because I feel good when I help people.

    One day that may change. When it does, I’m sure I’ll walk away. That’s just not today.

  • Indiegogo Embed

    Indiegogo Embed

    Indiegogo doesn't have oEmbed, which means you can't just paste in a URL and expect it to work on a WordPress site. And worse, their directions are "Use an iframe plugin!"

    NO.

    Just say NO to iframe plugins!

    Use a shortcode instead!

    If you're brand new to shortcodes, check out Sal Ferrarello's awesome post about it (I saw him talk at WC Philly 2017 and he's amazing). I'll give you the highlights for this one code though.

    The Code

    /*
     * Embed an IndieGoGo Campaign
     *
     * Usage: [indiegogo url="https://www.indiegogo.com/projects/riley-parra-season-2-lgbt"]
     *
     * Attributes:
     *		url: The URL of the project
     */
    add_shortcode( 'indigogo', 'helf_indiegogo' );
    function helf_indiegogo() {
    	$attr = shortcode_atts( array(
    		'url' => '',
    	), $atts );
    	
    	$url    = esc_url( $attr['url'] );
    	$url    = rtrim( $url, "#/");
    	$url    = str_replace( 'projects/', 'project/', $url );
    	$return =  '<iframe src="' . $url . '/embedded" width="222px" height="445px" frameborder="0" scrolling="no"></iframe>';
    
    	return $return;
    }
    

    What It Does

    The code is as basic as I could made it, and it takes the URL of the campaign, strips out the trailing hashtag, changes projects to project (singular – and yes, that gave me a headache), and punts out an iframe.

    Thankfully they make this easy unlike places like CrowdRise where you have to magically know the ID number in order to pull this off.

  • Find It, Write It, or Buy It?

    Find It, Write It, or Buy It?

    When you need to extend WordPress, you have three main choices for how to do it. You can find the code on WordPress.org, you can write the code, or you can buy premium code.

    Which is right depends more on your situation and skills than your space cash.

    Find It

    This is the cheapest, though it can be time consuming. Finding a good plugin or theme on WordPress.org is less a factor of the search function, and more a function of being unable to codify ‘need’ clearly. For example, if you want a slider plugin (no judgement here), there are around 2000 possibilities. Newspaper themes? You’re looking at 70 or so that may fit the bill.

    Finding what you need means you must narrow your search. You have to decide what kind of sliders, or what format of newspaper, you feel is the most important. You want a slider with text overlay? That’s different than one that supports animated images. Newspaper themes don’t always have the same formatting options.

    Once you find the features you want, you still have the headache of reviewing the developer and the code. Oh yes. If you’re installing plugins without looking into the developers or the code, you run a high risk of damaging your site. This isn’t a huge deal for a hobby site, but if you’re trying to make a business or a successful niche site, this can make or break you.

    So. Should you rely on what you find? For the most part, yes. Provided you can vet the code, you’re going to save yourself time, effort, and money. There’s no sense in reinventing the wheel.

    Write It

    This is the most expensive choice. Seriously. Think about how much you get paid a year. Let’s say you make $80k. Divide by two to get $40k. Now. You’re worth about $40 an hour. So if it takes you ten hours to write a plugin or theme, that’s $400. Surprise.

    So why would anyone write their own code? Basically because you cannot find what you’re looking for in a way that meets your requirements, be it security, stability, or functionality. Often you will find very close versions of what you’re looking for, but when the magic bullet is missing, it’s up to you to build it all your own. This is how forks happen, in software, by the way.

    There’s nothing inherently wrong with this, but it requires time and skill you may not have. But should you do it? Yes. If you can’t find what you want, and you know you can write and support the code, this is a perfectly viable option.

    Buy It

    People always seem to not want to do this. And really the only reason I can understand not wanting to buy premium code is that you can’t vet the usability or security until you buy it. That makes freemium code like Yoast SEO or Monster Insights my favourite kind. You can use their free code, see how well it works and if these are people you could work with.

    But when you argue that you shouldn’t have to pay for code, I gesture towards the door and ignore you. Because yes, yes you should. Remember how 10 hours of writing your own code is around $400? Plus ongoing upkeep? Okay, that plugin you want is $60 a year. That means six years of the plugin is the same cost as writing it yourself. Which is a way better deal.

    Should you buy it? Yes! Absolutely yes, buy the plugins but only if you can vet the plugin shop first.

    Wait… You said yes to all three!

    Surprise twist ending!

    Here’s the thing. Every single decision you make has a cost and repercussions. They’ll all cost you time, money, and a bit of a headache no matter what you pick. So the real answer, the one I can’t give you, is what’s worth more to you?

    For me, I will use free if it exists, I’ll write my own if it doesn’t, and I’ll buy premium if they do it so well I’m just whistling dixie.

  • FacetWP: Spinning While Updating

    FacetWP: Spinning While Updating

    When you use FacetWP you can do some cool things like change the ‘count’ output of a page. Using the function facetwp_display() you can add facetwp_display( 'counts' ) to your page title, and then a boring old archive title goes from “List of Characters (2022)” to “List of Characters (1-24 of 2022)”

    But… What if you could do more?

    What Could Be More?

    If you have a lot of data, sometimes a page can load and FacetWP spins while it collects everything in it’s wee javascripty brain. When that happens, you have a cognitive moment of “What?” And in order not to lose a user, you want to indicate, somehow, that an action is happening. A spinning icon is, I think, a great way to do that.

    So with that in mind, I want to do this:

    List of Characters showing a spinning icon for the number

    And I did.

    The Code

    This needs javascript. I used some logic from the FacetWP documentation and some memories about how you can replace text with javascript and came up with this:

    (function($) {
    	$(document).on('facetwp-refresh', function() {
    		$('.facetwp-count').html('<i class="fa fa-spinner fa-pulse fa-fw"></i><span class="sr-only">Loading...</span>');
    	});
        
        $(document).on('facetwp-loaded', function() {
    	   $('.facetwp-count').html('');
    	});
        
    })(jQuery);
    

    Then I slap it into my PHP code like so:

    $count_posts = facetwp_display( 'counts' );
    
    the_archive_title( '<h1 class="facetwp-page-title page-title">' . $title, ' (' . $count_posts . '<span class="facetwp-count"></span>)</h1>' );
    

    The content for $count_posts shows nothing while it’s loading, so the check for facetwp-loaded will handle it perfectly.

  • Alternate Symbols

    Alternate Symbols

    I like to remotely host my SVGs and then call them in my code. For the most part, this works well, and I wrote out some basic code to check if they’re defined and accessible before displaying.

    But what if you wanted your fallback to be a font-icon?

    And remember, you want your code to be DRY as a bone. So no repeating chunks of code all over the place, please and thank you.

    The Code

    There is but ONE requirement here. You have to define HALFELF_SYMBOLICONS_PATH as the path to your SVGs. In my case, mine is something like http://my-cool-icons.objects-us-west-1.dream.io/svgs/ because I’m using DreamObjects for them. Any cloud host works great for this, mind you.

    function halfelf_symbols( $svg = 'square.svg', $fontawesome = 'fa-square' ) {	
    
    	$icon = '<i class="fa ' . $fontawesome . '" aria-hidden="true"></i>';
    
    	if ( defined( 'HALFELF_SYMBOLICONS_PATH' ) ) {
    		$response      = wp_remote_get( HALFELF_SYMBOLICONS_PATH );
    		$response_code = wp_remote_retrieve_response_code( $response );
    		
    		if ( $response_code == '200' ) {
    			$get_svg      = wp_remote_get( LP_SYMBOLICONS_PATH . $svg );
    			$response_svg = wp_remote_retrieve_response_code( $get_svg );
    			$icon         = ( $response_svg == '200' )? $get_svg['body'] : 'square.svg';
    		}
    	}
    
    	return $icon;
    }
    

    This checks for the existence of the server used and if the actual icon exists before it sets things.

    Usage Example

    In my code, I define it like this:

    $icon  = halfelf_symbols( 'users.svg', 'fa-users' );
    $title = '<span role="img" aria-label="users" title="Users" class="TEMPLATE users">' . $icon . '</span>';
    

    This sets the icon and then calls the span which will help make this more accessibility friendly. I could have coded the span into the function, but since I often have it all dynamically generated, it worked more sustainably this way.

    In this example, I call it like this:

    the_archive_title( '<h1 class="page-title">' . $title . '</h1>' );
    

    And voila. Icons in my page title.