Skip to content

Instantly share code, notes, and snippets.

@gschoppe
Created May 14, 2015 14:00
Show Gist options
  • Save gschoppe/3ccc31b2e7f596bca08c to your computer and use it in GitHub Desktop.
Save gschoppe/3ccc31b2e7f596bca08c to your computer and use it in GitHub Desktop.
Wordpress Board of Directors Custom Post Type, with custom profile pictures and meta information (http://www.gschoppe.com)
<?php
// archiveboard.php (companion to cpt-board.php)
// by Greg Schoppe (http://gschoppe.com)
// Licensed under GPL
// Renders archive page for board of directors custom post type
// Will need to be customized to match theme. This one is customized for the _TK bootstrap theme
get_header(); ?>
<?php // add the class "panel" below here to wrap the content-padder in Bootstrap style ;) ?>
<div class="content-padder">
<?php if ( have_posts() ) : ?>
<header class="col-xs-12">
<h1 class="page-title">
Board of Directors
</h1>
<?php
// Show an optional term description.
$term_description = term_description();
if ( ! empty( $term_description ) ) :
printf( '<div class="taxonomy-description">%s</div>', $term_description );
endif;
?>
</header><!-- .page-header -->
<?php /* Start the Loop */ ?>
<div class="board-members col-xs-12">
<?php while ( have_posts() ) : the_post(); ?>
<a name="<?=get_the_ID()?>"></a>
<div class="row">
<div class="col-sm-2">
<?php
if(get_post_meta(get_the_ID(), '_board_member_pic', true)) {
$imgID = get_post_meta(get_the_ID(), '_board_member_pic', true);
$imgDetails = wp_get_attachment_image_src( $imgID, "board-thumb" );
$imgSrc = isset($imgDetails[0])?$imgDetails[0]:"";
if($imgSrc) {
?>
<div class="board-image-wrap"><img src="<?=$imgSrc?>" alt="<?php the_title(); ?>"/></div>
<?php
}
}
?>
</div>
<article id="board-<?php the_ID(); ?>" class="board-member col-sm-10">
<header>
<h2 class="page-title"><?php the_title(); ?></h2>
<div class="board-meta">
<?php
if(get_post_meta(get_the_ID(), '_board_member_title', true)) {
?>
<span class="board-position"><?=get_post_meta(get_the_ID(), '_board_member_title', true).", "?></span>
<?php
}
if(get_post_meta(get_the_ID(), '_board_member_company', true)) {
?>
<span class="board-company" ><?=get_post_meta(get_the_ID(), '_board_member_company', true)?></span>
<?php } ?>
</div>
</header><!-- .entry-header -->
<div class="entry-content">
<?php the_content( __( 'Continue reading <span class="meta-nav">&rarr;</span>', '_tk' ) ); ?>
<?php
wp_link_pages( array(
'before' => '<div class="page-links">' . __( 'Pages:', '_tk' ),
'after' => '</div>',
) );
?>
</div><!-- .entry-content -->
</article><!-- #post-## -->
</div>
<?php endwhile; ?>
<?php _tk_content_nav( 'nav-below' ); ?>
</div>
<?php else : ?>
<?php get_template_part( 'no-results', 'archive' ); ?>
<?php endif; ?>
</div><!-- .content-padder -->
<?php get_footer(); ?>
<?php
// CPT Board
// by Greg Schoppe (http://gschoppe.com)
// Licensed under GPL
// creates board members post type, to render custom board of directors archive page
// usage: in functions.php, add require_once('cpt-board.php');
// then add both files to theme root directory
// add custom image size for board member images
add_action( 'after_setup_theme', function() {
add_image_size( 'board-thumb', 350, 350, true );
});
// register custom 'board' post type
add_action('init', function() {
register_post_type('board',
array(
'labels' => array(
'name' => __( 'Board Members' ),
'singular_name' => __( 'Board Member' ),
'add_new_item' => __('Add New Board Member'),
'edit_item' => __('Edit Member'),
'new_item' => __('New Member'),
'view_item' => __('View Member')
),
'public' => true,
'has_archive' => true,
'show_in_nav_menus' => true
)
);
});
// redirect single posts to the archive page, scrolled to current ID
add_action( 'template_redirect', function() {
if ( is_singular('board') ) {
global $post;
$redirectLink = get_post_type_archive_link( 'board' )."#".$post->ID;
wp_redirect( $redirectLink, 302 );
exit;
}
});
// turn off pagination for the archive page
add_action('parse_query', function($query) {
if (is_post_type_archive('board')) {
$query->set('nopaging', 1);
}
});
// change the post title to request the name of the board member
add_filter( 'enter_title_here', function( $title ) {
$screen = get_current_screen();
if ( 'board' == $screen->post_type ) {
$title = 'Enter Name Here';
}
return $title;
});
// add custom metabox for profile picture, name, title
add_action('add_meta_boxes', function() {
// Define the custom attachment for posts
add_meta_box(
'board_member_meta',
'Member Information',
'board_member_meta_box',
'board',
'normal',
'high'
);
});
// render metabox
function board_member_meta_box($post) {
// create security nonce
wp_nonce_field('wp_board_member_nonce', 'wp_board_member_nonce');
// get any existing values (if we're editing a board member)
$company = get_post_meta( $post->ID, '_board_member_company' , true );
$title = get_post_meta( $post->ID, '_board_member_title' , true );
$pic = get_post_meta( $post->ID, '_board_member_pic' , true );
$picsrc = wp_get_attachment_image_src( $pic, "thumbnail" );
?>
<table>
<tr>
<td><label for="board_member_company">Company: </label></td>
<td><input id="board_member_company" name="board_member_company" type="text" value="<?=$company?>"/></td>
</tr><tr>
<td><label for="board_member_title">Position: </label></td>
<td><input id="board_member_title" name="board_member_title" type="text" value="<?=$title?>"/></td>
</tr><tr>
<td><label for="board_member_pic">Picture: </label></td>
<td>
<input id="board_member_pic" name="board_member_pic" type="hidden" value="<?=$pic?>"/>
<img src="<?=$picsrc[0]?>" id="board_member_pic-vis" width="150" height="150" alt="preview" style="display: block; float: none;"/>
<input id="board_member_pic_button" class="button" name="board_member_pic_button" type="button" value="Choose Profile Image"/>
</td>
</tr>
</table>
<?php
// this is how we attach the media manager to the metabox
?>
<script type="text/javascript">
jQuery(document).ready(function($){
var _custom_media = true,
_orig_send_attachment = wp.media.editor.send.attachment;
$('#board_member_pic_button').click(function(e) {
var send_attachment_bkp = wp.media.editor.send.attachment;
var button = $(this);
// this is just my shorthand for the id for hidden field associated with the button. could be hard coded
var id = button.attr('id').replace('_button', '');
_custom_media = true;
wp.media.editor.send.attachment = function(props, attachment){
if ( _custom_media ) {
$("#"+id).val(attachment.id);
if(typeof attachment.sizes.thumbnail != "undefined" && typeof attachment.sizes.thumbnail.url != "undefined") {
var src = attachment.sizes.thumbnail.url;
} else {
var src = attachment.url;
// warning, in case the image is too small to generate a thumbnail
alert('WARNING: This image is below the recommended dimensions of 500x500 pixels.');
}
// this one is my shorthand for the preview element id. could be hard coded instead
$("#"+id+"-vis").attr('src', src);
} else {
return _orig_send_attachment.apply( this, [props, attachment] );
};
}
wp.media.editor.open(button);
return false;
});
$('.add_media').on('click', function(){
_custom_media = false;
});
});
</script>
<?php
}
// save values entered into metabox
add_action( 'save_post', function($post_id) {
// verify nonce
if(!isset($_POST['wp_board_member_nonce']) || !wp_verify_nonce($_POST['wp_board_member_nonce'], 'wp_board_member_nonce')) {
return;
}
// ignore autosaves (this is up to you. it might be good for the metabox to autosave with drafts, but it adds complexity)
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return;
}
// check post type
if(!(isset($_POST['post_type']) && 'board' == $_POST['post_type'])) {
return;
}
// check user priviledges
if (!current_user_can('edit_page', $post_id)) {
return;
}
// get field values
$company = (isset($_POST['board_member_company']))?sanitize_text_field($_POST['board_member_company']):"";
$title = (isset($_POST['board_member_title']))?sanitize_text_field($_POST['board_member_title']):"";
$pic = (isset($_POST['board_member_pic']))?sanitize_text_field($_POST['board_member_pic']):"";
// update the meta values
update_post_meta( $post_id, '_board_member_company', $company );
update_post_meta( $post_id, '_board_member_title', $title );
update_post_meta( $post_id, '_board_member_pic', $pic );
});
// move the editor below the custom meta box (this is a nasty hack, but seems to work ok)
add_action('add_meta_boxes', function() {
global $_wp_post_type_features;
//move editor
if (isset($_wp_post_type_features['board']['editor']) && $_wp_post_type_features['board']['editor']) {
// remove the editor from it's normal position
unset($_wp_post_type_features['board']['editor']);
// create a clone of it in a custom metabox
add_meta_box(
'bio_section',
__('Biography'),
function($post) {
echo '<div class="wp-editor-wrap">';
wp_editor($post->post_content, 'content', array('dfw' => true, 'tabindex' => 1) );
echo '</div>';
},
'board',
'normal',
'high'
);
}
// add styles to make the editor look normal
add_action( 'admin_head', function(){
?>
<style type="text/css">
.wp-editor-container{background-color:#fff;}
</style>
<?php
});
});
// Add CPT Archives to menu list (works for all CPTs, so should only happen once, site-wide)
if(!defined("ADD-CPT-ARCHIVES-TO-WP-MENUS")) {
define("ADD-CPT-ARCHIVES-TO-WP-MENUS", true);
add_action( 'admin_head-nav-menus.php', function() {
add_meta_box( 'add-cpt', __( 'CPT Archives' ), function() {
// get custom post types with archive support
$post_types = get_post_types( array( 'show_in_nav_menus' => true, 'has_archive' => true ), 'object' );
// hydrate the necessary properties for identification in the walker (read as: insert magic here)
foreach ( $post_types as &$post_type ) {
$post_type->classes = array();
$post_type->type = $post_type->name;
$post_type->object_id = $post_type->name;
$post_type->title = $post_type->labels->name . ' ' . __( 'Archive', 'default' );
$post_type->object = 'cpt-archive';
$post_type->menu_item_parent = 0;
$post_type->url = 0;
$post_type->target = 0;
$post_type->attr_title = 0;
$post_type->xfn = 0;
$post_type->db_id = 0;
}
// the native menu checklist
$walker = new Walker_Nav_Menu_Checklist( array() );
?>
<div id="cpt-archive" class="posttypediv">
<div id="tabs-panel-cpt-archive" class="tabs-panel tabs-panel-active">
<ul id="ctp-archive-checklist" class="categorychecklist form-no-clear">
<?php
echo walk_nav_menu_tree( array_map('wp_setup_nav_menu_item', $post_types), 0, (object) array( 'walker' => $walker) );
?>
</ul>
</div><!-- /.tabs-panel -->
<p class="button-controls">
<span class="add-to-menu">
<input type="submit"<?php disabled( $nav_menu_selected_id, 0 ); ?> class="button-secondary right submit-add-to-menu" value="<?php esc_attr_e('Add to Menu'); ?>" name="add-ctp-archive-menu-item" id="submit-cpt-archive" />
<span class="spinner"></span>
</span>
</p>
</div>
<?php
}, 'nav-menus', 'side', 'default' );
});
// take care of the URLs and active status for CPT Archives in menus
add_filter( 'wp_get_nav_menu_items', function( $items, $menu, $args ) {
// alter the URL for cpt-archive objects
foreach ( $items as &$item ) {
if ( $item->object != 'cpt-archive' ) continue;
$item->url = get_post_type_archive_link( $item->type );
// set current
if ( get_query_var( 'post_type' ) == $item->type ) {
$item->classes []= 'current-menu-item';
$item->current = true;
}
}
return $items;
}, 10, 3 );
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment