I know I didn’t write a tutorial in a long while. It’s not that I didn’t have anything to write about, I was a bit busy with clients, getting involved with WordPress.org theme reviewing, giving talks and other projects and plugins. And since I really like to sleep I just didn’t find the proper time to write a tutorial. But I’m back now, and that’s all that matters :D I still have a redesign of the site to do, one article about my new plugin to write etc.
Notice: This article was written in 2017. WordPress has changed a lot since then, so take this article with a grain of salt…
Today I’ll write a simple tutorial that you can use to manipulate images a bit more.
Recently I worked on a site for a client, that was showcasing a lot of images. In sliders, in custom made pages that had a lot of images, and one request was that the single post was a showcase of images with a special arrangement. These posts would be made like horizontal sliders. First you’d have an image, then some post text about them, and then some more images. I used the info from the last tutorial about including images in your posts in a meta box, so that the client could arrange images to his liking, and also some ‘slides’ had 2 images placed side by side (60-40 ratio between the two images on a single slide).
All that was done relatively easily, I had some JavaScript that calculated the window height and width (so to cover the responsiveness of the site), and according to that I’d placed the images as a background of a container div. Now the drawbacks were how to determine which image should go to the left, and which to the right on a single slide, and how can I vertically position the images? I needed to be able to influence the background-position of the background. So I immediately remembered that I can add post meta controls inside the media selection of each image. This will allow the client to position the image as he wants.
Before we begin…
One notice that I’d like to mention before we start. Since December of the last year I’ve been reviewing the themes on WordPress.org and that really thought me a lot. It’s a thing I would recommend everyone to do when they find the time. It’s voluntary job, you won’t get paid, but you’ll get rewarded with the knowledge about what to do when creating a theme and what not to do.
One thing I’ve been doing in my tutorials is add everything (the custom parts) inside the theme. Now this is a valid approach and will definitely work. But what happens when you switch the theme, or your client does? The problem with placing everything inside your theme is that there will be a lot of clutter and mess left in your database, that you won’t be able to use on other themes if you make a switch. Ideally every custom part should be placed in a separate file and added as a plugin. In a plugin you can easily call a method on hooks which can detect plugin deactivation, and remove any extra parts from the database to avoid the clutter. Now since most stuff that I cover gets written to the post meta, if you delete the post, its post meta gets deleted too, so you’re safe with that one. Just keep in mind that content shouldn’t be lost on theme switch.
Just a word of advice I wanted to share with you, so that you keep it in mind when developing a custom solutions for your clients. Write a foolproof code that will be easy to maintain, not only to you, but to future developers who could be tasked with maintaining your code : )
PHP part
To add additional custom fields we will use attachment_fields_to_edit hook, and to save those fields we’ll use attachment_fields_to_save. Inside your plugin file, or functions.php file add
add_filter( 'attachment_fields_to_edit', 'mytheme_attachment_field_gallery', 10, 2 );
/**
* Add additional fields to media attachment post
*
* @param array $form_fields Form field array for the attachment.
* @param object $post Attachment record in the database.
* @return array Updated form fields.
*/
function mytheme_attachment_field_gallery( $form_fields, $post ) {
$post_id = $post->ID;
$checked_left = get_post_meta( $post_id, 'left_image', true );
$checked_right = get_post_meta( $post_id, 'right_image', true );
$image_position = get_post_meta( $post_id, 'image_position', true );
$form_fields['custom_text']['label'] = '';
$form_fields['custom_text']['input'] = 'html';
$form_fields['custom_text']['html'] = '<div>' . esc_html__( 'If the image will appear on a single side beside another one, select the side it will be on. Images labeled with a are usually on the left, while images labeled with b are on the right side.', 'mytheme' ) . '</div>';
$form_fields['left_image']['label'] = esc_html__( 'Left half image', 'mytheme' );
$form_fields['left_image']['input'] = 'html';
$form_fields['left_image']['html'] = '<input type="checkbox" value="1" name="attachments[' . $post_id . '][left_image]" id="attachments[' . $post_id . '][left_image]" ' . checked( $checked_left, '1', false ) . ' />';
$form_fields['right_image']['label'] = esc_html__( 'Right half image', 'mytheme' );
$form_fields['right_image']['input'] = 'html';
$form_fields['right_image']['html'] = '<input type="checkbox" value="1" name="attachments[' . $post_id . '][right_image]" id="attachments[' . $post_id . '][right_image]" ' . checked( $checked_right, '1', false ) . '/>';
$form_fields['image_position']['label'] = esc_html__( 'Image position', 'mytheme' );
$form_fields['image_position']['input'] = 'html';
$form_fields['image_position']['html'] = '<label for="attachments[' . $post_id . '][image_position]"> ' . esc_html__( 'Select the vertical alignment of the image. If the alignment isn\'t set, the image will be centered horizontally and vertically.', 'mytheme' ) . '
</label>
<select name="attachments[' . $post_id . '][image_position]" id="attachments[' . $post_id . '][image_position]">
<option value="10" ' . selected( $image_position, '10', false ) . '>' . esc_html__( '10%', 'mytheme' ) . '</option>
<option value="20" ' . selected( $image_position, '20', false ) . '>' . esc_html__( '20%', 'mytheme' ) . '</option>
<option value="30" ' . selected( $image_position, '30', false ) . '>' . esc_html__( '30%', 'mytheme' ) . '</option>
<option value="40" ' . selected( $image_position, '40', false ) . '>' . esc_html__( '40%', 'mytheme' ) . '</option>
<option value="50" ' . selected( $image_position, '50', false ) . '>' . esc_html__( '50%', 'mytheme' ) . '</option>
<option value="60" ' . selected( $image_position, '60', false ) . '>' . esc_html__( '60%', 'mytheme' ) . '</option>
<option value="70" ' . selected( $image_position, '70', false ) . '>' . esc_html__( '70%', 'mytheme' ) . '</option>
<option value="80" ' . selected( $image_position, '80', false ) . '>' . esc_html__( '80%', 'mytheme' ) . '</option>
<option value="90" ' . selected( $image_position, '90', false ) . '>' . esc_html__( '90%', 'mytheme' ) . '</option>
<option value="100" ' . selected( $image_position, '100', false ) . '>' . esc_html__( '100%', 'mytheme' ) . '</option>
<option value="center" ' . selected( $image_position, 'center', false ) . '>' . esc_html__( 'Center', 'mytheme' ) . '</option>
</select>';
return $form_fields;
}
Code language: PHP (php)
This will add the following fields to your media library ‘Attachment Details’ screen
After that we need to save them, so we’ll use the following code for this
add_filter( 'attachment_fields_to_save', 'mytheme_attachment_field_gallery_save', 10, 2 );
/**
* Save form fields for media attachments
*
* @param array $post WP post array.
* @param array $attachment Part of the form $_POST ($_POST[attachments][postID]).
* @return array Updated post.
*/
function mytheme_attachment_field_gallery_save( $post, $attachment ) {
if ( isset( $attachment['left_image'] ) ) {
update_post_meta( $post['ID'], 'left_image', $attachment['left_image'] );
}
if ( isset( $attachment['right_image'] ) ) {
update_post_meta( $post['ID'], 'right_image', $attachment['right_image'] );
}
if ( isset( $attachment['image_position'] ) ) {
update_post_meta( $post['ID'], 'image_position', $attachment['image_position'] );
}
return $post;
}
Code language: PHP (php)
Since attachments are just posts with a post type ‘attachment’, we need to save the values from the new fields to the attachment post meta. And that’s it for the addition of the custom fields. So how do we use it?
Usage
Since this is post meta, all you need to do is access the image post meta and check for your added field
$image_meta = get_post_meta( $post->ID );
get_post_meta( $image_meta, 'left_image', true );
Code language: PHP (php)
You can do with it what ever you want. In my case I had gallery stored as a string of image attachments ID’s. So I had, inside the loop
$meta = get_post_meta( $post->ID );
$gallery = ( isset( $meta['my_gallery'][0] ) && '' !== $meta['my_gallery'][0] ) ? explode( ',', $meta['my_gallery'][0] ) : '';
foreach ( $gallery as $key => $value ) {
$image_url = wp_get_attachment_url( $value );
$image_left_meta = get_post_meta( $value, 'left_image', true );
$image_right_meta = get_post_meta( $value, 'right_image', true );
$image_image_position = get_post_meta( $value, 'image_position', true );
$bg_pos = '';
if ( isset( $image_image_position ) && '' !== $image_image_position ) {
if ( '10' === $image_image_position ) {
$bg_pos .= 'background-position: center 10%;';
} elseif ( '20' === $image_image_position ) {
$bg_pos .= 'background-position: center 20%;';
} elseif ( '30' === $image_image_position ) {
$bg_pos .= 'background-position: center 30%;';
} elseif ( '40' === $image_image_position ) {
$bg_pos .= 'background-position: center 40%;';
} elseif ( '50' === $image_image_position ) {
$bg_pos .= 'background-position: center 50%;';
} elseif ( '60' === $image_image_position ) {
$bg_pos .= 'background-position: center 60%;';
} elseif ( '70' === $image_image_position ) {
$bg_pos .= 'background-position: center 70%;';
} elseif ( '80' === $image_image_position ) {
$bg_pos .= 'background-position: center 80%;';
} elseif ( '90' === $image_image_position ) {
$bg_pos .= 'background-position: center 90%;';
} elseif ( '100' === $image_image_position ) {
$bg_pos .= 'background-position: center 100%;';
} elseif ( 'center' === $image_image_position ) {
$bg_pos .= 'background-position: center center;';
} else {
$bg_pos .= 'background-position: center center;';
}
} else {
$bg_pos .= 'background-position: center center;';
}
$background = ( isset( $image_url ) && '' !== $image_url ) ? 'style="background:url( ' . esc_url( $image_url ) . ' ); -webkit-background-size: cover; background-size: cover; background-repeat: no-repeat; ' . $bg_pos . '"' : '';
?>
<div class="slide" <?php echo wp_kses_post( $background ); ?>></div>
<?php
}
Code language: JavaScript (javascript)
You get the point.
This is a really easy way of adding additional fields to your attachments, and saving them. You can add many different fields. For instance you can put an input field with the photographer name, or some copyright information that you’d like show in your gallery for each picture.
I hope you’ll find this tutorial interesting and useful. If you have any questions feel free to post them below, and as always, happy coding : )
Leave a Reply