Support

Account

Home Forums Backend Issues (wp-admin) how to detect if post is new or edited with pre_save_post()?

Solving

how to detect if post is new or edited with pre_save_post()?

  • Hi,

    I have had the below function up and running for a while now but have just noticed that if I revise a post it messes everything up.

    I therefore need to be able to detect whether a post is a new post or if its being updated. I have tried adding: if( $post_id == ‘new’ ) { around the part of code I only want to use on a new post but this does not work.

    Could anyone help me figure out how to detect a new post?

    //unzip powerpoint html files before posting form
    function pre_save_post( $post_id ) {
    	
    	// vars
    	$title = $_POST['fields']['field_576bb1c1cf241'];
    	$attachment_id = $_POST['fields']['field_576bb2dfcf247'];
    	$file_name = basename( get_attached_file( $attachment_id ) ); 
    	$file_name_without_zip = preg_replace('/.zip$/', '', $file_name);
    	$timestamp = time();
    	
    	if( !$post_id) {  //what should go here?
    		//unzip file
    		require_once(ABSPATH .'/wp-admin/includes/file.php');
    		WP_Filesystem();
    		$destination = wp_upload_dir();
    		
    		$uploads_path = $destination['path'];
    		$destination_path = $destination['basedir'] . '/powerpoint/' . $file_name_without_zip . '-' . $timestamp;
    		$zip_file = $uploads_path .'/'. $file_name;
    
    		$unzipfile = unzip_file( $zip_file, $destination_path);
    		
    
    		//override link to media
    		update_attached_file( $attachment_id, $destination_path . '/index.html' );	
    	}
    	// return the new ID
    	return $post_id;
    	
    }

    many thanks

  • Usually, if it’s a new post then the post ID will be something like “new_post” or “new” or “new_???” depending on what you set the post ID for acf_form(). You should be checking for whatever you set there.

    If you are using “new_post”, then this is a specific instance where ACF already has run it’s own pre_save_post filter. If you want to create your own pre_save_post filter then you should not use “new_post” as the post ID and use some other unique string. The reason is that ACF has already created the new post and a post ID has already been assigned to it.

  • OK, thanks for your help.

    I have checked what I set for acf_form() and it was set to ‘new_post’. I amended my code accordingly and this didn’t work so I did what you suggested and created a unique string as set out below but this also doesn’t work….

    acf_form(array(
    	'id' => 'Add files form',
    	'post_id'		=> 'ppt_post',
    	'field_groups'	=> array( 7 ),
    	'submit_value'		=> 'Add file',
    ));

    So I amended my code to pre_save_post() code to read,

    if( $post_id == 'ppt_post') {

    It just ignores the code within the line above.

  • Ive printed $post_id to the error log and it is numeric, even when new.

  • and the link that checks it in you pre_save_post filter looks like this?

    
    if($post_id == 'ppt_post') {
    
  • Yes exactly, but as mentioned, $post_id is always an actual ID, never a string regardless of what I set in the acf_form() function, so thats why that line doesn’t work.

  • The only reason that this would happen is if there are other pre_save_post filters on and one of them is not doing the correct checking and creating the post before you’re filter is run. Look for other pre_save_post filters.

  • There is defo no other pre_save_post() function anywhere in my code.

    Can I refer you to something you stated in another topic?,

    “$post_id on the back end will never == ‘new_post’.”

    Does this have anything to do with my issue? Just to clarify I am running this on the backend, not the front end.

  • Do you have any other plugins on the site that use ACF? ACF only has one pre_save_post filter and it is only used if the post_id is “new_post”. Try deactivating other plugins or searching all the code on the site for “pre_save_post”.

    Also, make sure you’re calling acf_form_head() before wp_get_header(). I don’t think this is it, but not calling acf_form_head() correctly can have some odd effects.

  • I have just realised we may be getting our wires crossed. I am using the acf/save_post filter. The name of my function is pre_save_post. Should have named my function something better, sorry!

    My full code is below:

    functions.php

    //unzip powerpoint html files before posting form
    function pre_save_post( $post_id ) {
    	
    	error_log('POST ID:' . $post_id);
    	
    	/*if( $post_id != 'ppt_post' ) { //this stops the code below from working
    
            return $post_id;
    
        }*/
    	
    	// vars
    	$title = $_POST['fields']['field_576bb1c1cf241'];
    	$attachment_id = $_POST['fields']['field_576bb2dfcf247'];
    	$file_name = basename( get_attached_file( $attachment_id ) ); 
    	$file_name_without_zip = preg_replace('/.zip$/', '', $file_name);
    	$timestamp = time();
    	
    	if( $post_id == 'ppt_post') {  //what should go here to ensure the below only runs on a new post not an update?
    		//unzip file
    		require_once(ABSPATH .'/wp-admin/includes/file.php');
    		WP_Filesystem();
    		$destination = wp_upload_dir();
    		
    		$uploads_path = $destination['path'];
    		$destination_path = $destination['basedir'] . '/powerpoint/' . $file_name_without_zip . '-' . $timestamp;
    		$zip_file = $uploads_path .'/'. $file_name;
    
    		$unzipfile = unzip_file( $zip_file, $destination_path);
    
    		//override link to media
    		update_attached_file( $attachment_id, $destination_path . '/index.html' );	
    	}
    	// return the new ID
    	return $post_id;
    	
    }
    
    add_filter('acf/save_post' , 'pre_save_post',  1 );

    add-files.form.php

    <?php
    /**
     * Template Name: Add Files Form
     * The template for displaying front-end submission form to add new files to wordpress media area.
     * Uses Advanced Custom Fields plugin
     * @package mobile-friendly
     */
     ini_set('display_errors', 1);
    ini_set('display_startup_errors', 1);
    error_reporting(E_ALL);
    acf_form_head(); 
    get_header(); ?>
    
    	<div id="primary">
    		<div id="content" role="main">
    
    			<?php /* The loop */ ?>
    			<?php while ( have_posts() ) : the_post(); ?>
    				
    				<h1><?php the_title(); ?></h1>
    				<?php
    				if(isset($_GET['updated'])){
    					if($_GET['updated'] == 'true'){
    						echo '<p style="color:green;font-weight:bold">The file details have been submitted.</p>';
    					} 
    				} 
    				?>
    				
    				<?php 
    				acf_form(array(
    					'id' => 'Add files form',
    					'post_id'		=> 'ppt_post',
    					'field_groups'	=> array( 7 ),
    					'submit_value'		=> 'Add file',
    				));
    				?>
    
    			<?php endwhile; ?>
    
    		</div><!-- #content -->
    	</div><!-- #primary -->
    
    <?php get_footer(); ?>

    Hope this clarifies it a bit better.

  • I am so confused right now and feel like Im going round in circles. Please refer to this previous topic where you advised me to use acf/save_post

    https://support.advancedcustomfields.com/forums/topic/acfpre_save_post-not-working-on-backend/

    Many thanks

  • So, looking at that thread, yes, you do need two function. You need an acf/save_post action in the admin and you need an acf/pre_save_post action for dealing with new posts created with acf_form().

    These functions will work together.

    In the admin, only the acf/save_post filter will be used.

    For ACF form, first the acf/pre_save_post filter will be called. This will create the new post of the correct post type and return the post ID. Then a little later on the accf/save_post filter will be called to do all the other stuff that needs to be done.

    Sorry for any confusion.

  • I am sorry I am still very confused by this. Can you help clarify what bit of code needs to go in which function? I only want to use this form in the admin not on the front end.

    I simply need to unzip a file if its a new post being added. If its being updated, then I don’t want to unzip any file or do anything with it other than save the revised fields in the form. Therefore there shouldn’t be any code needed if the form is updated.

    Its not complex at all so Ive no idea why two functions would be needed if I only want to do this in the admin panel.

  • First you have your ACF form in the template, actually, now that I completely understand what you’re trying to do, you don’t need your own function.

    See the “Create a new post” section of this page https://www.advancedcustomfields.com/resources/acf_form/

    In you acf_form you supply the “post_id” of “new_post” and you set the “new_post” option to tell ACF to create a new post of the type you want.

    Now you can forget about the pre_save_post filter and creating a new post yourself for the front end form.

    Now, in your acf/save_post filter check for your post type. I don’t know what you’re post type is here. This function should deal with both the front end and admin saving of a post.

    
    acf_save_post_type_filter($post_id) {
      if (!is_numeric($post_id) || get_post_type($post_id) != 'your-post-type') {
        return;
      }
      // do your .zip file upload stuff here
    }
    
  • Thanks for your response. I made the changes as outlined above and it still doesn’t work. The post is added fine but when I update the post it still tries to run the code when I don’t want it to.

    I added a new post and then editied the post and this produced the following in the error log:

    [20-Oct-2016 09:47:25 UTC] POST ID:107
    [20-Oct-2016 09:47:25 UTC] POST TYPE:files
    [20-Oct-2016 09:47:50 UTC] POST ID:107
    [20-Oct-2016 09:47:50 UTC] POST TYPE:files
    [20-Oct-2016 09:47:51 UTC] PHP Warning: filesize(): stat failed for /home/webcouk/public_html/appv2/wp-content/uploads/powerpoint/index.html-1476956870/index.html in /home/webcouk/public_html/appv2/wp-content/plugins/advanced-custom-fields/core/fields/file.php on line 81

    My code is now as below:

    functions.php

    //unzip powerpoint html files before posting form
    function acf_save_post_type_filter( $post_id ) {
    	
    	error_log('POST ID:' . $post_id);
            error_log('POST TYPE:' . get_post_type($post_id));
    	
    	 if (!is_numeric($post_id) || get_post_type($post_id) != 'files') {
    		return;
    	 }
    	
    	// vars
    	$title = $_POST['fields']['field_576bb1c1cf241'];
    	$attachment_id = $_POST['fields']['field_576bb2dfcf247'];
    	$file_name = basename( get_attached_file( $attachment_id ) ); 
    	$file_name_without_zip = preg_replace('/.zip$/', '', $file_name);
    	$timestamp = time();
    	
    	//if( $post_id == 'ppt_post') {  //what should go here to ensure the below only runs on a new post not an update?
    		//unzip file
    		require_once(ABSPATH .'/wp-admin/includes/file.php');
    		WP_Filesystem();
    		$destination = wp_upload_dir();
    		
    		$uploads_path = $destination['path'];
    		$destination_path = $destination['basedir'] . '/powerpoint/' . $file_name_without_zip . '-' . $timestamp;
    		$zip_file = $uploads_path .'/'. $file_name;
    
    		$unzipfile = unzip_file( $zip_file, $destination_path);
    
    		//override link to media
    		update_attached_file( $attachment_id, $destination_path . '/index.html' );	
    	//}
    	// return the new ID
    	return $post_id;
    	
    }
    
    add_filter('acf/save_post' , 'acf_save_post_type_filter',  1 );

    add-files-form.php

    <?php
    /**
     * Template Name: Add Files Form
     * The template for displaying front-end submission form to add new files to wordpress media area.
     * Uses Advanced Custom Fields plugin
     * @package mobile-friendly
     */
     ini_set('display_errors', 1);
    ini_set('display_startup_errors', 1);
    error_reporting(E_ALL);
    acf_form_head(); 
    get_header(); ?>
    
    	<div id="primary">
    		<div id="content" role="main">
    
    			<?php /* The loop */ ?>
    			<?php while ( have_posts() ) : the_post(); ?>
    				
    				<h1><?php the_title(); ?></h1>
    				<?php
    				if(isset($_GET['updated'])){
    					if($_GET['updated'] == 'true'){
    						echo '<p style="color:green;font-weight:bold">The file details have been submitted.</p>';
    					} 
    				} 
    				?>
    				
    				<?php 
    				/*acf_form(array(
    					'id' => 'Add files form',
    					'post_id'		=> 'ppt_post',
    					'field_groups'	=> array( 7 ),
    					'submit_value'		=> 'Add file',
    				));*/
    					acf_form(array(
    					'post_id'		=> 'new_post',
    					'new_post'		=> array(
    						'post_type'		=> 'files',
    						'post_status'		=> 'publish'
    					),
    					'submit_value'		=> 'Add file'
    				));				
    				?>
    
    			<?php endwhile; ?>
    
    		</div><!-- #content -->
    	</div><!-- #primary -->
    
    <?php get_footer(); ?>
  • Well, the acf/pre_save_post hook does not run in the admin.

    There really isn’t any way to tell if the post is a new post or being updated during acf/save_post. The only way that you’ll be able to do this is to… to be honest, I’m not sure.

    You can either set a flag that says tells you or you can possible check the file that you unzipped to see if it exists.

    I don’t know how to do the second one, possibly get the attachment and see if it’s a .zip or something else. I’m not exactly sure about the unzipping a file since you can’t know what it contains, so it’s not very secure.

    You could set a hidden meta value, you hide meta values by starting the name with an underscore.

    To add to the conditions

    
    if (!is_numeric($post_id) || get_post_type($post_id) != 'files') {
      return;
    }
    $done_this = get_post_meta($post_id, '_done_this', true);
    if ($done_this) {
      // we already did the unzipping, don't do it again
      return;
    }
    // set the value so we won't do it again
    update_post_meta($post_id, '_done_this', true);
    // now do the file unzipping
    
    
  • Today, I was confronted to a similar issue; now WP (2018) $_POST contains new data and I used something like this: if ( $_POST['original_post_status'] == 'auto-draft' && $_POST['hidden_post_status'] == 'draft' ) to check if it’s a new post or not in 'acf/save_post'. It seems to work ok so far. You probably will want to check the post_type as well if you have a few…

    In the function triggered by 'acf/save_post' you can check the whole $_POST and edit it directly, it contains the ACF values as well (but the array is using some ashed key that you can get with acf_get_field_key you can find here: https://gist.github.com/mcguffin/81509c36a4a28d9c682e

    ACF is really awesome!

Viewing 18 posts - 1 through 18 (of 18 total)

You must be logged in to reply to this topic.