1

Is there any way to add class to edited posts in order to style them differently? If there is a way to do that without adding a class, this option would be much better.

EDITED - IGNORE THE ABOVE QUESTION - SEE BELOW

Is there a way to add a check box (meta box) in the area that a user writes an article/post so when this is checked a class will be added on the specific post (in loop and in single post page)? If something like this way is impossible, is there a way to get this done with a custom field? If both are possible I would prefer the first way.

4
  • Just to be clear, can you expand on what you mean by "edited." Your question would be clearer if you included an example of a post that would be styled and a post that wouldn't and how those differ. Since CSS depends on classes and ID to differentiate identical markup, I can't imagine a way to do this without a class (other than an ID).
    – mrwweb
    Commented May 14, 2012 at 21:29
  • Lets say I have written a post and made a mistake. So I have edited the post, corrected my mistake and have updated the post. When this is done, I want this specific post to be styled differently in the loop and also in single page (I want to add an icon before the post title).
    – Arg Geo
    Commented May 14, 2012 at 21:34
  • That's useful. Do you want this to happen for even trivial updates like adding an errant comma or removing a blank paragraph at the end of the page?
    – mrwweb
    Commented May 14, 2012 at 21:35
  • It's not right to do this when adding an errant comma or something like that. Your question helped me a loooot. Can I add a check box in the admin area (where user types the article) so he checks if he wants this to happen? Or if that's impossible, can be done with a custom field? I would prefer the first way.
    – Arg Geo
    Commented May 14, 2012 at 21:42

3 Answers 3

1

This is very similar to @mrwweb's answer, but a little bit more fleshed out. We're also not going to overload taxonomies in order to get our post class, but do what you wanted initially: use a custom meta box.

There is a built in template tag called post_class. Like almost every other function in WordPress you can control its output via a filter.

Step one: add the meta box.

This is done via add_meta_box. If you're wondering what the arguments are, you can head on over to the codex -- the docs are very good. The thing to be concerned about is the third argument which specifies a callback function -- the callback is what renders the HTML. To add the meta box we'll hook into add_meta_boxes_post and call add_meta_box.

Here's the whole deal:

<?php
add_action('add_meta_boxes_post', 'wpse52122_meta_box');
/*
 * Adds a meta box on the post editing screen.
 *
 * @uses add_meta_box
 */
function wpse52122_meta_box()
{
    add_meta_box(
        'wpse52122-box',
        __('Add Custom Style', 'wpse52122'),
        'wpse52122_meta_box_cb',
        'post',
        'side',
        'low'
    );
}


/*
 * Callback function for the meta box added above. This is what renders the 
 * boxes HTML.
 *
 * @uses get_post_meta
 */
function wpse52122_meta_box_cb($post)
{
    $meta = get_post_meta($post->ID, '_wpse52122_style', true);
    wp_nonce_field('wpse52122_nonce', 'wpse52122_nonce', false);
    echo '<p>';
    echo '<label for="wpse52122_style">' . __('Edited?', 'wpse52122') . '</label> ';
    echo '<input type="checkbox" name="wpse52122_style" id="wpse52122_style" ' .
         checked($meta, 'on', false) . ' />';
    echo '</p>';
}

Now we need to actually save that stuff when the post is saved. You hook into save_post to do that:

<?php
add_action('save_post', 'wpse52122_save_post');
/*
 * Hooked in `save_post` this is the function that will take care of saving the
 * checkbox rendered above
 *
 * @uses update_post_meta
 * @uses wp_verify_nonce
 * @uses current_user_can
 */
function wpse52122_save_post($post_id)
{
    // no auto save
    if(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) 
        return;

    // can the current user edit this post?
    if(!current_user_can('edit_post', $post_id))
        return;

    // Do we have our nonce?
    if(!isset($_POST['wpse52122_nonce']) ||
        !wp_verify_nonce($_POST['wpse52122_nonce'], 'wpse52122_nonce')) return;

    // if the the box is set, save meta key with 'on' as the value.
    $val = isset($_POST['wpse52122_style']) && $_POST['wpse52122_style'] ?
                'on' : 'off';
    update_post_meta($post_id, '_wpse52122_style', esc_attr($val));
}

Finally, hook into post_class to add your 'edited' class. Your hooked function will get three arguments, we're concerned with the first and last: the array of post classes and the post id respectively.

<?php
add_filter('post_class', 'wpse52122_post_class', 10, 3);
/*
 * Hooked into `post_class` this function adds the class 'edited' to the
 * post_class array if the meta value `_wpse52122_style` is set to 'on'
 *
 * @uses get_post_meta
 * @return array The Post classes
 */
function wpse52122_post_class($classes, $class, $post_id)
{
    if('on' == get_post_meta($post_id, '_wpse52122_style', true))
    {
        $classes[] = 'edited';
    }
    return $classes;
}

Done! All that seems like quite a bit of work, however. So why not just hook into post_class and compare the post_created_gmt and post_modified_gmt?

<?php
add_filter('post_class', 'wpse52122_post_class_alt', 11, 3);
/*
 * Filter the post_class and add the class edited if the post_date_gmt & 
 * post_modified_gmt don't match up.
 *
 * @uses get_post
 * @return array The post classes
 */
function wpse52122_post_class_alt($classes, $class, $post_id)
{
    $post = get_post($post_id);
    if(!$post) return $classes;
    $created = strtotime($post->post_date_gmt);
    $mod = strtotime($post->post_modified_gmt);
    if($mod > $created)
    {
        $classes[] = 'edited-alt';
    }
    return $classes;
}

