Loop through the terms of a Custom Taxonomy

Loop through the terms of a custom taxonomy and get their stuff. This outputs a list of terms from a custom taxonomy and lists their “ID’s”.

// loop through terms of a custom Taxonomy
$getArgs = array(
	'parent'       => 0,
	'order' => 'DESC',
	'orderby' => 'count',
   	'hide_empty'    => false,
);
$taxonomy = get_terms('MY_TAX', $getArgs);
			
foreach ($taxonomy as $term) { 
            
	 echo '<li>' . $term->term_id . '</li>';
                
}

 

Non hierarchal taxonomies with checkboxes

How to get non hierarchal taxonomies, like tags, to have a checkbox system like a hierarchal taxonomy like categories.

Place the following in a plugin or your theme’s function file. All you have to do is change the last lines CUSTOM_TAXONOMY and CUSTOM_POST_TYPE to meet your needs.

<?php
class Tag_Checklist {

    private $taxonomy;
  private $post_type;

	function __construct( $taxonomy, $post_type ) {
		$this->taxonomy = $taxonomy;
		$this->post_type = $post_type;

		// Remove default taxonomy meta box
		add_action( 'admin_menu', array( $this, 'remove_meta_box' ) );

		// Add new meta box
		add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );

		// Handle Ajax call for adding new term
		add_action( 'wp_ajax_add-' . $this->taxonomy , '_wp_ajax_add_non_hierarchical_term' );

	}

	/**
	 * Remove default meta box
	 * @return void
	 */
	public function remove_meta_box() {
		remove_meta_box('tagsdiv-' . $this->taxonomy, $this->post_type, 'normal');
	}

	/**
	 * Add new metabox
	 * @return void
	 */
	public function add_meta_box() {
		$tax = get_taxonomy( $this->taxonomy );
		add_meta_box( 'taglist-' . $this->taxonomy, $tax->labels->name, array( $this, 'metabox_content' ), $this->post_type, 'side', 'core' );
	}

	/**
	 * Generate metabox content
	 * @param  obj $post Post object
	 * @return void
	 */
	public function metabox_content( $post ) {
        $taxonomy = $this->taxonomy;
        $tax = get_taxonomy( $taxonomy );
		?>
		<div id="taxonomy-<?php echo $taxonomy; ?>" class="categorydiv">

			<ul id="<?php echo $taxonomy; ?>-tabs" class="category-tabs">
				<li class="tabs"><a href="#<?php echo $taxonomy; ?>-all"><?php echo $tax->labels->all_items; ?></a></li>
				<li class="hide-if-no-js"><a href="#<?php echo $taxonomy; ?>-pop"><?php _e( 'Most Used' ); ?></a></li>
			</ul>

			<div id="<?php echo $taxonomy; ?>-pop" class="tabs-panel" style="display: none;">
				<ul id="<?php echo $taxonomy; ?>checklist-pop" class="categorychecklist form-no-clear" >
					<?php $popular_ids = wp_popular_terms_checklist( $taxonomy ); ?>
				</ul>
			</div>

		    <div id="<?php echo $taxonomy; ?>-all" class="tabs-panel">
		    	<input type="hidden" name="tax_input[<?php echo $taxonomy; ?>][]" value="0" />
				<?php
				if( class_exists( 'Walker_Tag_Checklist' ) ) {
					$walker = new Walker_Tag_Checklist;
				}
				?>
		       <ul id="<?php echo $taxonomy; ?>checklist" data-wp-lists="list:<?php echo $taxonomy; ?>" class="categorychecklist form-no-clear">
					<?php wp_terms_checklist($post->ID, array( 'taxonomy' => $taxonomy, 'popular_cats' => $popular_ids , 'walker' => $walker ) ) ?>
				</ul>
		   </div>
			<?php if ( current_user_can($tax->cap->edit_terms) ) : ?>
				<div id="<?php echo $taxonomy; ?>-adder" class="wp-hidden-children">
					<h4>
						<a id="<?php echo $taxonomy; ?>-add-toggle" href="#<?php echo $taxonomy; ?>-add" class="hide-if-no-js">
							<?php
								/* translators: %s: add new taxonomy label */
								printf( __( '+ %s' ), $tax->labels->add_new_item );
							?>
						</a>
					</h4>
					<p id="<?php echo $taxonomy; ?>-add" class="category-add wp-hidden-child">
						<label class="screen-reader-text" for="new<?php echo $taxonomy; ?>"><?php echo $tax->labels->add_new_item; ?></label>
						<input type="text" name="new<?php echo $taxonomy; ?>" id="new<?php echo $taxonomy; ?>" class="form-required form-input-tip" value="<?php echo esc_attr( $tax->labels->new_item_name ); ?>" aria-required="true"/>
						<input type="button" id="<?php echo $taxonomy; ?>-add-submit" data-wp-lists="add:<?php echo $taxonomy ?>checklist:<?php echo $taxonomy ?>-add" class="button category-add-submit" value="<?php echo esc_attr( $tax->labels->add_new_item ); ?>" />
						<?php wp_nonce_field( 'add-'.$taxonomy, '_ajax_nonce-add-'.$taxonomy, false ); ?>
						<span id="<?php echo $taxonomy; ?>-ajax-response"></span>
					</p>
				</div>
			<?php endif; ?>
		</div>
		<?php
	}
}


