Is it possible to build an option in Wordpress which allows user to customise placement of featured image?
Currently the theme I am building, puts the featured image as a banner across the top of the post. Have some users requesting for option to be able to have featured images appear top right of the post with text wrapping around it.
Not sure about how to approach this. My first thought is to put an option in the customiser but I'm concerned this will apply to all blog posts rather than on an individual basis.
Another idea is to build a metabox into the post editing screen (underneath feat. image box) and then build a function to hook into wp post.
I've scoured over google on ways how to do this but all I can find so far is information on how to edit content.php to universally change/edit placement of all featured images.
It's hard to give an exact answer without knowing how your template is marked up, but I think you'll have two options of doing this. Either use a plugin (Advanced Custom Fields), or the solution you mentioned of adding a meta box to the post editor.
I would recommend Option 1 because the plugin is stable, configurable, and will save you some time if you need to add more fields.
Option 1: Use Advanced Custom Fields
Download and install the plugin from their site: https://www.advancedcustomfields.com
Use the plugin to add a custom field. These directions might help: https://www.advancedcustomfields.com/resources/creating-a-field-group/
Make note of the Field Name as you will need this in your code. You might use something such as image_placement. I'd recommend setting up a select box with values such as Left, Center, and Right.
Then, in your PHP template file, you'll want something like this:
<?php if( get_option('image_placement') === 'left' ) : ?>
// Write the markup here when the image be left-aligned
<?php else if( get_option('image_placement') === 'right' ) : ?>
// Write the markup here when the image should be right-aligned
<?php else : ?>
// Write the markup here when the image should be shown as a banner
<?php endif; ?>
Option 2: Add a custom meta box to each post
Add the following code to your functions.php:
// add the meta box to the post editor page
function add_image_meta_box( $post ) {
add_meta_box( 'image_meta_box', 'Image Placement', 'image_build_meta_box', 'post', 'side', 'low' );
}
add_action( 'add_meta_boxes', 'add_image_meta_box' );
// build the front-end for the meta box (shown on the post editor page)
function image_build_meta_box( $post ) {
wp_nonce_field( basename( __FILE__ ), 'image_meta_box_nonce' );
$image_placement = get_post_meta( $post->ID, '_post_image_placement' );
?>
<h3>Image Placement URL</h3>
<select name="image_placement">
<option value="left" <?php ($image_placement[0] === 'left') ?; echo 'selected'; ?>>Left</option>
<option value="center" <?php ($image_placement[0] === 'center') ?; echo 'selected'; ?>>Center</option>
<option value="right" <?php ($image_placement[0] === 'right') ?; echo 'selected'; ?>>Right</option>
</select>
<?php
}
// save the setting
function image_save_meta_box_data( $post_id ) {
// Check the user's permissions.
if ( !current_user_can( 'edit_post', $post_id ) ) {
return;
}
$image_placement = $_POST['image_placement'];
if( isset( $image_placement ) ){
update_post_meta( $post_id, '_post_image_placement', sanitize_text_field( $image_placement ) );
}
}
add_action( 'save_post', 'image_save_meta_box_data' );
This will add a field to each of your posts which can be used in the markup like thus:
<?php $image_placement = get_post_meta( $post->ID, '_post_image_placement' )[0]; ?>
<?php if( $image_placement === 'left' ) : ?>
// Write the markup here when the image be left-aligned
<?php else if( $image_placement === 'right' ) : ?>
// Write the markup here when the image should be right-aligned
<?php else : ?>
// Write the markup here when the image should be shown as a banner
<?php endif; ?>
kudos to #rideron89 for helping me with the solution. So here it is if anyone needs to use it (in some implementation):
I'm keeping functions.php a bit clean so I put it into another php file within 'incl' folder and it gets included within functions.php"
// add the meta box to the post editor page
function add_image_meta_box( $post ) {
add_meta_box( 'image_meta_box', 'Featured Image Placement', 'image_build_meta_box', 'post', 'side', 'low' );
}
add_action( 'add_meta_boxes', 'add_image_meta_box' );
// build the front-end for the meta box (shown on the post editor page)
function image_build_meta_box( $post ) {
wp_nonce_field( basename( __FILE__ ), 'image_meta_box_nonce' );
$image_placement_array = get_post_meta( $post->ID, '_post_image_placement' );
$image_placement = implode (" ",$image_placement_array);
?>
<p>Please select the layout/alignment of your featured image <em>(default is full width banner)</em></p>
<select name="image_placement">
<option value="default" name="feat_img_align" <?php if($image_placement === 'default'){ echo "selected"; } ?>>Default</option>
<option value="left" name="feat_img_align" <?php if($image_placement === 'left'){ echo "selected"; } ?>>Left</option>
<option value="right" name="feat_img_align" <?php if($image_placement === 'right'){ echo "selected"; } ?>>Right</option>
</select>
<?php
}
// save the setting
function image_save_meta_box_data( $post_id ) {
// Check the user's permissions.
if ( !current_user_can( 'edit_post', $post_id ) ) {
return;
}
$image_placement = $_POST['image_placement'];
if( isset( $image_placement ) ){
update_post_meta( $post_id, '_post_image_placement', sanitize_text_field( $image_placement ) );
}
}
add_action( 'save_post', 'image_save_meta_box_data' );
The code that I inserted into the post content.php template was:
<?php
$post_feat_img = quick_resize_to_ratio_and_size(get_post_thumbnail_id($post->ID),1,1,250);
$alt_text = get_post_meta(get_post_thumbnail_id($post->ID), '_wp_attachment_image_alt', true);
$image_placement_array = get_post_meta( $post->ID, '_post_image_placement' );
$image_placement = implode (" ",$image_placement_array);
?>
<?php if ($image_placement === 'default') { ?>
<p><?php echo get_the_post_thumbnail($post->ID, 'large', array( 'class'=>'img-responsive center-block img-thumbnail')); ?></p>
<?php } else if ($image_placement === 'left') { ?>
<img src="<?php echo $post_feat_img; ?>" alt="<?php echo $alt_text ?>" class="alignFeatleft img-thumbnail img-responsive">
<?php } else if ($image_placement === 'right') { ?>
<img src="<?php echo $post_feat_img; ?>" alt="<?php echo $alt_text ?>" class="alignFeatRight img-thumbnail img-responsive">
<?php } else { ?>
<p><?php echo get_the_post_thumbnail($post->ID, 'large', array( 'class'=>'img-responsive center-block img-thumbnail')); ?></p>
<?php } ?>
<?php the_content(); ?>
Related
Hi :) I am working on my site with the "flexible post widget" to show the related contents or the content that I am interested in showing on the sidebar.
The widget works very well and I'm interested in continuing to use it, especially for the design and adaptability options with my site.
The problem? It does not include a function for "exclude the current post".
I was reviewing the code (I add it to this thread) and I think I could add some lines of code for this function (exclude the post I'm reading).
Unfortunately I'm new to programming and I'm lost with what and where to add it.
Could you help me?
<?php
/**
* Flexible Posts Widget: Default widget template
*
* #since 3.4.0
*
* This template was added to overcome some often-requested changes
* to the old default template (widget.php).
*/
// Block direct requests
if ( !defined('ABSPATH') )
die('-1');
echo $before_widget;
if ( ! empty( $title ) )
echo $before_title . $title . $after_title;
if ( $flexible_posts->have_posts() ):
function be_exclude_current_post( $args ) {
if( is_singular() && !isset( $args['post__in'] ) )
$args['post__not_in'] = array( get_the_ID() );
return $args;
}
add_filter( 'widget_posts_args', 'be_exclude_current_post' );
?>
<ul class="dpe-flexible-posts">
<?php while ( $flexible_posts->have_posts() ) : $flexible_posts->the_post(); global $post; ?>
<li id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
<a href="<?php echo the_permalink(); ?>">
<?php
if ( $thumbnail == true ) {
// If the post has a feature image, show it
if ( has_post_thumbnail() ) {
the_post_thumbnail( $thumbsize );
// Else if the post has a mime type that starts with "image/" then show the image directly.
} elseif ( 'image/' == substr( $post->post_mime_type, 0, 6 ) ) {
echo wp_get_attachment_image( $post->ID, $thumbsize );
}
}
?>
<div class="title"><?php the_title(); ?></div>
</a>
</li>
<hr>
<?php endwhile; ?>
</ul><!-- .dpe-flexible-posts -->
<?php
endif; // End have_posts()
echo $after_widget;
Add this to your theme's 'functions.php' and remove it from the widget template.
function be_exclude_current_post( $args ) {
if( is_singular() && !isset( $args['post__in'] ) )
$args['post__not_in'] = array( get_the_ID() );
return $args;
}
add_filter( 'dpe_fpw_args', 'be_exclude_current_post' );
I have customised my Wordpress site design to use the featured image for posts quite excessively. This is why I need to require all post made by non-admins to require a set featured image.
How is this possible?
You need to hook the Publish Action in a custom PlugIn you write. Although this is to require a title, this should get you started, you just need to check if a featured image was assigned.
add_action( 'pre_post_update', 'bawdp_dont_publish' );
function bawdp_dont_publish()
{
global $post;
if ( strlen( $post->title ) < 10 ) {
wp_die( 'The title of your post have to be 10 or more !' );
}
}
Look at (has_post_thumbnail( $post->ID )) to determine if a post has a featured image.
Given Gary's example above, I've written the following to my functions.php file:
function featured_image_requirement() {
if(!has_post_thumbnail()) {
wp_die( 'You forgot to set the featured image. Click the back button on your browser and set it.' );
}
}
add_action( 'pre_post_update', 'featured_image_requirement' );
I'd much rather see this in a plugin as well - there's one called Mandatory Field but it doesn't work with scheduled posts. Both are not really eloquent solutions.
you can use a plugin
https://wordpress.org/plugins/require-featured-image/
or you can copy and paste below code in your wordpress theme functions.php file:
<?php
/**
* Require a featured image to be set before a post can be published.
*/
add_filter( 'wp_insert_post_data', function ( $data, $postarr ) {
$post_id = $postarr['ID'];
$post_status = $data['post_status'];
$original_post_status = $postarr['original_post_status'];
if ( $post_id && 'publish' === $post_status && 'publish' !== $original_post_status ) {
$post_type = get_post_type( $post_id );
if ( post_type_supports( $post_type, 'thumbnail' ) && ! has_post_thumbnail( $post_id ) ) {
$data['post_status'] = 'draft';
}
}
return $data;
}, 10, 2 );
add_action( 'admin_notices', function () {
$post = get_post();
if ( 'publish' !== get_post_status( $post->ID ) && ! has_post_thumbnail( $post->ID ) ) { ?>
<div id="message" class="error">
<p>
<strong><?php _e( 'Please set a Featured Image. This post cannot be published without one.' ); ?></strong>
</p>
</div>
<?php
}
} );
I created a metabox that can be used to add a sidebar to a post. The get_sidebar function will be added to the post template using an if statement based on whether the user checks the sidebar radio button or not, but I haven't got that far yet.
So far the metabox shows up in the editor screen but when I check the sidebar radio button it returns unchecked after I update the post.
This is what I am using to keep the radio button checked after the post has been updated.
$layout = $_POST["layout"];
<input type="radio" name="layout" <?php if (isset($layout) && $layout=="right-sidebar") echo "checked"; ?> value="right-sidebar">
This is the full code I am using to create and update the metabox:
<?php
function hill_add_layout_metabox() {
add_meta_box(
'layout_metabox',
'Layout1',
'hill_callback_layout_matabox',
'post',
'side',
'high'
);
}
add_action('add_meta_boxes', 'hill_add_layout_metabox');
function hill_callback_layout_matabox() {
$layout = $_POST["layout"];
?>
<input type="radio" name="layout" <?php if (isset($layout) && $layout=="right-sidebar") echo "checked"; ?> value="right-sidebar"> Right Sidebar
<?php
}
function hill_save_layout_metabox($post_id) {
$is_autosave = wp_is_post_autosave ( $post_id );
$is_revision = wp_is_post_revision ( $post_id );
if ( $is_autosave || $is_revision ) {
return;
}
$layout = $_POST["layout"];
if (isset($layout) && $layout=="right-sidebar") {
update_post_meta( $post_id, $layout );
}
}
add_action('save_post', 'hill_save_layout_metabox');
?>
How to add custom meta box in post . Refer the below links it will solved your problem .
https://www.smashingmagazine.com/2011/10/create-custom-post-meta-boxes-wordpress/
http://code.tutsplus.com/tutorials/how-to-create-custom-wordpress-writemeta-boxes--wp-20336
http://www.sitepoint.com/adding-custom-meta-boxes-to-wordpress/
First, when saving the meta value, add a value to be saved:
It's a matter of preference, but I'll set the value to 'on' if checked other wise ''.
$value = isset($layout) && $layout=='right-sidebar' ? 'on' : ''
update_post_meta( $post_id, 'right-sidebar', $value );
After updating the post, get the value you saved using get_post_meta and set the radio button if needed; the WP checked() function is handy for this:
<?php $check = get_post_meta( $post_id, 'right-sidebar', true ); ?>
<input type="radio" name="layout" <?php checked( $check, 'on' ); ?> value="right-sidebar">
I'm using the Dazzling theme with the WooCommerce Plugin and on the WooCommerce pages that have products on them, the product image is also showing up as my featured image. I have a featured image set, but the product image seems be overwriting it.
The Feature image I have set is for all the shop pages is home_off.jpg. The cart and checkout pages look fine and are loading the proper feature image (no product images on those pages) So I guess the product image on the catalogue pages is using same/similar post_thumbnail code?
the code snippet I'm using to load my featured image as the background of a div is
<?php if (has_post_thumbnail( $post->ID ) ): ?>
<?php $image = wp_get_attachment_image_src( get_post_thumbnail_id( $post->ID ),
'single-post-thumbnail' ); ?>
<div id="featureImg" style="background-image: url('<?php echo $image[0]; ?>')">
</div>
<?php endif; ?>
You can see it best on this page http://dev.tdfinternational.net/index.php/product/finding-your-place-the-tdf-map-book/
But cart, checkout, etc, are looking good!
http://dev.tdfinternational.net/index.php/cart/
Any idea how to keep this from happening?
Ok, so what I recommend is that you create separate metabox for your posts and pages that will have the ability to use different image as your breadcrumbs image.
Create metabox
In your functions.php or wherever you put your metaboxes, put this code (should be working):
add_action( 'add_meta_boxes', 'my_add_custom_box' );
function my_add_custom_box($postType) {
$types = array('page', 'post');
if(in_array($postType, $types)){
add_meta_box(
'breadcrumbs-image-metabox-options',
esc_html__('Breadcrumbs', 'yourtheme' ),
'breadcrumbs_image_meta_box',
$postType,
'side',
'low'
);
}
}
if (!function_exists('breadcrumbs_image_meta_box') ) {
function breadcrumbs_image_meta_box($post) {
$custom = get_post_custom( $post->ID );
$breadcrumbs_image = (isset($custom["breadcrumbs_image"][0])) ? $custom["breadcrumbs_image"][0] : '';
wp_nonce_field( 'breadcrumbs_meta_box', 'breadcrumbs_meta_box_nonce' );
?>
<style type="text/css">
.hidden{display: none;}
.postbox .separator{padding-top: 0;margin-top: 20px;}
</style>
<p class="separator">
<input id="breadcrumbs_image_input" type="hidden" name="breadcrumbs_image" value="<?php echo esc_html($breadcrumbs_image); ?>"/>
<a title="<?php esc_html_e('Set Breadcrumbs Image', 'mytheme'); ?>" href="#" id="add-post-breadcrumbs_image">
<?php
if(!empty($custom["breadcrumbs_image"][0]) ){
echo '<img width="254" src="'.esc_url($breadcrumbs_image).'" />';
} else{
esc_html_e('Set Breadcrumbs Image', 'mytheme');
} ?></a>
<?php
if (empty($custom["breadcrumbs_image"][0])) {
echo '<a title="'.esc_html__('Remove Breadcrumbs Image', 'mytheme').'" href="#" id="remove-post-breadcrumbs_image" class="hidden">'.esc_html__('Remove Breadcrumbs Image', 'mytheme').'</a>';
} else{
echo '<a title="'.esc_html__('Remove Breadcrumbs Image', 'mytheme').'" href="#" id="remove-post-breadcrumbs_image" >'.esc_html__('Remove Breadcrumbs Image', 'mytheme').'</a>';
}
?>
</p>
<?php
}
}
add_action( 'save_post', 'save_breadcrumbs_image_meta_box' );
if ( ! function_exists( 'save_breadcrumbs_image_meta_box' ) ){
function save_breadcrumbs_image_meta_box( $post_id ){
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return;
}
if( !current_user_can( 'edit_pages' ) ) {
return;
}
if( !isset( $_POST['breadcrumbs_meta_box_nonce'] ) || !wp_verify_nonce( $_POST['breadcrumbs_meta_box_nonce'], 'breadcrumbs_meta_box' ) ) {
return;
}
$breadcrumbs_image = (isset($_POST["breadcrumbs_image"]) && $_POST["breadcrumbs_image"]!='') ? $_POST["breadcrumbs_image"] : '';
update_post_meta($post_id, "breadcrumbs_image", $breadcrumbs_image);
}
}
add_action('admin_enqueue_scripts', 'backend_scripts');
if ( ! function_exists( 'backend_scripts' ) ){
function backend_scripts() {
wp_enqueue_script( 'breadcrumbs_image_upload', get_template_directory_uri().'/js/admin.js' );
}
}
The first part creates a breadcrumbs metabox in your pages and posts. For woocommerce product you should probably add product to the $types array.
Then you create a metabox and save function for it. Now, since you want to have the functionality of a Featured image, you'll need some jquery to make it all work. That's why you need to enqueue a separate script that will appear only in your backend (that's why you're hooking to admin_enqueue_scripts).
And in your admin.js that you've put in your js theme folder, just put this:
jQuery(document).ready(function($) {
"use strict";
//Breadcrumbs Image
$(document).on('click', '#add-post-breadcrumbs_image', upload_breadcrumbs_image_button);
function upload_breadcrumbs_image_button(e) {
e.preventDefault();
var $input_field = $(this).prev();
var $image = $('#add-post-breadcrumbs_image');
var custom_uploader = wp.media.frames.file_frame = wp.media({
title: 'Add Breadcrumbs Image',
button: {
text: 'Add Breadcrumbs Image'
},
multiple: false
});
custom_uploader.on('select', function() {
var attachment = custom_uploader.state().get('selection').first().toJSON();
$input_field.val(attachment.url);
$image.html('');
$image.html('<img width="254" src="'+attachment.url+'" />');
$('#remove-post-breadcrumbs_image').removeClass('hidden');
});
custom_uploader.open();
}
$(document).on('click', '#remove-post-breadcrumbs_image', remove_breadcrumbs_image_button);
function remove_breadcrumbs_image_button(e){
e.preventDefault();
var $input_field = $('#breadcrumbs_image_input');
var $image = $('#add-post-breadcrumbs_image');
$input_field.val('');
var title = $image.attr('title');
$image.html(title);
$('#remove-post-breadcrumbs_image').addClass('hidden');
}
});
I've tested it in Twenty Fifteen and it's working:
And you can then use it by simply
$custom = get_post_custom(get_the_ID());
$custom['breadcrumbs_image'][0];
Hope this helps :)
I have customised my Wordpress site design to use the featured image for posts quite excessively. This is why I need to require all post made by non-admins to require a set featured image.
How is this possible?
You need to hook the Publish Action in a custom PlugIn you write. Although this is to require a title, this should get you started, you just need to check if a featured image was assigned.
add_action( 'pre_post_update', 'bawdp_dont_publish' );
function bawdp_dont_publish()
{
global $post;
if ( strlen( $post->title ) < 10 ) {
wp_die( 'The title of your post have to be 10 or more !' );
}
}
Look at (has_post_thumbnail( $post->ID )) to determine if a post has a featured image.
Given Gary's example above, I've written the following to my functions.php file:
function featured_image_requirement() {
if(!has_post_thumbnail()) {
wp_die( 'You forgot to set the featured image. Click the back button on your browser and set it.' );
}
}
add_action( 'pre_post_update', 'featured_image_requirement' );
I'd much rather see this in a plugin as well - there's one called Mandatory Field but it doesn't work with scheduled posts. Both are not really eloquent solutions.
you can use a plugin
https://wordpress.org/plugins/require-featured-image/
or you can copy and paste below code in your wordpress theme functions.php file:
<?php
/**
* Require a featured image to be set before a post can be published.
*/
add_filter( 'wp_insert_post_data', function ( $data, $postarr ) {
$post_id = $postarr['ID'];
$post_status = $data['post_status'];
$original_post_status = $postarr['original_post_status'];
if ( $post_id && 'publish' === $post_status && 'publish' !== $original_post_status ) {
$post_type = get_post_type( $post_id );
if ( post_type_supports( $post_type, 'thumbnail' ) && ! has_post_thumbnail( $post_id ) ) {
$data['post_status'] = 'draft';
}
}
return $data;
}, 10, 2 );
add_action( 'admin_notices', function () {
$post = get_post();
if ( 'publish' !== get_post_status( $post->ID ) && ! has_post_thumbnail( $post->ID ) ) { ?>
<div id="message" class="error">
<p>
<strong><?php _e( 'Please set a Featured Image. This post cannot be published without one.' ); ?></strong>
</p>
</div>
<?php
}
} );