Here is all of that as a plugin.

5
  • 1
    many thanks for your AWESOME answer. I prefer the first way because I want the user to have the option to do something like that. It wouldn't be nice if this happen when someone correct just a typo.
    – Arg Geo
    Commented May 15, 2012 at 21:26
  • Oh, after doing whatever you told me, the result: Meta box appears, but class is not added. I did everything exactly as you said. Seems to save options when posts are updated but no class applied.
    – Arg Geo
    Commented May 15, 2012 at 22:03
  • Did you copy and paste the code? Or rewrite it? Commented May 15, 2012 at 22:05
  • Oh, I'm stupid! Forgot to add <?php post_class(); ?> in the loop. Tested and worked fine!!! Is there a way to add a column in the posts admin area that says "edited"? Also is it possible to set expiration date (user defines that) so the class "edited" is being removed after the desired date?
    – Arg Geo
    Commented May 15, 2012 at 22:12
  • Yes there is! You should put it in another question. Something like "How to Expire a Post Meta Key". Here's how you add columns to the post list table: justintadlock.com/archives/2011/06/27/… Commented May 15, 2012 at 22:32
0

Basically what you want to do is write either a function, or a small plugin (not so challenging if you know php).

To have you code fired at the right time, you can hook into an action or filter that will happen when a post is updated.

If you are not sure what that means, you should read up on wordpress.org on how to write plugins, and see the Action and Filter API's. The main difference between actions and filters is that a filter lets you change some data. In your case that is interesting, because the filter wp_insert_post_data allows you access to all of the post content and metadata before it is stored in the database.

This means you could use the content to compare to the content that is already stored to see if this is a substantial edit, or just a small one. Of course you could implement a feature where the user can choose, or top it all and do both, like a checkbox that will turn on if the editor content differs by more than 15 characters from the stored post, but will not change state anymore once the user has checked/unchecked it manually.

However I would keep it simple for a first version and just do a comparison in php and add the right class automatically. That is considerably simpler to implement and probably more desirable than needing the user to decide on this consciously.

So, technically it comes down to this:

  1. Create a hook on the wp_insert_post_data filter.
  2. Compare the new content to that already in the database
  3. If changed substantially, add some identifier to the post in the database
  4. In your theme, call post_class to check the database and add the desired class
  5. In your theme css, define a new look for these edited posts

Regarding 3, note that wp doesn't keep classes in the database, they are generated at runtime when pages are generated. You want to keep some durable info linked to the post though, so you need to add something. I think you have the choice between a custom meta field or the existing status field. The latter might have some complications in the sense that if you change articles status from published to edited say, you might have to check what all the consequences of that are. Potentially wordpress code or plugins count on posts being "published" to do certain things.

Now, I don't know what your php skill is. If you need more explanation let me know and I can elaborate those five points in a bit more detail. Otherwise, codex.wordpress.org has all the explanation you need.

Ps: Don't forget that programming is 75% error handling. For example wp_insert_post_data will also fire when a new post is created and obviously checking the database for a previous version will not give you a sensible result to compare with. Things like that should be obvious, but I think for a lot of people they aren't. In essence, think scenarios. Try to conceive all possible input your code could get and try to consciously do the best thing you can in every situation.

1
  • My php skills are not advanced so if this is the only way that can be done, I won't include this feature in my theme. Thanks a lot for you help.
    – Arg Geo
    Commented May 14, 2012 at 23:22
0

A custom meta box with a checkbox field would probably work best, but the easiest solution I can think of is this:

  1. Create an "Edited" category.
  2. Make sure you are using post_class() on the wrapper element of each article/post/page.*
  3. Add a CSS rule that looks for .category-edited class on the post wrapper (or .category-{ID}, which is safer if the "edited" slug ever changes).

The post_class() function (read about it on the Codex) is a template tag used in theme files. It's put on the wrapping element for each post in a loop. It can be on any HTML element, but common ones are div, article (HTML5 only), and li. Using the class looks like this:

<article <?php post_class(); ?>>
    <!-- stuff like the_title() and the_content() goes here. -->
</article>

Post_class() then generates something like "class='post post-23 category-events'".

6
  • I like this solution mrwweb but: 1) I do not clearly understand the no.2 2) In posts i display categories so can i hide this so it will not be displayed?
    – Arg Geo
    Commented May 14, 2012 at 23:38
  • I understand how to do this now. So, a class ".category-edited" will be added. As I told you I display the post categories in every post. How can I hide the category "Edited" that will appear but keep the category applied?
    – Arg Geo
    Commented May 14, 2012 at 23:48
  • You could use a tag or you could register a custom taxonomy and use this snippet to generate the post class.
    – mrwweb
    Commented May 14, 2012 at 23:50
  • I did't ask about post class mrwweb. For example lets say my post has the following categories: Politics - Sports - Cinema. After doing what you said, categories will now be: Politics - Sports - Cinema - Edited. How can I hide the category named "Edited" but still remain attached to the post so the class "category-edited" is still applied.
    – Arg Geo
    Commented May 15, 2012 at 0:02
  • I just wanted to update the post class answer for general clarity. Right now, I can't think of a great way to hide the edited category, hence my last comment about using tags or custom taxonomies instead.
    – mrwweb
    Commented May 15, 2012 at 0:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.