Half-Elf on Tech

Thoughts From a Professional Lesbian

Tag: studiopress

  • Genesis: Overriding a Child Theme

    Genesis: Overriding a Child Theme

    There are some odd tricks you end up learning when you use StudioPress’s Genesis Frameworks. Since no one actually uses the framework as the theme, we’re all downloading children themes and then editing them.

    I have to be honest here, I hate editing child themes. That’s why I’ve begun making a functional plugin to ‘grandchild’ the themes. There are some subtle differences, however, in how one approaches code for a grandchild vs a child ‘theme,’ and one of them is how the credits work.

    Normal Genesis Overrides Are Simple

    At the footer of every page for a StudioPress theme is a credit line. It reads out the year and a link to your theme and Genesis, and done. If you don’t like it, you can edit it like this:

    //* Change the footer text
    add_filter('genesis_footer_creds_text', 'sp_footer_creds_filter');
    function sp_footer_creds_filter( $creds ) {
    	$creds = '[footer_copyright] &middot; <a href="http://mydomain.com">My Custom Link</a> &middot; Built on the <a href="http://www.studiopress.com/themes/genesis" title="Genesis Framework">Genesis Framework</a>';
    	return $creds;
    }
    

    If you’re not comfortable with code, I recommend you use the Genesis Simple Edits plugin. But …

    What happens when your child theme already filters the credits?

    Grandchild Genesis Overrides are Not

    My child theme includes a filter already, called CHILDTHEME_footer_creds_filter, and it’s not filterable. That means I can’t just change the add filter line to this:

    add_filter('genesis_footer_creds_text', 'CHILDTHEME_footer_creds_filter');
    

    That’s okay, though, because I knew I could use could use remove_filter() to get rid of it like this:

    remove_filter( 'genesis_do_footer', 'CHILDTHEME_footer_creds_filter' );
    

    Except that didn’t work. I kicked myself and remembered what the illustrious Mike Little said about how one could replace filters in a theme (he was using Twenty Twelve):

    … your child theme’s functions.php runs before Twenty Twelve’s does. That means that when your call to remove_filter() runs, Twenty Twelve hasn’t yet called add_filter(). It won’t work because there’s nothing to remove!

    Logically, I needed to make sure my filter removal runs after the filter is added in the first place. Right? Logical.

    The Credit Removal Solution

    Here’s how you do it:

    add_action( 'after_setup_theme', 'HALFELF_footer_creds' );
    
    function genesis_footer_creds() {
    	remove_filter( 'genesis_do_footer', 'CHILDTHEME_footer_creds_filter' );
    	add_filter( 'genesis_footer_creds_text', 'HALFELF_footer_creds' );
    }
    
    function genesis_footer_creds_text( $creds ) {
    	$creds = '[footer_copyright] &middot; <a href="https://halfelf.org/">Half-Elf on Tech</a> &middot; Built on the <a href="http://www.studiopress.com/themes/genesis" title="Genesis Framework">Genesis Framework</a>';
    	return $creds;
    }
    

    That first add_action() is called after the theme is set up. Then it removes the filter I don’t want and adds the one I do.

    Done and done.

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

  • Genesis Themes: Author Box Shortcode

    Genesis Themes: Author Box Shortcode

    In building out a network of sites, I was struck upon by a feature of multisite I love, a feature of a theme I adore, and an inconvenience of the combination.

    Author Box

    StudioPress’ Genesis themes include a feature called “Author Box” which allows authors to create bios from their profiles and show them at the bottom of posts. When you have multiple authors on a site, this is a great way to make sure everyone gets credit and that they can control it.

    The code to make this show up is included in most (if not all) StudioPress themes, but if you need to add it for your post archives and single posts, it looks like this:

    add_filter( 'get_the_author_genesis_author_box_single', '__return_true' );
    add_filter( 'get_the_author_genesis_author_box_archive', '__return_true' );
    

    Multisite Magic

    Once the code is enabled, and once someone’s written a bio, their author box shows up for all sites on the network. This is great for what I needed, as it meant everyone had control and I could just set it and forget it. The only ‘annoying’ part is it’s the same bio for all sites, so if you have wildly different sites on your network, this may not be right for you.

    This does harken back to my age old comment: WordPress Multisite is for a network of somewhat related sites.

    By this I mean if all the sites on your network are related, let’s say for a school, then it doesn’t matter that everyone’s bio talks about their school work. But if you combine the school with hobbies, then it gets weird to announce that the champion archer has a PhD in neuroscience. Although that is pretty cool.

    Display The Author Box Anywhere

    The other problem with the author box is you can only use it on pages or posts as context. Which is not what I wanted here. So I made it a shortcode.

    function author_box( $atts ) {
    
    	$user = username_exists( sanitize_user( $atts['user'] ) );
    
    	if ( !$user ) return;
    
    	wp_enqueue_style( 'author-box-shortcode', plugins_url( 'author-box.css', __FILE__ ) );
    
    	$authordata    = get_userdata( $user );
    	$gravatar_size = 'genesis_author_box_gravatar_size' ;
    	$gravatar      = get_avatar( get_the_author_meta( 'email', $user ), $gravatar_size );
    	$description   = wpautop( get_the_author_meta( 'description', $user ) );
    	$username      = get_the_author_meta( 'display_name' , $user );
    
    	$author_box    = '
    		<section class="author-box author-box-shortcode">'
    		. $gravatar
    		. '<h4 class="author-box-title"><span itemprop="name">' . $username . '</span></h4>
    		<div class="author-box-content" itemprop="description">'. $description .'</div>
    		</section>
    	';
    
    	return $author_box;
    }
    

    This is obviously skewed towards Genesis themes, but realistically other than the code in $gravatar_size you can use this for any theme anywhere. The benefit of Genesis here is that most, if not all, of the CSS is done for you. The shortcode is [author-box user="ipstenu"] and it dumps out a full width user box of your named author.

    Display Multiple Boxes Instead

    But… What if you wanted a grid? Or a group of IDs? Taking advantage of the fact that Genesis comes with columns, the code looks like this:

    function author_box( $atts ) {
    
    	if ( $atts['users'] == '' ) return;
    
    	wp_enqueue_style( 'author-box-shortcode', '/wp-content/mu-plugins/css/author-box.css' );
    
    	$users = explode(',', $atts['users'] );
    	$user_count = count( $users );
    
    	$columns = 'one-half';
    	if ( $user_count == 1 ) $columns = '';
    	if ( $user_count % 3 == 0 ) $columns = 'one-third';
    
    	$author_box = '<div class="author-box-shortcode">';
    
    	foreach( $users as $user ) {
    		$user = username_exists( sanitize_user( $user ) );
    		if ( $user ) {
    			$authordata    = get_userdata( $user );
    			$gravatar_size = 'genesis_author_box_gravatar_size' ;
    			$gravatar      = get_avatar( get_the_author_meta( 'email', $user ), $gravatar_size );
    			$description   = wpautop( get_the_author_meta( 'description', $user ) );
    			$username      = get_the_author_meta( 'display_name' , $user );
    
    			$author_box   .= '
    				<section class="author-box '. $columns .'">'
    				. $gravatar
    				. '<h4 class="author-box-title"><span itemprop="name">' . $username . '</span></h4>
    				<div class="author-box-content" itemprop="description">'. $description .'</div>
    				</section>
    			';
    		}
    	}
    
    	$author_box .= '</div>';
    
    	return $author_box;
    }
    

    The shortcode here is [author-box users="ipstenu, liljimmi"] and that puts out a column of either fullwidth, half, or a third. The default is a half, and if there’s only one item, it goes to full width, but I only put in a 1/3rd check because I didn’t feel the need to cover everything. If you want to nick the CSS, StudioPress put it up online, and you can extend it as you want.