/**
 * Mod of WP's Walker_Category_Checklist class
 */
class Walker_Tag_Checklist extends Walker {
    var $tree_type = 'tag';
  var $db_fields = array ('parent' => 'parent', 'id' => 'term_id');

	function start_lvl( &$output, $depth = 0, $args = array() ) {
		$indent = str_repeat("\t", $depth);
		$output .= "$indent<ul class='children'>\n";
	}

	function end_lvl( &$output, $depth = 0, $args = array() ) {
		$indent = str_repeat("\t", $depth);
		$output .= "$indent</ul>\n";
	}

	function start_el( &$output, $tax_term, $depth, $args, $id = 0 ) {
		extract($args);
		if ( empty($taxonomy) )
			$taxonomy = 'tag';

		if ( $taxonomy == 'tag' )
			$name = 'post_tag';
		else
			$name = 'tax_input['.$taxonomy.']';

		$class = in_array( $tax_term->term_id, $popular_cats ) ? ' class="popular-category"' : '';
		$output .= "\n<li id='{$taxonomy}-{$tax_term->term_id}'$class>" . '<label class="selectit"><input value="' . $tax_term->slug . '" type="checkbox" name="'.$name.'[]" id="in-'.$taxonomy.'-' . $tax_term->term_id . '"' . checked( in_array( $tax_term->term_id, $selected_cats ), true, false ) . disabled( empty( $args['disabled'] ), false, false ) . ' /> ' . esc_html( apply_filters('the_category', $tax_term->name )) . '</label>';
	}

	function end_el( &$output, $tax_term, $depth = 0, $args = array() ) {
		$output .= "</li>\n";
	}
}

