I have created a custom post type for cars which I have bootstraped off this tutorial. I am having a problem where I am getting 404 returned instead of archive-car.php and single-car.php. I have also tried to add the plural versions to the template names, however, no success. What could be wrong? Am I missing something?
<?php
if( ! function_exists( 'quote_create_post_type' ) ) :
function quote_create_post_type() {
$labels = array(
'name' => 'Cars',
'singular_name' => 'Car',
'add_new' => 'Add Car',
'all_items' => 'All Cars',
'add_new_item' => 'Add Car',
'edit_item' => 'Edit car',
'new_item' => 'New car',
'view_item' => 'View car',
'search_items' => 'Search cars',
'not_found' => 'No cars found',
'not_found_in_trash' => 'No cars found in trash',
'parent_item_colon' => 'Parent car'
//'menu_name' => default to 'name'
);
$args = array(
'labels' => $labels,
'public' => true,
'has_archive' => true,
'publicly_queryable' => true,
'query_var' => true,
'rewrite' => true,
'capability_type' => 'post',
'hierarchical' => false,
'supports' => array(
'title',
'editor',
'excerpt',
'thumbnail',
//'author',
//'trackbacks',
//'custom-fields',
//'comments',
'revisions',
//'page-attributes', // (menu order, hierarchical must be true to show Parent option)
//'post-formats',
),
'menu_position' => 5,
'exclude_from_search' => true,
'register_meta_box_cb' => 'quote_add_post_type_metabox'
);
register_post_type( 'car', $args );
//flush_rewrite_rules();
register_taxonomy( 'quote_category', // register custom taxonomy - category
'car',
array(
'hierarchical' => true,
'labels' => array(
'name' => 'Brands',
'singular_name' => 'Brand',
)
)
);
}
add_action( 'init', 'quote_create_post_type' );
function quote_add_post_type_metabox() { // add the meta box
add_meta_box( 'quote_metabox', 'Car Details', 'quote_metabox', 'car', 'normal' );
}
function quote_metabox() {
global $post;
// Noncename needed to verify where the data originated
echo '<input type="hidden" name="quote_post_noncename" value="' . wp_create_nonce( plugin_basename(__FILE__) ) . '" />';
// Get the data if its already been entered
$quote_post_name = get_post_meta($post->ID, '_quote_post_name', true);
$quote_post_desc = get_post_meta($post->ID, '_quote_post_desc', true);
// Echo out the field
?>
<table class="form-table">
<tr>
<th>
<label>Brand</label>
</th>
<td>
<input type="text" name="quote_post_name" value="<?php echo $quote_post_name; ?>">
<!-- classes: .small-text .regular-text .large-text -->
</td>
</tr>
<tr>
<th>
<label>Description</label>
</th>
<td>
<textarea name="quote_post_desc" class="large-text"><?php echo $quote_post_desc; ?></textarea>
</td>
</tr>
</table>
<?php
}
function quote_post_save_meta( $post_id, $post ) { // save the data
/*
* We need to verify this came from our screen and with proper authorization,
* because the save_post action can be triggered at other times.
*/
if ( ! isset( $_POST['quote_post_noncename'] ) ) { // Check if our nonce is set.
return;
}
if( !wp_verify_nonce( $_POST['quote_post_noncename'], plugin_basename(__FILE__) ) ) { // Verify that the nonce is valid.
return $post->ID;
}
// verify this came from the our screen and with proper authorization,
// because save_post can be triggered at other times
if( !wp_verify_nonce( $_POST['quote_post_noncename'], plugin_basename(__FILE__) ) ) {
return $post->ID;
}
// is the user allowed to edit the post or page?
if( ! current_user_can( 'edit_post', $post->ID )){
return $post->ID;
}
// ok, we're authenticated: we need to find and save the data
// we'll put it into an array to make it easier to loop though
$quote_post_meta['_quote_post_name'] = $_POST['quote_post_name'];
$quote_post_meta['_quote_post_desc'] = $_POST['quote_post_desc'];
// add values as custom fields
foreach( $quote_post_meta as $key => $value ) { // cycle through the $quote_post_meta array
// if( $post->post_type == 'revision' ) return; // don't store custom data twice
$value = implode(',', (array)$value); // if $value is an array, make it a CSV (unlikely)
if( get_post_meta( $post->ID, $key, FALSE ) ) { // if the custom field already has a value
update_post_meta($post->ID, $key, $value);
} else { // if the custom field doesn't have a value
add_post_meta( $post->ID, $key, $value );
}
if( !$value ) { // delete if blank
delete_post_meta( $post->ID, $key );
}
}
}
add_action( 'save_post', 'quote_post_save_meta', 1, 2 ); // save the custom fields
endif; // end of function_exists()
if( ! function_exists( 'view_quotes_posts' ) ) : // output
function view_quotes_posts($do_shortcode = 1, $strip_shortcodes = 0 ) {
$args = array(
'posts_per_page' => 10,
'offset' => 0,
//'category' => ,
'orderby' => 'menu_order, post_title', // post_date, rand
'order' => 'DESC',
//'include' => ,
//'exclude' => ,
//'meta_key' => ,
//'meta_value' => ,
'post_type' => 'car',
//'post_mime_type' => ,
//'post_parent' => ,
'post_status' => 'publish',
'suppress_filters' => true
);
$posts = get_posts( $args );
$html = '';
foreach ( $posts as $post ) {
$meta_name = get_post_meta( $post->ID, '_quote_post_name', true );
$meta_desc = get_post_meta( $post->ID, '_quote_post_desc', true );
$img = get_the_post_thumbnail( $post->ID, 'medium' );
if( empty( $img ) ) {
$img = '<img src="'.plugins_url( '/img/default.png', __FILE__ ).'">';
}
if( has_post_thumbnail( $post->ID ) ) {
$img = wp_get_attachment_image_src( get_post_thumbnail_id( $post->ID ), 'thumbnail' );
$img_url = $img[0];
//the_post_thumbnail( 'thumbnail' ); /* thumbnail, medium, large, full, thumb-100, thumb-200, thumb-400, array(100,100) */
}
$content = $post->post_content;
if( $do_shortcode == 1 ) {
$content = do_shortcode( $content );
}
if( $strip_shortcodes == 1 ) {
$content = strip_shortcodes( $content );
}
$content = wp_trim_words( $content, 30, '...');
$content = wpautop( $content );
$html .= '
<div>
<h3>'.$post->post_title.'</h3>
<div>
<p>Name: '.$meta_name.'</p>
<p>Description: '.$meta_desc.'</p>
</div>
<div>'.$img.'</div>
<div>'.$content.'</div>
</div>
';
}
$html = '<div class="wrapper">'.$html.'</div>';
return $html;
}
endif; // end of function_exists()
?>
Further Info
All I am doing is extending the TwentyFifteen theme.
If I had to put money on this, I would say that you have not updated your permalinks! Simply go to Settings >> Permalinks >> Post Name.
The codex provides a little more information:
Note: In some cases, the permalink structure must be updated in order for the new template files to be accessed when viewing posts of a custom post type. To do this, go to Administration Panels > Settings > Permalinks, change the permalink structure to a different structure, save the changes, and change it back to the desired structure.
Related
I have built a WooCommerce website for a client with a "Latest Products" page. Due to the competitive nature of the client's industry, the client wants to be able to select certain products to NOT appear amongst the Latest Products.
For this, I have added a custom "Hide from Latest Products" checkbox to the product editor with this code:
add_action('add_meta_boxes', 'gd_add_product_extra_options_metabox');
function gd_add_product_extra_options_metabox(){
add_meta_box("product_extra_options_meta", "Extra Options", "gd_product_extra_options_metabox", "product", "side", "high");
}
// ADD CUSTOM FIELDS //
function gd_product_extra_options_metabox(){
global $post;
// Nonce field to validate form request came from current site
wp_nonce_field( basename( __FILE__ ), 'product_fields' );
// Get the field data if it's already been entered
$hide_from_latest = get_post_meta( $post->ID, 'hide_from_latest', true );
if($hide_from_latest == '1'){$checked = ' checked';}else{$checked = '';}
// Output the field
echo '<p><input type="checkbox" name="hide_from_latest" value="1"' . $checked . '> Hide from Latest Products</p>';
}
And so on and so forth with the saving code, etc. The checkbox appears to work perfectly.
The problem though, is in writing a custom product query to fetch all of the latest products for which this checkbox is NOT checked.
For testing, I have checked and saved the "Hide" option for only 1 product.
I have my query as follows:
$products = new WP_Query( array (
'post_type' => 'product',
'post_status' => 'publish',
'posts_per_page' => '100',
'order_by' => 'date',
'order' => 'ASC',
'meta_query' => array(
array(
'key' => 'hide_from_latest',
'value' => '1',
'compare' => 'NOT LIKE'
),
)
This gives me a very empty screen with "There is no results."
If, however, I change the meta_query to:
'meta_query' => array(
array(
'key' => 'hide_from_latest',
'value' => '1',
'compare' => 'LIKE'
),
)
Then it fetches and displays the 1 single product that I have checked and saved the option for.
I have tried various other options such as using "=" and "!=" for 'compare', I've tried changing the value of the checkbox to "on" and then having 'value' => 'on' in the meta_query, etc. The results are always the same.
Where have I gone wrong?
EDIT:
Here is my full code:
// ADD CUSTOM OPTIONS TO WOOCOMMERCE PRODUCTS //
add_action('add_meta_boxes', 'gd_add_product_extra_options_metabox');
function gd_add_product_extra_options_metabox(){
add_meta_box("product_extra_options_meta", "Extra Options", "gd_product_extra_options_metabox", "product", "side", "high");
}
// ADD CUSTOM FIELDS //
function gd_product_extra_options_metabox(){
global $post;
// Nonce field to validate form request came from current site
wp_nonce_field( basename( __FILE__ ), 'notice_fields' );
// Get the field data if it's already been entered
$hide_from_latest = get_post_meta( $post->ID, 'hide_from_latest', true );
if($hide_from_latest == '1'){$checked = ' checked';}else{$checked = '';}
// Output the field
echo '<p><input type="checkbox" name="hide_from_latest" value="1"' . $checked . '> Hide from Latest Products</p>';
}
// SAVE METABOX DATA //
function gd_save_product_extra_options_metabox( $post_id, $post ) {
// Return if the user doesn't have edit permissions.
if ( ! current_user_can( 'edit_post', $post_id ) ) {
return $post_id;
}
// Verify this came from the our screen and with proper authorization,
// because save_post can be triggered at other times.
if ( !wp_verify_nonce($_POST['notice_fields'], basename(__FILE__)) ) {
return $post_id;
}
// Now that we're authenticated, time to save the data.
// This sanitizes the data from the field and saves it into an array $product_meta.
$product_meta['hide_from_latest'] = esc_textarea( $_POST['hide_from_latest'] );
// Cycle through the $notice_meta array.
foreach ( $product_meta as $key => $value ) :
// Don't store custom data twice
if ( 'revision' === $post->post_type ) {
return;
}
if ( get_post_meta( $post_id, $key, false ) ) {
// If the custom field already has a value, update it.
update_post_meta( $post_id, $key, $value );
} else {
// If the custom field doesn't have a value, add it.
add_post_meta( $post_id, $key, $value);
}
if ( ! $value ) {
// Delete the meta key if there's no value
delete_post_meta( $post_id, $key );
}
endforeach;
}
add_action( 'save_post', 'gd_save_product_extra_options_metabox', 1, 2 );
if( ! function_exists('latest_products_censored') ) {
// Add Shortcode
function latest_products_censored( $atts ) {
global $woocommerce_loop;
// Attributes
$atts = shortcode_atts(
array(
'columns' => '4',
'limit' => '100'
),
$atts, 'products_test'
);
$woocommerce_loop['columns'] = $atts['columns'];
// The WP_Query
$products = new WP_Query( array (
'post_type' => 'product',
'post_status' => 'publish',
'posts_per_page' => $atts['limit'],
'order_by' => 'date',
'order' => 'ASC',
'meta_query' => array(
array(
'key' => 'hide_from_latest',
'value' => '1',
'compare' => 'NOT LIKE'
),
)
));
ob_start();
if ( $products->have_posts() ) { ?>
<?php woocommerce_product_loop_start(); ?>
<?php while ( $products->have_posts() ) : $products->the_post(); ?>
<?php wc_get_template_part( 'content', 'product' ); ?>
<?php endwhile; // end of the loop. ?>
<?php woocommerce_product_loop_end(); ?>
<?php
} else {
do_action( "woocommerce_shortcode_products_loop_no_results", $atts );
echo "<p>There is no results.</p>";
}
woocommerce_reset_loop();
wp_reset_postdata();
return '<div class="woocommerce columns-' . $atts['columns'] . '">' . ob_get_clean() . '</div>';
}
add_shortcode( 'latest_products_censored', 'latest_products_censored' );
}
After a bit more digging in the Wordpress Codex, I have found the answer!
The meta_query needs to be:
'meta_query' => array(
array(
'key' => 'hide_from_latest',
'value' => '1',
'compare' => 'NOT EXISTS'
),
)
I have just given that a go and it is now working perfectly! :-)
Thanks to these two posts I have come up with this solution for adding multiple tabs to Woocommerce product detail page.
Editing Custom product tab content in Woocommerce Admin product pages
Adding multiple tabs to WooCommerce single product pages
However, I am still having trouble saving the data and can't figure out how to make each meta_box save. I thought of a foreach statement but I'm not that well versed in PHP to know how the syntax is.
Here is my code. I have 6 tabs I added which show up on the page, and the meta boxes show up in the admin panel but they won't save any input. I only have one that is trying to save right now and I feel like the problem is in the save function.
add_action( 'add_meta_boxes', 'create_custom_meta_box' );
if ( ! function_exists( 'create_custom_meta_box' ) )
{
function create_custom_meta_box()
{
add_meta_box(
'custom_product_cost_field',
__( 'Cost and Performance Tab', 'woocommerce' ),
'add_custom_content_meta_box',
'product',
'normal',
'high'
);
add_meta_box(
'custom_product_environment_field',
__( 'Environment Tab', 'woocommerce' ),
'add_custom_content_meta_box',
'product',
'normal',
'high'
);
add_meta_box(
'custom_product_dilution_field',
__( 'Dilution Directions Tab', 'woocommerce' ),
'add_custom_content_meta_box',
'product',
'normal',
'high'
);
add_meta_box(
'custom_product_packaging_field',
__( 'Packaging and Handling', 'woocommerce' ),
'add_custom_content_meta_box',
'product',
'normal',
'high'
);
add_meta_box(
'custom_product_application_field',
__( 'Use and Application Tab', 'woocommerce' ),
'add_custom_content_meta_box',
'product',
'normal',
'high'
);
add_meta_box(
'custom_product_specification_field',
__( 'Product Specification Tab', 'woocommerce' ),
'add_custom_content_meta_box',
'product',
'normal',
'high'
);
}
}
// Custom metabox content in admin product pages
if ( ! function_exists( 'add_custom_content_meta_box' ) )
{
function add_custom_content_meta_box( $post )
{
$value = get_post_meta( $post->ID, 'cost_performance_tab', true ) ? get_post_meta( $post->ID, 'cost_performance_tab', true ) : '';
wp_editor( $value, 'custom_cost_performance_tab', array( 'editor_height' => 100 ) );
echo '<input type="hidden" name="custom_product_field_nonce" value="' . wp_create_nonce() . '">';
}
}
//Save the data of the Meta field
add_action( 'save_post', 'save_custom_content_meta_box', 10, 1 );
if ( ! function_exists( 'save_custom_content_meta_box' ) )
{
function save_custom_content_meta_box( $post_id ) {
// We need to verify this with the proper authorization (security stuff).
// Check if our nonce is set.
if ( ! isset( $_POST[ 'custom_product_field_nonce' ] ) ) {
return $post_id;
}
$nonce = $_REQUEST[ 'custom_product_field_nonce' ];
//Verify that the nonce is valid.
if ( ! wp_verify_nonce( $nonce ) ) {
return $post_id;
}
// If this is an autosave, our form has not been submitted, so we don't want to do anything.
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return $post_id;
}
// Check the user's permissions.
if ( 'page' == $_POST[ 'post_type' ] ) {
if ( ! current_user_can( 'edit_page', $post_id ) ) {
return $post_id;
}
} else {
if ( ! current_user_can( 'edit_post', $post_id ) ) {
return $post_id;
}
}
// --- Its safe for us to save the data ! --- //
// Sanitize user input and update the meta field in the database.
update_post_meta( $post_id, 'cost_performance_tab', wp_kses_post($_POST[ 'custom_cost_performance_tab' ]) );
}
}
add_filter( 'woocommerce_product_tabs', 'woo_custom_product_tabs' );
function woo_custom_product_tabs( $tabs ) {
// 1) Removing tabs
unset( $tabs['description'] ); // Remove the description tab
// unset( $tabs['reviews'] ); // Remove the reviews tab
unset( $tabs['additional_information'] ); // Remove the additional information tab
// 2 Adding new tabs and set the right order
//Attribute Cost and Performance tab
$tabs['cost_performance_tab'] = array(
'title' => __( 'Cost + Performance', 'woocommerce' ),
'priority' => 100,
'callback' => 'woo_cost_performance_tab_content'
);
// Adds the environment tab
$tabs['environment_tab'] = array(
'title' => __( 'Environment', 'woocommerce' ),
'priority' => 110,
'callback' => 'woo_environment_tab_content'
);
// Adds the dilution tab
$tabs['dilution_tab'] = array(
'title' => __( 'Suggested Dilution Directions', 'woocommerce' ),
'priority' => 120,
'callback' => 'woo_dilution_tab_content'
);
// Adds the packaging tab
$tabs['packaging_tab'] = array(
'title' => __( 'Packaging + Handling', 'woocommerce' ),
'priority' => 120,
'callback' => 'woo_packaging_tab_content'
);
// Adds the application tab
$tabs['application_tab'] = array(
'title' => __( 'Use + Application', 'woocommerce' ),
'priority' => 120,
'callback' => 'woo_application_tab_content'
);
// Adds the application tab
$tabs['specification_tab'] = array(
'title' => __( 'Product Specification', 'woocommerce' ),
'priority' => 120,
'callback' => 'woo_specification_tab_content'
);
return $tabs;
}
function woo_cost_performance_tab_content() {
// The new tab content
$prod_id = get_the_ID();
echo'<div><p>'.get_post_meta( get_the_ID(), 'cost_performance_tab' ,true ).'</p></div>';
}
function woo_environment_tab_content() {
// The new tab content
$prod_id = get_the_ID();
echo'<div><p>'.get_post_meta( get_the_ID(), 'environment_tab' ,true ).'</p></div>';
}
function woo_dilution_tab_content() {
// The new tab content
$prod_id = get_the_ID();
echo'<div><p>'.get_post_meta( get_the_ID(), 'dilution_tab' ,true ).'</p></div>';
}
function woo_packaging_tab_content() {
// The new tab content
$prod_id = get_the_ID();
echo'<div><p>'.get_post_meta( get_the_ID(), 'packaging_tab' ,true ).'</p></div>';
}
function woo_application_tab_content() {
// The new tab content
$prod_id = get_the_ID();
echo'<div><p>'.get_post_meta( get_the_ID(), 'application_tab' ,true ).'</p></div>';
}
function woo_specification_tab_content() {
// The new tab content
$prod_id = get_the_ID();
echo'<div><p>'.get_post_meta( get_the_ID(), 'specification_tab' ,true ).'</p></div>';
}
You don't need 6 metaboxes in admin product edit pages and there is a lot of mistakes… Try the following instead:
// Add a custom metabox
add_action( 'add_meta_boxes', 'additional_product_tabs_metabox' );
function additional_product_tabs_metabox()
{
add_meta_box(
'add_product_metabox_additional_tabs',
__( 'Additional product Tabs', 'woocommerce' ),
'additional_product_tabs_metabox_content',
'product',
'normal',
'high'
);
}
// Add custom metabox content
function additional_product_tabs_metabox_content( $post )
{
// Cost and Performance
echo '<h4>' . __( 'Cost and Performance', 'woocommerce' ) . '</h4>';
$value = get_post_meta( $post->ID, '_cost_performance', true );
wp_editor( $value, '_cost_performance', array( 'editor_height' => 100 ) );
// Environment
echo '<br><hr><h4>' . __( 'Environment', 'woocommerce' ) . '</h4>';
$value = get_post_meta( $post->ID, '_environment', true );
wp_editor( $value, '_environment', array( 'editor_height' => 100 ) );
// Dilution Directions
echo '<br><hr><h4>' . __( 'Dilution Directions', 'woocommerce' ) . '</h4>';
$value = get_post_meta( $post->ID, '_dilution_directions', true );
wp_editor( $value, '_dilution_directions', array( 'editor_height' => 100 ) );
// Environment
echo '<br><hr><h4>' . __( 'Packaging and Handling', 'woocommerce' ) . '</h4>';
$value = get_post_meta( $post->ID, '_packaging_and_handling', true );
wp_editor( $value, '_packaging_and_handling', array( 'editor_height' => 100 ) );
// Use and Application
echo '<br><hr><h4>' . __( 'Use and Application', 'woocommerce' ) . '</h4>';
$value = get_post_meta( $post->ID, '_use_and_application', true );
wp_editor( $value, '_use_and_application', array( 'editor_height' => 100 ) );
// Environment
echo '<br><hr><h4>' . __( 'Specification', 'woocommerce' ) . '</h4>';
$value = get_post_meta( $post->ID, '_specification', true );
wp_editor( $value, '_specification', array( 'editor_height' => 100 ) );
// Nonce field (for security)
echo '<input type="hidden" name="additional_product_tabs_nonce" value="' . wp_create_nonce() . '">';
}
// Save product data
add_action( 'save_post_product', 'save_additional_product_tabs', 10, 1 );
function save_additional_product_tabs( $post_id ) {
// Security check
if ( ! isset( $_POST[ 'additional_product_tabs_nonce' ] ) ) {
return $post_id;
}
//Verify that the nonce is valid.
if ( ! wp_verify_nonce( $_POST[ 'additional_product_tabs_nonce' ] ) ) {
return $post_id;
}
// If this is an autosave, our form has not been submitted, so we don't want to do anything.
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return $post_id;
}
if ( ! current_user_can( 'edit_product', $post_id ) ) {
return $post_id;
}
// Sanitize user input and save the post meta fields values.
if( isset($_POST[ '_cost_performance' ]) )
update_post_meta( $post_id, '_cost_performance', wp_kses_post($_POST[ '_cost_performance' ]) );
if( isset($_POST[ '_environment' ]) )
update_post_meta( $post_id, '_environment', wp_kses_post($_POST[ '_environment' ]) );
if( isset($_POST[ '_dilution_directions' ]) )
update_post_meta( $post_id, '_dilution_directions', wp_kses_post($_POST[ '_dilution_directions' ]) );
if( isset($_POST[ '_packaging_and_handling' ]) )
update_post_meta( $post_id, '_packaging_and_handling', wp_kses_post($_POST[ '_packaging_and_handling' ]) );
if( isset($_POST[ '_use_and_application' ]) )
update_post_meta( $post_id, '_use_and_application', wp_kses_post($_POST[ '_use_and_application' ]) );
if( isset($_POST[ '_specification' ]) )
update_post_meta( $post_id, '_specification', wp_kses_post($_POST[ '_specification' ]) );
}
add_filter( 'woocommerce_product_tabs', 'woo_custom_product_tabs' );
function woo_custom_product_tabs( $tabs ) {
// 1) Removing tabs
unset( $tabs['description'] ); // Remove the description tab
unset( $tabs['additional_information'] ); // Remove the additional information tab
// 2 Adding new tabs and set the right order
//Attribute Cost and Performance tab
$tabs['cost_performance_tab'] = array(
'title' => __( 'Cost + Performance', 'woocommerce' ),
'priority' => 10,
'callback' => 'woo_cost_performance_tab_content'
);
// Adds the environment tab
$tabs['environment_tab'] = array(
'title' => __( 'Environment', 'woocommerce' ),
'priority' => 20,
'callback' => 'woo_environment_tab_content'
);
// Adds the dilution tab
$tabs['dilution_tab'] = array(
'title' => __( 'Suggested Dilution Directions', 'woocommerce' ),
'priority' => 30,
'callback' => 'woo_dilution_tab_content'
);
// Adds the packaging tab
$tabs['packaging_tab'] = array(
'title' => __( 'Packaging + Handling', 'woocommerce' ),
'priority' => 40,
'callback' => 'woo_packaging_tab_content'
);
// Adds the application tab
$tabs['application_tab'] = array(
'title' => __( 'Use + Application', 'woocommerce' ),
'priority' => 60,
'callback' => 'woo_application_tab_content'
);
// Adds the specification tab
$tabs['specification_tab'] = array(
'title' => __( 'Specification', 'woocommerce' ),
'priority' => 70,
'callback' => 'woo_specification_tab_content'
);
$tabs['reviews']['priority'] = 80;
return $tabs;
}
function woo_cost_performance_tab_content() {
global $product;
echo'<div><p>'. $product->get_meta( '_cost_performance' ) . '</p></div>';
}
function woo_environment_tab_content() {
global $product;
echo'<div><p>'. $product->get_meta( '_environment' ) . '</p></div>';
}
function woo_dilution_tab_content() {
global $product;
echo'<div><p>'. $product->get_meta( '_dilution_directions' ) . '</p></div>';
}
function woo_packaging_tab_content() {
global $product;
echo'<div><p>'. $product->get_meta( '_packaging_and_handling' ) . '</p></div>';
}
function woo_application_tab_content() {
global $product;
echo'<div><p>'. $product->get_meta( '_use_and_application' ) . '</p></div>';
}
function woo_specification_tab_content() {
global $product;
echo'<div><p>'. $product->get_meta( '_specification' ) . '</p></div>';
}
Code goes in function.php file of your active child theme (or active theme). Tested and work.
I need to know how to pull all of my posts from a custom post type into a single page, while making the page display these posts according to the page template that is chosen in the post editor.
I integrated a dropdown that assigns page templates that can be chosen by the client, but how do I output that content?
Here's all the code for the post type, including the template chooser.
add_action('init', 'create_modules');
function create_modules() {
$moduleslabels = array(
'name' => 'Module',
'singular_name' => 'Home Module',
'add_new' => 'Add New Module',
'add_new_item' => 'Add New Module',
'edit_item' => 'Edit Module',
'new_item' => 'New Module',
'all_items' => 'All Modules',
'view_item' => 'View Module',
'search_items' => 'Search Modules',
'not_found' => 'No Modules Found',
'not_found_in_trash' => 'No Modules Found in Trash',
'parent_item_colon' => '',
'menu_name' => 'Home Modules'
);
$modules_args = array(
'labels' => $moduleslabels,
'public' => true,
'show_ui' => true,
'capability_type' => 'page',
'order' => 'ASC',
'rewrite' => true,
'menu_icon' => 'dashicons-menu',
'supports' => array('title', 'editor', 'thumbnail', 'page-attributes', 'revisions')
);
register_post_type('modules',$modules_args);
}
// admin filters
add_filter("manage_edit_modules_columns", "modules_edit_columns");
add_action("manage_posts_custom_column", "modules_columns_display");
function modules_edit_columns($modules_columns){
$modules_columns = array(
"cb" => "<input type=\"checkbox\" />",
"title" => "Section Title",
"description" => "Section Content",
);
return $modules_columns;
}
function modules_columns_display($modules_columns){
switch ($modules_columns)
{
case "description":
the_content();
break;
}
}
// new title text in Module
add_filter( 'enter_title_here', 'modules_enter_title_here' );
function modules_enter_title_here( $message ){
global $post;
if( 'modules' == $post-> post_type ):
$message = 'Enter Title';
endif;
return $message;
}
/** Custom Post Type Template Selector **/
function cpt_add_meta_boxes() {
$post_types = get_post_types();
foreach( $post_types as $ptype ) {
if ( $ptype !== 'page') {
add_meta_box( 'cpt-selector', 'Attributes', 'cpt_meta_box', $ptype, 'side', 'core' );
}
}
}
add_action( 'add_meta_boxes', 'cpt_add_meta_boxes' );
function cpt_remove_meta_boxes() {
$post_types = get_post_types();
foreach( $post_types as $ptype ) {
if ( $ptype !== 'page') {
remove_meta_box( 'pageparentdiv', $ptype, 'normal' );
}
}
}
add_action( 'admin_menu' , 'cpt_remove_meta_boxes' );
function cpt_meta_box( $post ) {
$post_meta = get_post_meta( $post->ID );
$templates = wp_get_theme()->get_page_templates();
$post_type_object = get_post_type_object($post->post_type);
if ( $post_type_object->hierarchical ) {
$dropdown_args = array(
'post_type' => $post->post_type,
'exclude_tree' => $post->ID,
'selected' => $post->post_parent,
'name' => 'parent_id',
'show_option_none' => __('(no parent)'),
'sort_column' => 'menu_order, post_title',
'echo' => 0,
);
$dropdown_args = apply_filters( 'page_attributes_dropdown_pages_args', $dropdown_args, $post );
$pages = wp_dropdown_pages( $dropdown_args );
if ( $pages ) {
echo "<p><strong>Parent</strong></p>";
echo "<label class=\"screen-reader-text\" for=\"parent_id\">Parent</label>";
echo $pages;
}
}
// Template Selector
echo "<p><strong>Template</strong></p>";
echo "<select id=\"cpt-selector\" name=\"_wp_page_template\"><option value=\"default\">Default Template</option>";
foreach ( $templates as $template_filename => $template_name ) {
if ( $post->post_type == strstr( $template_filename, '-', true) ) {
if ( isset($post_meta['_wp_page_template'][0]) && ($post_meta['_wp_page_template'][0] == $template_filename) ) {
echo "<option value=\"$template_filename\" selected=\"selected\">$template_name</option>";
} else {
echo "<option value=\"$template_filename\">$template_name</option>";
}
}
}
echo "</select>";
// Page order
echo "<p><strong>Order</strong></p>";
echo "<p><label class=\"screen-reader-text\" for=\"menu_order\">Order</label><input name=\"menu_order\" type=\"text\" size=\"4\" id=\"menu_order\" value=\"". esc_attr($post->menu_order) . "\" /></p>";
}
function save_cpt_template_meta_data( $post_id ) {
if ( isset( $_REQUEST['_wp_page_template'] ) ) {
update_post_meta( $post_id, '_wp_page_template', $_REQUEST['_wp_page_template'] );
}
}
add_action( 'save_post' , 'save_cpt_template_meta_data' );
function custom_single_template($template) {
global $post;
$post_meta = ( $post ) ? get_post_meta( $post->ID ) : null;
if ( isset($post_meta['_wp_page_template'][0]) && ( $post_meta['_wp_page_template'][0] != 'default' ) ) {
$template = get_template_directory() . '/' . $post_meta['_wp_page_template'][0];
}
return $template;
}
add_filter( 'single_template', 'custom_single_template' );
/** END Custom Post Type Template Selector **/
I don't have anything in terms of a page template yet, that's what I need help creating, but here's the post type code.
Thanks!
Using the right filter
The single_template filter is hookable when someone views a single item. Since you're looking to create a page with an overview of all the modules you should replace the filter you're now using (single_template) with another one - replace the last sentence of your code with:
add_filter( 'page_template', 'custom_single_template' );
Create a new page in the backend
Create a new page and name it 'Modules Page'. Select a page template from your custom drop down. Remember what page template you've selected. You'll need that in the following step.
Edit the page template
Fetching posts can be done with WP_Query. Try to paste the following code in the page template you selected in the above step, and see if you get results. Make sure you've added a couple of items in the modules post type.
// WP_Query arguments
$args = array (
'post_type' => array( 'modules' ),
'post_status' => array( 'publish' ),
'posts_per_page' => '-1',
);
// The Query
$query = new WP_Query( $args );
// The Loop
if ( $query->have_posts() ) {
while ( $query->have_posts() ) {
// get post data
$query->the_post();
// show the module title
echo get_the_title();
}
} else {
// no modules found
echo 'No items in "modules" post type';
}
// Restore original Post Data
wp_reset_postdata();
<?php
/*
Plugin Name: Opportunities
Description: Custom Post Types for "The Oppourtunities Blog" website.
Author: Sheju
Author URI: http://www.localhost.com
*/
if( ! function_exists( 'Opportunity_create_post_type' ) ) :
function Opportunity_create_post_type() {
$labels = array(
'name' => __( 'Opportunity' ),
'singular_name' => __( 'Opportunity' ),
'add_new' => __( 'Add New Opportunity' ),
'all_items' => __( 'All Opportunities' ),
'add_new_item' => __( 'Add New Opportunity' ),
'edit_item' => __( 'Edit Opportunity' ),
'new_item' => __( 'New Opportunity' ),
'view_item' => __( 'View Opportunity' ),
'search_items' => __( 'Search Opportunities' ),
'not_found' => __( 'No Opportunities found' ),
'not_found_in_trash' => __( 'No Opportunities found in trash' ),
'parent_item_colon' => __( 'Parent Opportunity' )
//'menu_name' => default to 'name'
);
$args = array(
'labels' => $labels,
'public' => true,
'has_archive' => true,
'publicly_queryable' => true,
'query_var' => true,
'rewrite' => true,
'capability_type' => 'post',
'hierarchical' => false,
'supports' => array(
'title',
'editor',
'excerpt',
//'thumbnail',
//'author',
//'trackbacks',
//'custom-fields',
//'comments',
'revisions',
//'page-attributes', // (menu order, hierarchical must be true to show Parent option)
//'post-formats',
),
'taxonomies' => array( 'category', 'post_tag' ), // add default post categories and tags
'menu_position' => 5,
'register_meta_box_cb' => 'Opportunity_add_post_type_metabox'
);
register_post_type( 'Opportunity', $args );
//flush_rewrite_rules();
register_taxonomy( 'Opportunity_category', // register custom taxonomy - Opportunity category
'Opportunity',
array( 'hierarchical' => true,
'label' => __( 'Opportunity categories' )
)
);
register_taxonomy( 'Opportunity_tag', // register custom taxonomy - Opportunity tag
'Opportunity',
array( 'hierarchical' => false,
'label' => __( 'Opportunity tags' )
)
);
}
add_action( 'init', 'Opportunity_create_post_type' );
function Opportunity_add_post_type_metabox() { // add the meta box
add_meta_box( 'Opportunity_metabox', 'More Details about Opportunity', 'Opportunity_metabox', 'Opportunity', 'normal' );
}
function Opportunity_metabox() {
global $post;
// Noncename needed to verify where the data originated
echo '<input type="hidden" name="Opportunity_post_noncename" id="Opportunity_post_noncename" value="' . wp_create_nonce( plugin_basename(__FILE__) ) . '" />';
// Get the data if its already been entered
$Opportunity_post_name = get_post_meta($post->ID, '_Opportunity_post_name', true);
$Opportunity_post_desc = get_post_meta($post->ID, '_Opportunity_post_desc', true);
$Opportunity_post_duration = get_post_meta($post->ID, '_Opportunity_post_duration', true);
// Echo out the field
?>
<div class="width_full p_box">
<p>
<label>Name<br>
<input type="text" name="Opportunity_post_name" class="widefat" value="<?php echo $Opportunity_post_name; ?>">
</label>
</p>
<p><label>Description<br>
<textarea name="Opportunity_post_desc" class="widefat"><?php echo $Opportunity_post_desc; ?></textarea>
</label>
</p>
<p><label>Duration<br>
<textarea name="Opportunity_post_duration" class="widefat"><?php echo $Opportunity_post_duration; ?></textarea>
</label>
</p>
</div>
<?php
}
function Opportunity_post_save_meta( $post_id, $post ) { // save the data
// verify this came from the our screen and with proper authorization,
// because save_post can be triggered at other times
if( !wp_verify_nonce( $_POST['Opportunity_post_noncename'], plugin_basename(__FILE__) ) ) {
return $post->ID;
}
// is the user allowed to edit the post or page?
if( ! current_user_can( 'edit_post', $post->ID )){
return $post->ID;
}
// ok, we're authenticated: we need to find and save the data
// we'll put it into an array to make it easier to loop though
$Opportunity_post_meta['_Opportunity_post_name'] = $_POST['Opportunity_post_name'];
$Opportunity_post_meta['_Opportunity_post_desc'] = $_POST['Opportunity_post_desc'];
$Opportunity_post_meta['_Opportunity_post_duration'] = $_POST['Opportunity_post_duration'];
// add values as custom fields
foreach( $Opportunity_post_meta as $key => $value ) { // cycle through the $Opportunity_post_meta array
// if( $post->post_type == 'revision' ) return; // don't store custom data twice
$value = implode(',', (array)$value); // if $value is an array, make it a CSV (unlikely)
if( get_post_meta( $post->ID, $key, FALSE ) ) { // if the custom field already has a value
update_post_meta($post->ID, $key, $value);
} else { // if the custom field doesn't have a value
add_post_meta( $post->ID, $key, $value );
}
if( !$value ) { // delete if blank
delete_post_meta( $post->ID, $key );
}
}
}
add_action( 'save_post', 'Opportunity_post_save_meta', 1, 2 ); // save the custom fields
endif; // end of function_exists()
if( ! function_exists( 'view_Opportunities_posts' ) ) : // output
function view_Opportunities_posts( $num = 4, $do_shortcode = 1, $strip_shortcodes = 0 ) {
$args = array(
'numberposts' => $num,
'offset' => 0,
//'category' => ,
'orderby' => 'menu_order, post_title', // post_date, rand
'order' => 'DESC',
//'include' => ,
//'exclude' => ,
//'meta_key' => ,
//'meta_value' => ,
'post_type' => 'Opportunity',
//'post_mime_type' => ,
//'post_parent' => ,
'post_status' => 'publish',
'suppress_filters' => true
);
$posts = get_posts( $args );
$html = '';
foreach ( $posts as $post ) {
$meta_name = get_post_meta( $post->ID, '_echo"test"'.'_Opportunity_post_name', true );
$meta_desc = get_post_meta( $post->ID, '_Opportunity_post_desc', true );
$meta_duration = get_post_meta( $post->ID, '_Opportunity_post_duration', true );
/*if (!empty($meta_duration) && !empty($$meta_duration['_Opportunity_post_duration']));
*/
/*<?php $my_meta = get_post_meta($post->ID,'_my_meta',TRUE); ?>
<?php if (!empty($my_meta) && !empty($my_meta['image_one'])): ?>
<div class="archive_images_one"><img border="0" width="300px" height="200px" src="<? echo $my_meta['image_one']; ?>" alt="Android and iPhone App Development"></div>
<?php endif; ?>*/
//$img = get_the_post_thumbnail( $post->ID, 'medium' );
// if( empty( $img ) ) {
// $img = '<img src="'.plugins_url( '/img/default.png', __FILE__ ).'">';
// }
//
//
// if( has_post_thumbnail( $post->ID ) ) {
// //$image = wp_get_attachment_image_src( get_post_thumbnail_id( $post->ID ), 'single-post-thumbnail' );
// //$img_url = $image[0];
// $img = wp_get_attachment_image_src( get_post_thumbnail_id( $post->ID ), 'thumbnail' );
// $img_url = $img[0];
//
// //the_post_thumbnail( 'thumbnail' ); /* thumbnail, medium, large, full, thumb-100, thumb-200, thumb-400, array(100,100) */
// }
//
$content = $post->post_content;
if( $do_shortcode == 1 ) {
$content = do_shortcode( $content );
}
if( $strip_shortcodes == 1 ) {
$content = strip_shortcodes( $content );
}
$html .= '
<div>
<h3>'.$post->post_title.'</h3>
<div>'.$content.'</div>
<div>
<p>'.$meta_name.'</p>
<p>'.$meta_desc.'</p>
<p>'.$meta_duration.'</p>
</div>
</div>
';
}
$html = '<div class="wrapper">'.$html.'</div>';
return $html;
}
endif; // end of function_exists()
?>
I need to add custom label for the meta fields in out put only if there is a value exist. Please help to do it.
I tried to change the p tag at the end (something like this):
<h3>'.$post->post_title.'</h3>
<div>
<p>Name: '.$meta_name.'</p>
<p>Description: '.$meta_desc.'</p>
</div>
<div>'.$img.'</div>
<div>'.$content.'</div>
Not 100% sure I understand what you need, but if you're looking to only show certain meta if it has a value you could do something like this:
$html .= '<div>';
$html .= '<h3>' . $post->post_title . '</h3>';
$html .= '<div>' . $content . '</div>';
$html .= '<div>';
if( !empty($meta_name) ) {
$html .= '<p>' . $meta_name . '</p>';
}
if( !empty($meta_desc) ) {
$html .= '<p>' . $meta_desc . '</p>';
}
if( !empty($meta_duration) ) {
$html .= '<p>' . $meta_duration . '</p>';
}
$html .= '</div>';
$html .= '</div>';
I am using register_post_type to create post_meta. So in its listing page by default it is showing date filter. I want remove all default filter and i want to create my new custom filter. My code to create post_type is -
//Manage news Feed
add_action('init', 'manage_news_feed');
function manage_news_feed() {
register_post_type('news_feed', array(
'labels' => array(
'name' => 'Feed Management',
'singular_name' => 'Feed Management',
'add_new' => 'Add New',
'add_new_item' => 'Add New Feed',
'edit' => 'Edit',
'edit_item' => 'Edit Feed',
'new_item' => 'New Feed',
'view' => 'View',
'view_item' => 'View Feed',
'search_items' => 'Search Feed',
'not_found' => 'No Feed',
'not_found_in_trash' => 'No Feed found in Trash',
'parent' => 'Parent News Feed'
),
'public' => true,
'menu_position' => 100,
'supports' => array('title', 'thumbnail'),
'taxonomies' => array(''),
'menu_icon' => plugins_url('images/adv-.png', __FILE__),
'has_archive' => true,
'rewrite' => true,
)
);
}
And this is to add custom column to in list page-
//Add custom column for feed_url
add_filter( 'manage_edit-news_feed_columns', 'news_feed_custom_columns', 25, 1 );
function news_feed_custom_columns( $cols )
{
$cols = array(
"cb" => "<input type=\"checkbox\" />",
"title" => "News Feed Url",
"category_id" => "Category Id",
"date" => "Created Date"
);
return $cols;
}
add_action( 'manage_posts_custom_column', 'custom_columns', 2, 1 );
function custom_columns( $col )
{
global $post;
switch ( $col )
{
case "feed_url" :
if( '' != get_post_meta( $post->ID, 'feed_url', true ) )
echo get_post_meta( $post->ID, 'feed_url', true );
else
echo __( 'N/A', 'txt_domain' );
break;
case "category_id" :
echo get_post_meta( $post->ID, 'category_id', true );
break;
}
}
my code for Custom_meta_box is -
// Add fields for news Feed
add_action('admin_init', 'my_admin');
function my_admin() {
add_meta_box('movie_review_meta_box', 'Feed Details', 'news_feed_meta_box', 'news_feed', 'normal', 'high'
);
}
//Function to create meta_box for news feed
function news_feed_meta_box($feed) {
global $wpdb;
$category_name = esc_html(get_post_meta($feed->ID, 'category_id', true));
$feed_url = esc_html(get_post_meta($feed->ID, 'post_title', true));
?>
<table style="width: 100%">
<tr>
<td>Category Name</td>
<td><?php wp_dropdown_categories(array('hide_empty' => 0, 'name' => 'category_id', 'hierarchical' => true));?></td>
</tr>
<tr>
<td>Feed Url</td>
<td><input id="post_title" type="text" required="" data-required="true" size="40" name="post_title" value="<?php echo $feed_url; ?>" /></td>
</tr>
</table>
<?php
}
add_action('save_post', 'add_feed_fields', 10, 2);
function add_feed_fields($feed_id, $feed) {
// Check post type for feed
if ($feed->post_type == 'news_feed') {
if (isset($_POST['category_id']) && $_POST['category_id'] != '') {
update_post_meta($feed_id, 'category_id', $_POST['category_id']);
}
if (isset($_POST['feed_url']) && $_POST['feed_url'] != '') {
update_post_meta($feed_id, 'feed_url', $_POST['feed_url']);
}
}
}
i want use custom filter based on category id in list page. please help me. How i can do this.
My category filter image
If you need to add a new custom category filter you need to hook to the restrict_manage_posts filter.
Add this in your themes functions.php file.
//filter to add custom category filter and modify request
add_filter( 'restrict_manage_posts', 'custom_category_id_filter' );
add_filter( 'request', 'custom_category_id_request' );
function custom_category_id_request( $request ) {
global $post_type;
//return if we are not in wp-admin or the post type is not news_feed
if ( !is_admin() || $post_type != 'news_feed')
return $request;
//check if meta value filter is called. if then set request params
if ( isset( $_GET['mv'] ) and !empty( $_GET['mv'] )) {
$request['meta_key'] = 'category_id';
$request['meta_value'] = $_GET['mv'];
}
return $request;
}
function custom_category_id_filter( ) {
global $wpdb, $post_type;
//add this if we are in the specified post type
if ( is_admin() && $post_type == 'news_feed') {
$mvs = $wpdb->get_col( " SELECT DISTINCT meta_value FROM {$wpdb->postmeta} WHERE meta_key = 'category_id' ORDER BY meta_value ASC " );
?>
<select name="mv">
<option value=""><?php _e( 'Show Posts from all Category ID', 'posts_meta_search' ); ?></option>
<?php
if (!empty ($mvs)) {
foreach ( $mvs as $mv ) { ?>
<option value="<?php echo esc_attr( $mv ); ?>" <?php selected( $_GET['mv'], $mv ); ?>><?php echo esc_attr( $mv ); ?></option>
<?php }
}
?>
</select>
<?php
}
}
UPDATE 1:
Since the meta_value column is varchar field you need to cast it as integer to sort it as 1,2,3 ...
Change your query in custom_category_id_filter as follows:
$mvs = $wpdb->get_col( " SELECT DISTINCT meta_value FROM {$wpdb->postmeta} WHERE meta_key = 'category_id' ORDER BY CAST( meta_value AS SIGNED INTEGER ) ASC " );
Hope this helps you :-)