save_post and making post_title required (with appropriate $message)

I'm putting together a plugin that checks to make sure certain fields are populated on save (read: hook / action save_post). For example, category is required. I check the $_POST and render a message (via filter: post_updated_messages). For catgory and others it works just fine :slight_smile:

However, if I check $_POST['post_title']. with this (code) things get a bit wonky.

protected function my_title_required($msg_id = NULL){
global $wpdb, $post;
if ( !isset($_POST['post_title']) || empty($_POST['post_title']) || $_POST['post_title'] == false ){

$wpdb->update( $wpdb->posts, array( 'post_status' => 'pending' ), array( 'ID' => $post->ID ) );
$this->message_id = $msg_id; // the message_id property pass the msg_id to the method hooked to post_updated_messages
add_filter( 'redirect_post_location', array($this, 'location_add_query_arg_message'));
return 'break';
} // close if
} // close method

In case you're wondering, I return a 'break' because the validation methods are called from an array and if I hit an error I want to break from that foreach.

In short, the above doesn't work. I do get a 'break' back when the post_title is blank, but the $wpdb->update doesn't seem to work right, and the redirect_post_location doesn't force a message to be displayed.

I've also noticed that if there's a value in the title from a previous save and I then make the title blank, WP will not allow that. The save reverts the title back to its pre-blanked out value.

Obviously, WP does something with the post_title that effects what I can do - at least given my current approach.

Question 1: What is WP doing?

Question 2: And how can I get around that so I can display an error message that says "Post Title required". Mind you, some might say that should be understood but a good UX - especially with regards to form validation - should be as crisp and clear as possible, yes?

If I was detailed / clear enough please let me know and I'll resolve anything that needs additional clarity.

thx
mfs

  • Alexander

    @ChiefAlchemist,

    In this case, there are several routines setup to properly sanitize the values of fields. Alot of this title stuff happens behind the scenes, and it's really meant to be that way, and we shouldn't need to understand in detail what's happening at these levels when Wordpress gives us APIs to work with, and hooks to enter the system at just about any point.

    For example, rather than checking the superglobals directly to see if something was set, you can hook a filter for it. Checkout this file:

    http://svn.automattic.com/wordpress/tags/3.6/wp-includes/post.php

    Look for the sanitize post field function. You'll see this line:

    $value = apply_filters("{$field_no_prefix}_save_pre", $value);

    This means we can do:

    add_filter('title_save_pre','sanitize_title_callback');
    function sanitize_title_callback($value) {
    if($value=="") {
    //Do something
    }
    
         return $value;
    }

    I've not tested this code out, but it would be an ideal place to catch the value of the title.

    Best regards

  • ChiefAlchemist

    Interesting idea. I'll give it a shot. Thx.

    As long as the filter runs later (after WP is done doing what it does) rather than sooner then I should be able to sort something out for post_title. I just hope it's pre-save to the DB. Obviously, I'm validating to keep the DB content clean and in order.

    For anything else, I think it's still best to use the actual form data in a proactive way.

    btw, why do you think the title reverts when I try to blank it out?

  • Alexander

    This specific hook happens during the sanitization of all keys before they are stored in the database.

    As for the title reverting, it's likely because you're not modifying it appropriately.

    Your code might run too late. If so, the title has already been processed by Wordpress. You can still check the superglobal and do what you like, but the title is out of your hands

    Or your code runs too early. If you're going in too early, you might be updating the title to blank, but this might not be the actual title and only a representation of it. Or you're writing to the database, and when you abort, Wordpress persists the old version back. I don't know specifically

    Now keep in mind that the actual post exists moments after you click the "Add New" button whether or not you save it at all. Wordpress will make an ajax request to create a new post. It gets a post ID back that it will use for any subsequent edits.

    Wordpress has classes and a particular data-structure setup for interacting with these posts, also lead to conflicts in later versions of Wordpress as you don't have any security.

    Wordpress APIs and hooks are how you can create sustainable plugins. It adds a level of abstraction - this way the Wordpress core is free to refactor and create low level changes without affecting how plugins interact.

    Typically the higher your plugin runs in terms of abstraction, the more longevity it will have. Introducing code that interacts at lower levels is hard to debug and troubleshoot.

    Best regards

  • ChiefAlchemist

    Thanks Alexander.

    The filter was close / closer but best I can tell, not quite spot on. I'm still experimenting but I figured I'd fill you in on what I'm seeing so far (and maybe you can add your thoughts).

    Basically, I can use the title_save_pre filter to trigger the filter 'redirect_post_location' and get the $message "Post title is required" to display.

    However, it appears (to me) that if the filter returns with the title either not being modified or I set the title to '' (empty) a couple things happen.

    1) When I do Posts > Add New and do not check for the current status (i.e., it's a new / emply post) and just let the filter run, my meta boxes get screwed up. Categories and Tags meta boxes are gone, and the Format box stays but all the formats (radio list) goes MIA.

    2) If I then save that (read: hit the Publish button), WP assigns the value "Auto Draft" to the title and the meta boxes come back. Unfortunately, now the title has a value - bogus or not - and I can't check for no value. I suppose I could check for Auto Draft and some other conditions (because technically, the title would be Auto Draft) but that seems like a whole lotta work for something that seems to me should be standard. In other words, plain ol' WP should say "Hey! You need a title if you want to publish this."

    Or am I wanting / expecting a better UX than WP is capable of? :slight_smile:

    p.s. Is it just me, but in this particular instance, filters and the timing of hooks make OOP / methods feel odd, if not awkward. I'm saving. I want to do "X" on save_post. Now it feels like I have to have a work around as well. Mind you, this is not a complaint. I just feel like there's got to be a more reasonable way to do this, but maybe not? :slight_frown:

    Thanks again. I hope you have a moment to kick back some more ideas on what I've seen above.

  • Alexander

    Hi @ChiefAlchemist,

    I'm sorry for the delay here. I have a few more thoughts.

    Honestly, the method we're using here is more of a hack as we're coming in during sanitization. The best solution here would be a simple javascript validation on the front end. You could attach a click handle to the publish/update button - then have it check for appropriate data before allowing the submit action to be performed. This would be perfectly fine because the database is already sanitizing everything and doing enough validation of it's own. There really isn't a reason this needs to be done on the server.

    Best regards,

Thank NAME, for their help.

Let NAME know exactly why they deserved these points.

Gift a custom amount of points.