if( ! function_exists( '_wp_ajax_add_non_hierarchical_term' ) ) {
    /**
   * Mod of _wp_ajax_add_hierarchical_term to handle non-hierarchical taxonomies
	 * @return void
	 */
	function _wp_ajax_add_non_hierarchical_term() {
		$action = $_POST['action'];
		$taxonomy = get_taxonomy( substr( $action, 4 ) );
		check_ajax_referer( $action, '_ajax_nonce-add-' . $taxonomy->name );
		if ( !current_user_can( $taxonomy->cap->edit_terms ) )
			wp_die( -1 );
		$names = explode( ',', $_POST['new'.$taxonomy->name] );
		$parent = 0;
		if ( $taxonomy->name == 'category' )
			$post_category = isset( $_POST['post_category'] ) ? (array) $_POST['post_category'] : array();
		else
			$post_category = ( isset( $_POST['tax_input'] ) && isset( $_POST['tax_input'][$taxonomy->name] ) ) ? (array) $_POST['tax_input'][$taxonomy->name] : array();
		$checked_categories = array_map( 'absint', (array) $post_category );
		$popular_ids = wp_popular_terms_checklist( $taxonomy->name, 0, 10, false );

		// Set up custom walker
		$walker = false;
		if( class_exists( 'Walker_Tag_Checklist' ) ) {
			$walker = new Walker_Tag_Checklist;
		}

		foreach ( $names as $tax_name ) {
			$tax_name = trim( $tax_name );
			$category_nicename = sanitize_title( $tax_name );
			if ( '' === $category_nicename )
				continue;
			if ( ! $cat_id = term_exists( $tax_name, $taxonomy->name, $parent ) )
				$cat_id = wp_insert_term( $tax_name, $taxonomy->name, array( 'parent' => $parent ) );
			if ( is_wp_error( $cat_id ) )
				continue;
			else if ( is_array( $cat_id ) )
				$cat_id = $cat_id['term_id'];
			$checked_categories[] = $cat_id;
			if ( $parent ) // Do these all at once in a second
				continue;
			ob_start();
			$args = array(
				'taxonomy' => $taxonomy->name,
				'selected_cats' => $checked_categories,
				'popular_cats' => $popular_ids,
				'checked_ontop' => true
			);
			if( $walker ) {
				$args['walker'] = $walker;
			}
			wp_terms_checklist( 0, $args );
			$data = ob_get_contents();
			ob_end_clean();
			$add = array(
				'what' => $taxonomy->name,
				'id' => $cat_id,
				'data' => str_replace( array("\n", "\t"), '', $data ),
				'position' => -1
			);
		}

		$x = new WP_Ajax_Response( $add );
		$x->send();
	}
}
 new Tag_Checklist( 'CUSTOM_TAXONOMY', 'CUSTOM_POST_TYPE' );

 

Query adjacent next and previous posts from current post in specific term

WordPress offers get_adjacent_post() to get the next post in the current term. It’s just like next and previous post link, but see’s what terms the current post is attached to, and stay’s within that term/terms. So if your current post is in terms ‘x’ and ‘y’, it will not pull any posts in ‘z’.

get_adjacent post() works great if all posts are only located in one term in a taxonomy and works ok when posts are in multiple categories. So if your posts are in multiple categories, you may not get the exact results you’re looking for with next/prev post I’ll show an example below.

If you’re fine going to the next or previous post even if the post is in multiple terms so that you may ‘jump’ to another term from which you came, the simply use WordPress’ get_adjacent_post()

But if your posts are in multiple terms and you want to stay in a specific term, you have to do a special query. The below query will pull the next and previous post in a post type within a specific taxonomy term. You can choose how many previous and next posts to pull by changing the limit and the get_post_siblings() number. This is a union query getting both results in one query.

