setup_actions(); } return self::$instance; } /** * A dummy constructor. * * @return GL_Featured_Items */ private function __construct() { } /** * Set up WordPress hooks */ function setup_actions() { add_action( 'init', array( $this, 'setup_post_type' ) ); add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) ); add_filter( 'wp_insert_post_data', array( $this, 'post_data' ), null, 2 ); add_filter( 'post_updated_messages', array( $this, 'filter_updated_messages' ) ); add_filter( 'manage_edit-' . $this->slug . '_columns', array( $this, 'add_columns' ) ); add_action( 'manage_' . $this->slug . '_posts_custom_column', array( $this, 'render_columns' ), null, 2 ); add_action( 'add_meta_boxes', array( $this, 'add_meta_boxes' ) ); add_action( 'wp_ajax_feature-grid-search', array( $this, 'ajax_feature_grid_search' ) ); add_action( 'wp_ajax_feature_edit_fields', array( $this, 'ajax_feature_edit_fields' ) ); } /** * Set up Post Type */ function setup_post_type() { register_post_type( $this->slug, array( 'labels' => array( 'name' => 'Feature Grids', 'singular_name' => 'Feature Grid', 'menu_name' => 'Feature Grids', 'all_items' => 'All Grids', 'add_new_item' => 'Add New Grid', 'edit_item' => 'Edit Grid', 'view_item' => 'View Grid', 'search_items' => 'Search Grids', 'not_found' => 'No grids found', 'not_found_in_trash' => 'No grids found in trash' ), 'description' => 'A single feature grid is used on the home page to display several items in a grid', 'public' => false, 'show_ui' => true, 'menu_icon' => 'dashicons-slides', 'supports' => false ) ); } function add_meta_boxes() { $this->features = new Tenup_Featured_Item( get_the_ID() ); foreach ( array( 'Secondary', 'Feature', 'Tertiary' ) as $index ) { add_meta_box( 'featured-' . sanitize_key( $index ), $index, array( $this, 'feature_meta_box' ), $this->slug, 'normal', 'high', array( 'index' => $index ) ); } } /** * Display the meta box for features * * @param $post * @param $metabox */ function feature_meta_box( $post, $metabox ) { $index = $metabox['args']['index']; $index_key = sanitize_key( $index ); $post_id = $this->features->get_position_field( 'post_id', $index_key ); ?>
get_feature_edit_fields( $index ); ?>
ID, 'gl_feature_editor_nonce' ); } /** * Get the fields that can be edited. * In a separate function so it can be ajax'ed in */ function get_feature_edit_fields( $position_index, $post_id_override = 0 ) { $index_key = sanitize_key( $position_index ); if ( empty( $post_id_override ) ) { $post_id = $this->features->get_position_field( 'post_id', $index_key ); } else { $post_id = $post_id_override; } $saved_data = $this->features->get_position_data( $index_key ); $data = wp_parse_args( $saved_data, array( 'display' => 'image', 'quote' => '', 'citation' => '', 'title' => get_the_title( $post_id ), 'img_id' => get_post_thumbnail_id( $post_id ), ), $saved_data ); ob_start(); ?>
data-tab="image"> data-tab="quote">
features->get_position_field( 'img_id', $index_key ); if ( ! empty( $img_id ) ) { echo wp_get_attachment_image( $img_id, 'bitty-book' ); } else { echo 'No featured image'; } ?>

slug ) { return; } wp_enqueue_style( 'select2', get_template_directory_uri() . '/assets/js/vendor/select2/select2.css' ); } /** * Hook in just before saving data to the database so we can manipulate the post_content * * @param $data array * @param $postarr array * * @return array */ function post_data( $data, $postarr ) { if ( get_post_type() !== $this->slug ) { return $data; } if ( ! wp_verify_nonce( $_POST['gl_feature_editor_nonce'], 'feature-edit-' . get_the_ID() ) ) { return $data; }; // set post_content to be some JSON from $_POST if ( isset( $_POST['gl-feature'] ) ) { $escaped_data = $_POST['gl-feature']; $data['post_content'] = wp_slash( json_encode( $escaped_data ) ); // note wp_insert_post does sanitization } return $data; } /** * Filter updated messages * @param $messages * * @return mixed */ function filter_updated_messages( $messages ) { global $post; if ( $this->slug !== get_post_type( $post ) ) { return $messages; } $preview_url = esc_url( add_query_arg( 'preview', $post->ID, home_url() ) ); $messages['post'] = array( 0 => '', // Unused. Messages start at index 1. 1 => sprintf( 'Grid updated. View homepage with this grid', $preview_url ), 2 => __( 'Custom field updated.' ), 3 => __( 'Custom field deleted.' ), 4 => 'Grid updated.', 5 => isset( $_GET['revision'] ) ? sprintf( 'Grid restored to revision from %s', wp_post_revision_title( (int) $_GET['revision'], false ) ) : false, 6 => sprintf( 'Grid published. View homepage with this grid', $preview_url ), 7 => __( 'Grid saved.' ), 8 => sprintf( 'Grid submitted. Preview homepage with this grid', $preview_url ), 9 => sprintf( 'Grid scheduled for: %1$s. Preview homepage with this grid', date_i18n( __( 'M j, Y @ G:i' ), strtotime( $post->post_date ) ), $preview_url ), 10 => sprintf( 'Post draft updated. Preview homepage with this grid', $preview_url ), ); return $messages; } /** * Filter the columns on the edit post screen * * @param $columns array * * @return array */ function add_columns( $columns ) { $columns = array( 'cb' => '', 'gl-preview' => 'Preview', 'date' => _x( 'Date', 'column name' ), ); return $columns; } /** * Display our custom column's content * * @param $column_name string * @param $post_id integer */ function render_columns( $column_name, $post_id ) { if ( $column_name !== 'gl-preview' ) { return; } // Get all the images for the given post ID $feature = new Tenup_Featured_Item( $post_id ); if ( $feature->featured_items ) { $image_ids = wp_list_pluck( $feature->featured_items, 'img_id' ); foreach ( $image_ids as $img_id ) { if ( empty( $img_id ) ) { echo '[no preview img]'; } echo wp_get_attachment_image( $img_id, 'bitty-book' ); } } /** * Steal the bit from wp-posts-list-table for post locking */ $lock_holder = wp_check_post_lock( get_the_ID() ); if ( $lock_holder ) { $lock_holder = get_userdata( $lock_holder ); } if ( current_user_can( 'edit_post', get_the_ID() ) && get_post_status( get_the_ID() ) != 'trash' ) { if ( $lock_holder ) { $locked_avatar = get_avatar( $lock_holder->ID, 18 ); $locked_text = esc_html( sprintf( __( '%s is currently editing' ), $lock_holder->display_name ) ); } else { $locked_avatar = $locked_text = ''; } echo '
' . $locked_avatar . ' ' . $locked_text . "
\n"; } /** * Steal the bit from wp-posts-list-table for post status */ if ( get_post_status( get_the_ID() ) === 'draft' ) { echo ' — Draft'; } if ( get_post_status( get_the_ID() ) === 'future' ) { echo ' — Scheduled'; } if ( get_post_status( get_the_ID() ) === 'pending' ) { echo ' — Pending Review'; } $this->row_actions( $post_id ); } /** * Echo the row actions for this CPT. * * This code is taken from WP_List_Table. Unfortunately WP only generates the * $actions array when it's dealing with the 'title' column since we removed the * title column, we need to generate our own $actions array, pass it to the * globalized $wp_list_table object's row_actions method. It's ridiculous. * * @param $post_id */ private function row_actions( $post_id ) { global $wp_list_table; $actions = array(); $post = get_post( $post_id ); $can_edit_post = current_user_can( 'edit_post', $post_id ); $post_type_object = get_post_type_object( $post->post_type ); $preview_url = esc_url( add_query_arg( 'preview', $post_id, home_url() ) ); if ( $can_edit_post && 'trash' != $post->post_status ) { $actions['edit'] = '' . __( 'Edit' ) . ''; $actions['inline hide-if-no-js'] = '' . __( 'Quick Edit' ) . ''; } if ( current_user_can( 'delete_post', $post->ID ) ) { if ( 'trash' == $post->post_status ) $actions['untrash'] = "ID ) ), 'untrash-post_' . $post->ID ) . "'>" . __( 'Restore' ) . ""; elseif ( EMPTY_TRASH_DAYS ) $actions['trash'] = "" . __( 'Trash' ) . ""; if ( 'trash' == $post->post_status || ! EMPTY_TRASH_DAYS ) $actions['delete'] = "" . __( 'Delete Permanently' ) . ""; } if ( in_array( $post->post_status, array( 'pending', 'draft', 'future' ) ) ) { if ( $can_edit_post ) $actions['view'] = '' . __( 'Preview' ) . ''; } elseif ( 'trash' != $post->post_status ) { $actions['view'] = '' . __( 'View' ) . ''; } $actions = apply_filters( is_post_type_hierarchical( $post->post_type ) ? 'page_row_actions' : 'post_row_actions', $actions, $post ); echo $wp_list_table->row_actions( $actions ); } public static function ajax_feature_grid_search() { $posts = new WP_Query( array( 'posts_per_page' => absint( $_GET['posts_per_page'] ), 'post_type' => array( GL_CPT_Library::CPT_SLUG, 'post', 'page' ), 'paged' => absint( $_GET['paged'] ), 's' => sanitize_text_field( $_GET['s'] ), 'update_term_cache' => false, 'update_post_meta_cache' => false, ) ); $results = array(); if ( $posts->have_posts() ) { while ( $posts->have_posts() ) { $posts->the_post(); $results[] = array( 'id' => get_the_ID(), 'text' => get_post_field( 'post_title', get_the_ID(), 'display' ) ); } } $response = array( 'results' => $results, 'more' => $posts->max_num_pages > $_GET['paged'] ); wp_send_json( $response ); } /** * Get the default field data so it can be ajax loaded */ public static function ajax_feature_edit_fields() { $index = $_GET['index']; $postid = $_GET['postid']; $default_response = array( 'display' => 'image', 'title' => '', 'img_id' => 0, 'img_preview' => '', 'quote' => '', 'citation' => '' ); if ( empty( $index ) || empty( $postid ) ) { wp_send_json_error( $default_response ); } $response = wp_parse_args( array( 'title' => utf8_encode( get_post_field( 'post_title', $postid, 'display' ) ), 'img_id' => get_post_thumbnail_id( $postid ), 'img_preview' => utf8_encode( get_the_post_thumbnail( $postid, 'bitty-book' ) ), ), $default_response ); wp_send_json_success( $response ); } } /** * Gets the main GL_Featured_Items Instance * * Calling this function places into motion the main functions of the class, but can also be utilized to get properties * and run methods of the class. * * @return GL_Featured_Items */ function get_gl_featured_items() { return GL_Featured_Items::get_instance(); } add_action( 'after_setup_theme', 'get_gl_featured_items' ); /** * Handle getting information related to featured items. Designed to handle one * post of the featured items CPT. * * Class TenupFeaturedItem */ class Tenup_Featured_Item { /** * Post object associated with this featured item * @var WP_Post */ var $item_post = ''; /** * featured item array * @var array */ var $featured_items = ''; /** * Constructor * * @param $post WP_Post or Post ID */ function __construct( $post ) { $this->item_post = get_post( $post ); $this->featured_items = $this->_get_data(); } /** * Get all the featured item data for the post * @return array */ private function _get_data() { if ( $this->item_post->post_content ) { return stripslashes_deep( json_decode( $this->item_post->post_content, true ) ); } else { return array(); } } /** * Get an array of positions. For easy use in iterators */ public function get_positions() { return array( 'Feature', 'Secondary', 'Tertiary' ); } /** * Get all the data for a given position * * @param $position_index mixed * @param $placeholder_img_in_admin bool display a placeholder image in admin contexts * * @return array */ public function get_position_data( $position_index, $placeholder_img_in_admin = true ) { if ( empty( $this->featured_items[sanitize_key( $position_index )] ) ) { $position_data = array(); } else { $position_data = $this->featured_items[sanitize_key( $position_index )]; } return $position_data; } /** * Get the data from a specific field for a specific index * * @param $position_field * @param $position_index * @param $placeholder_img_in_admin bool display a placeholder image in admin contexts * * @return mixed */ public function get_position_field( $position_field, $position_index, $placeholder_img_in_admin = true ) { $data = $this->get_position_data( $position_index, $placeholder_img_in_admin ); if ( ! empty( $data[sanitize_key( $position_field )] ) ) { return wp_kses_post( wptexturize( stripslashes( $data[sanitize_key( $position_field )] ) ) ); } else { return ''; } } }