• I’m trying to create a function on my theme’s functions.php file that accomplishes that goal.

    I want the editor to prevent saving or updating new posts when certain characters are used on the editor. Characters like non-breaking space, certain brackets and aposthrophes and encoded html entities.

    I’ve managed to create a function to sanitize the input after the post was saved to the database, getting rid of all these undesired characters. I did this by writing a function that includes

    $wpdb->update('wp_posts', ['post_excerpt' =>$sanitized_post_excerpt], ['id' => $post_id]);

    and then adding the function as a hook to save_post:

    add_action('save_post', 'sm_sanitize_HTML_entities', 99, 3);

    Is there a way to prevent the input of the characters being saved (maybe even displaying a message to the user), rather than updating a sanitized version of the data after it’s already been saved?

Viewing 5 replies - 1 through 5 (of 5 total)
  • Moderator bcworkz

    (@bcworkz)

    Hooking ‘save_post’ to alter DB data that had just been saved makes the update vulnerable to a race condition because it takes longer to write the data than it takes PHP to execute ‘save_post’ callbacks. You could be altering existing data instead of newly saved data. Then the new data overwrites you changes.

    It’s better to alter the data before it’s saved through the ‘wp_insert_post_data’ filter.

    Another possibility would be to alter how wp_kses() works through its various filters. Post content is already filtered through this function. It could possibly be modified to also filter out what you don’t want in content.

    Yet another approach would be to validate post content client side before it’s even saved. This would require custom JavaScript code that runs after some DOM event like clicking “Publish” or “Update”.

    Thread Starter ftroitero

    (@ftroitero)

    Thanks for the reply.

    I tried using wp_insert_post_data, replacing

    add_action('save_post', 'sm_sanitize_HTML_entities', 99, 3);

    with

    add_filter( 'wp_insert_post_data', 'sm_sanitize_HTML_entities', 99, 3 );

    while keeping my function the same. This caused the post to stop updating. Unfortunately, I have no idea why this might have happened nor how to work around it.

    Then I followed the last option you mentioned in your kind reply and tried to implement a JS solution.

    function sm_test() {
    		echo "
    		<script>
    		jQuery('body').on('click', '.editor-post-publish-button__button', function(event) {
    			let button = this;
    			button.disabled = true; //setting button state to disabled
    			event.preventDefault();
    			alert('Hello! I am an alert box!!');
    			return false;
    		});
    		</script>";
    }
    
    add_action('admin_footer-post.php', 'sm_test');

    Miraculously, I managed to display an alert after clicking on the “Update” button.

    And then I tried to disable the save button. This was in the hope of being able to save the post conditionally according to the post content containing invalid characters or not. This obviously failed and the post is still being saved after clicking.

    Where could I go from here? I believe validating post content on the client side before it’s even is what I’m looking for but I will settle for any other strategy that “works”.

    Is it possible to prevent saving conditionally with a JS script as I was trying to do?

    I also came up with this beautiful article about preventing post publishing on the condition of having a large enough image attached, by using “transitation_post_status”
    https://wpshout.com/stop-post-publishing-php/

    The thing is my condition is not having invalid characters, rather than having an image attached or not.

    • This reply was modified 3 years, 6 months ago by ftroitero.
    Moderator bcworkz

    (@bcworkz)

    AFAIK status transition fires after a post is published/updated. I don’t see how that could stop the DB update. Even if it works, dying to prevent something is an inelegant solution 🙂

    I would have expected .preventDefault() to prevent a publish/update. In any case, JS can be disabled, so you’d want a server side backup to prevent publishing as well. Client side processes are for improved UX. Secure processes need to happen server side. In this case, I have no problem with dying since someone had to workaround JS to get to that point. They don’t need a nice UX 🙂

    I still think ‘wp_insert_post_data’ should work for you. I believe the problem you encounter has to do with your callback function. It’s apparently not returning values in a manner acceptable to the filter hook? The return should be an associative array of post data in the same form as it was initially passed. Only the element values should be altered, maintaining types as passed.

    Thread Starter ftroitero

    (@ftroitero)

    Your knowledge and pedagogic ability know no boundaries.

    My callback function was not returning the proper values. Once I had a better understanding on how add_filter and wp_insert_post_data work, I could use them to sanitize data.

    function sm_sanitize_title( $data, $postarr, $unsanitized_postarr){
        $data['post_title'] = html_entity_decode($data['post_title']);
    	
    	$quotationMarks = array ('/«/','/‹/','/»/','/›/','/','/‛/','/❛/','/❜/');
    	$data['post_title'] = preg_replace($quotationMarks, '"', $data['post_title']);
        return $data;
    }

    add_filter( 'wp_insert_post_data', 'sm_sanitize_title', 1, 3 );

    I could also implement a JS script to validate input on the client side

    function sm_validate_title_client_side() {
    		echo "
    		<script>
    		jQuery('body').on('focus', '[contenteditable]', function() {}).on('paste input', '[contenteditable]', function() {
    			let title = event.target.innerText;
    			let inputIsValid = !title.includes(String.fromCharCode(160));
    			let button = document.querySelector('.editor-post-publish-button__button');
    			if (!inputIsValid) {
    				button.disabled = true; //setting button state to disabled;
    				alert('invalid input');
    			} else {
    				button.disabled = false;
    			}
    		});
    		
    		</script>";
    }
    
    add_action('admin_footer', 'sm_test');
    Moderator bcworkz

    (@bcworkz)

    Nicely done!

    Your knowledge and pedagogic ability know no boundaries.

    Apparently you found the boundary, I sheepishly admit that I had to look up “pedagogy” to remind myself what it is. While I once knew of it, it wasn’t coming back to me today. Memory fails more than I like to admit. I appreciate the compliment though 🙂

Viewing 5 replies - 1 through 5 (of 5 total)

The topic ‘WordPress text editor input validation. Prevent save when certain characters are’ is closed to new replies.