<?php
function get_post_siblings( $limit = 1, $date = '' ) {
   global $wpdb, $post;
	
  // Custom Category
  $taxonomy = 'CUSTOM_TAXONOMY';
  // Custom Post Type
  $postType = 'CUSTOM_POSTTYPE';
  // SSpecific Term ID
  $term_id = '18';
  
  	if( empty( $date ) )
        $date = $post->post_date;

    $limit = absint( $limit );
    if( !$limit )
        return;

    $p = $wpdb->get_results( "
    (
        SELECT 
            p1.post_title, 
            p1.post_date,
            p1.ID
        FROM 
            $wpdb->posts p1 
		INNER JOIN wp_term_relationships 
		AS tr 
		ON p1.ID = tr.object_id 
		INNER JOIN wp_term_taxonomy tt 
		ON tr.term_taxonomy_id = tt.term_taxonomy_id 
        WHERE 
            p1.post_date < '$date' AND 
            p1.post_type = '$postType' AND 
            p1.post_status = 'publish' 
		AND tt.taxonomy = '$taxonomy' 
		AND tt.term_id 
		IN ($term_id) 
        ORDER by 
            p1.post_date DESC
        LIMIT 
            $limit
    )
    UNION 
    (
        SELECT 
            p2.post_title, 
            p2.post_date,
            p2.ID 
        FROM 
            $wpdb->posts p2 
		 INNER JOIN wp_term_relationships 
		AS tr 
		ON p2.ID = tr.object_id 
		INNER JOIN wp_term_taxonomy tt 
		ON tr.term_taxonomy_id = tt.term_taxonomy_id
        WHERE 
            p2.post_date > '$date' AND 
            p2.post_type = '$postType' AND 
            p2.post_status = 'publish' 
		AND tt.taxonomy = '$taxonomy' 
		AND tt.term_id 
		IN ($term_id)	
		ORDER by
            p2.post_date ASC
        LIMIT 
            $limit
    ) 
    ORDER by post_date ASC
    " );
    $i = 0;
    $adjacents = array();
    for( $c = count($p); $i < $c; $i++ )
        if( $i < $limit )
            $adjacents['prev'][] = $p[$i];
        else
            $adjacents['next'][] = $p[$i];

    return $adjacents;
}
?>

<div class="proj-pagi-prev">
	<?php 
    $siblings = get_post_siblings( 1 ); 
     $prev = $siblings['prev'];
    
    foreach( $prev as $p )
        $permalink = get_permalink( $p->ID );
            echo "<a href='" . $permalink . "'><span class='plain-text'>Previous</span> PROJECT</a>";
    ?>
</div><!-- proj pagi prev -->


<div class="proj-pagi-next">
	<?php 
    $next = $siblings['next'];
    
    foreach( $next as $p )
        $permalink = get_permalink( $p->ID );
             echo "<a href='" . $permalink . "'><span class='plain-text'>Next</span> PROJECT</a>";
    ?>
</div><!-- proj-pagi-next -->

If you want to break it out in two separate queries, you can use this one. Added to this one is a url variable (cat) which requests the passed url, which is the taxonomy term from where you came. You would of course have to add that to the link you came from in some fashion.

<?php
function get_post_siblings( $limit = 1, $date = '' ) {
   global $wpdb, $post;
       
  // Custom Category
  $taxonomy = 'CUSTOM_TAXONOMY';
  // Custom Post Type
  $postType = 'CUSTOM_POSTTYPE';
  // Get term id value from incoming URL
  $term_id = $_REQUEST['cat'];
  //echo $term_id;
  $terms = get_the_terms( $post->ID, $taxonomy );
  // echo $terms->term_id;
    if( empty( $date ) )
        $date = $post->post_date;
 
    $limit = absint( $limit );
    if( !$limit )
        return;
        
    // Get previous posts into $p
    $p = $wpdb->get_results( "
   (
       SELECT
           p1.post_title,
           p1.post_date,
           p1.ID
       FROM
           $wpdb->posts p1
                INNER JOIN wp_term_relationships
                AS tr
                ON p1.ID = tr.object_id
                INNER JOIN wp_term_taxonomy tt
                ON tr.term_taxonomy_id = tt.term_taxonomy_id
       WHERE
           p1.post_date < '$date' AND
           p1.post_type = '$postType' AND
           p1.post_status = 'publish'
                AND tt.taxonomy = '$taxonomy'
                AND tt.term_id
                IN ($term_id)
       ORDER by p1.post_date DESC
       LIMIT $limit
	   )
        " );
   
    // Get next posts into $n
    $n = $wpdb->get_results( "
       (
       SELECT
           p2.post_title,
           p2.post_date,
           p2.ID
       FROM
           $wpdb->posts p2
                 INNER JOIN wp_term_relationships
                AS tr
                ON p2.ID = tr.object_id
                INNER JOIN wp_term_taxonomy tt
                ON tr.term_taxonomy_id = tt.term_taxonomy_id
       WHERE
           p2.post_date > '$date' AND
           p2.post_type = '$postType' AND
           p2.post_status = 'publish'
                AND tt.taxonomy = '$taxonomy'
                AND tt.term_id
                IN ($term_id)  
       ORDER by post_date ASC
       LIMIT $limit
       )
       " );
   
    $adjacents = array();
    $adjacents['prev'] = array();
    $adjacents['next'] = array();
    
    for( $i=0; $i<count($p); $i++ ) {
        $adjacents['prev'][] = $p[$i];
    }
    
    for( $i=0; $i<count($n); $i++ ) {
        $adjacents['next'][] = $n[$i];
    }    
 
    return $adjacents;
}
 
?>
 
<div class="proj-pagi-prev">
      <?php
	   $siblings = get_post_siblings( 1 );
       $next = $siblings['next'];
   
    foreach( $next as $n )
        $term_id = $_REQUEST['cat'];
        $permalink = get_permalink( $n->ID );
        $link = $permalink . "?cat=" . $term_id;
		if($n != "") {
             echo "<a href='" . $link . "'><span class='plain-text'>Previous</span> PROJECT</a>";
		}
    ?>
</div><!-- proj pagi prev -->
 
 
<div class="proj-pagi-next">
   <?php
   
   
    $prev = $siblings['prev'];
   
    foreach( $prev as $p )
        $term_id = $_REQUEST['cat'];
        $permalink = get_permalink( $p->ID );
        $link = $permalink . "?cat=" . $term_id;
		if($p != "") {
            echo "<a href='" . $link . "'><span class='plain-text'>Next</span> PROJECT</a>";
		}
    ?>
       
</div><!-- proj-pagi-next -->

 

How to know which category or term you came from in WordPress

I’ve come across projects where the client wanted to do something base on where you came from. So this example will check to see which category or taxonomy term you came from and show a category or term menu based off where you came from.

First start with the link from a taxonomy page. We add the “?cat= and echo the term_id to the permalink url.

<?php 
$queried_object = get_queried_object(); 
$taxonomy = $queried_object->taxonomy;
?>

<li>
 <a href="<?php the_permalink();?>?cat=<?php echo $queried_object->term_id ?>">
   <?php echo $queried_object->name ?>
 </a>
</li>

Once we’ve clicked through, we get that id, find the parent term so we can list it’s name.

<?php
  // Get term id value from incoming URL.
  $taxonomy = 'portcats';
  $term_id = $_REQUEST['cat'];
  //get the parent
  $child_term = get_term( $term_id, $taxonomy );
  $parent_term = get_term( $child_term->parent, $taxonomy );

?>

<h1 class="page-title">
<?php 
$url = get_bloginfo('url');
?>
	<?php echo $parent_term->name ?> | 
    <a href="<?php echo $url . '/portfolio-categories/' . $parent_term->slug ?>/#viewall">
    	View All
    </a>
</h1>

 

ACF Post object on a Taxonomy Template

Getting the post object is easy on a page, but what if you want to put it on a taxonomy template? Add the term to the get_feild and voila!

<?php
	// which term?
	$obj = get_queried_object();
	// which field?
	$post_object = get_field('link_to_featured_project', $obj);
	
	if( $post_object ): 

	// override $post
	$post = $post_object;
	setup_postdata( $post ); 

	?>
    <div class="featured-post-link">
    	<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
    </div><!-- featured post link -->
    <?php wp_reset_postdata(); ?>
	<?php endif; ?>

 

Redirect wordpress user after log in

There are a couple ways to do this. Based off, “role” or “capability”. Often I use Just Tadlocks Members plugin to create custom roles for clients to not over burden them with every thing in the dashboard. Because of this, I think using “Capabilities” is a much better way of going about it.

Redirect user based off role … you can change “administrator” to be:
administrator
editor
subscriber
author
contributor

function my_login_redirect( $redirect_to, $request, $user ) {
	//is there a user to check?
	global $user;
	if ( isset( $user->roles ) && is_array( $user->roles ) ) {
		//check for admins
		if ( in_array( 'administrator', $user->roles ) ) {
			// redirect them to the default place
			return $redirect_to;
		} else {
			return home_url();
		}
	} else {
		return $redirect_to;
	}
}
add_filter( 'login_redirect', 'my_login_redirect', 10, 3 );

 

Redirect User based off Capability: List of Capabilities

Ex: If user can moderate comments, redirect to home…

function wps_login_redirect_contributors() {
  if ( current_user_can('moderate_comments') ){
     return home_url();
  }
}

add_filter('login_redirect', 'wps_login_redirect_contributors');

If user can not update core, redirect home…

function wps_login_redirect_contributors() {
  if ( !current_user_can('update_core') ){
     return home_url();
  }
}

add_filter('login_redirect', 'wps_login_redirect_contributors');

You get the idea…

Create a Custom WordPress Welcome message in the Dashboard

This function creates a custom welcome message in the wordpress dashboard.

/**
 * Hide default welcome dashboard message and and create a custom one
 *
 * @access      public
 * @since       1.0 
 * @return      void
*/
function rc_my_welcome_panel() {

	?>
<script type="text/javascript">
/* Hide default welcome message */
jQuery(document).ready( function($) 
{
	$('div.welcome-panel-content').hide();
});
</script>

	<div class="custom-welcome-panel-content">
	<h3><?php _e( 'Welcome to Paddlr.' ); ?></h3>
	<p class="about-description"><?php _e( 'Paddlr is a place to record all the rivers you\'ve done and create detailed river trips. You can keep a log of what you\'ve done and view others and their travels.' ); ?></p>
	<div class="welcome-panel-column-container">
	<div class="welcome-panel-column">
	
	</div>
	<div class="welcome-panel-column">
		<h4><?php _e( 'Next Steps' ); ?></h4>
		<ul>
		<?php if ( 'page' == get_option( 'show_on_front' ) && ! get_option( 'page_for_posts' ) ) : ?>
		
			
		<?php else : ?>
        <li><?php printf( '<a href="%s" class="welcome-icon welcome-write-blog">' . __( 'Add a River Trip.' ) . '</a>', admin_url( 'post-new.php?post_type=rivers' ) ); ?></li>
			<li><?php printf( '<a href="%s" class="welcome-icon welcome-add-page">' . __( 'Add an About page' ) . '</a>', admin_url( 'post-new.php?post_type=page' ) ); ?></li>
		<?php endif; ?>
			<li><?php printf( '<a href="%s" class="welcome-icon welcome-view-site">' . __( 'View your site' ) . '</a>', home_url( '/' ) ); ?></li>
		</ul>
	</div>
	
	</div>
	<!--<div class="">
	<h3><?php _e( 'If you need more space' ); ?></h3>
	<p class="about-description">Create a new paragraph!</p>
	<p>Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Donec ullamcorper nulla non metus auctor fringilla. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Nulla vitae elit libero, a pharetra augue. Nullam id dolor id nibh ultricies vehicula ut id elit. Etiam porta sem malesuada magna mollis euismod.
	
	Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Etiam porta sem malesuada magna mollis euismod. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.</p>
	</div>-->
	</div>

<?php
}

add_action( 'welcome_panel', 'rc_my_welcome_panel' );

 

Remove Personal Options from WordPress Profile Page

Remove personal options from WordPress Profile Page, like admin color scheme and others.

// removes the `profile.php` admin color scheme options
remove_action( 'admin_color_scheme_picker', 'admin_color_scheme_picker' );

if ( ! function_exists( 'cor_remove_personal_options' ) ) {
  /**
   * Removes the leftover 'Visual Editor', 'Keyboard Shortcuts' and 'Toolbar' options.
   */
  function cor_remove_personal_options( $subject ) {
    $subject = preg_replace( '#<h3>Personal Options</h3>.+?/table>#s', '', $subject, 1 );
    return $subject;
  }

  function cor_profile_subject_start() {
    ob_start( 'cor_remove_personal_options' );
  }

  function cor_profile_subject_end() {
    ob_end_flush();
  }
}
add_action( 'admin_head-profile.php', 'cor_profile_subject_start' );
add_action( 'admin_footer-profile.php', 'cor_profile_subject_end' );