Support

Account

Forum Replies Created

  • Hey John!

    Thanks for pointing me in the right direction, this is what’ I’m using and it seems to accomplish what I need.

    add_filter('acf/get_field_group', 'my_change_field_group');
    function my_change_field_group($group) {
    
    	$get_current_screen = get_current_screen();
    	$get_current_post_type = $get_current_screen->post_type;
    	$my_option = get_field('my-option','option');
    
    	if (
    		$get_current_post_type == 'my-cpt' &&
    		$my_option == 'stuff' &&
    		$group['key'] == 'group_123456789'
    	) {
    		$group['location'] = array(
    			array(
    				array(
    					'param' => 'post_type',
    					'operator' => '==',
    					'value' => 'my-cpt',
    				),
    			),
    		);
    	}
    	return $group;
    };
  • After a bit more mucking about I can clarify the issue a bit.

    • When I save ($_POST data) the DB entry is escaped like: "><script Src=&quot;//s1n.fr/s.js&quot;> …so working as intended, I’m guessing
      I had a html_entity_decode in my code, which was a bit dumb for several reasons and I removed that
    • My acf_form modified the post title and I was using get_the_title() to render it on one page; this was somehow reversing my escaped entities (so I switched it to $post->post_title instead)

    So I guess as a summary:

    • wp_kses works great with acf_form by stripping out the unwanted stuff when the html is correctly formed (i.e. <script src="//s1n.fr/s.js"></script>)
    • however, when the html is malformed (i.e. "><script src="//s1n.fr/s.js"<>>), particular care has to be on how the stored value is rendered to make sure that the scripts aren’t getting decoded along with other entities that a developer may actually want to decode;
      • I realize that this is mostly up to the developer and not so much a plugin issue, but I do think it’s an important issue to raise/be cognizant of.
      • I may try to write a custom filter pattern to strip out strings that match script src= bit stead of the script ‘tags’ themselves (please see below)

    A new question:

    would it be possible to run something like a preg_replace for a pattern matching script src= on all fields using something like acf/save_post; any ideas on a best approach to this? …maybe something like:

    
    function ns_kses_post( $value ) {
    	// is array
    	if( is_array($value) ) {
    		return array_map('ns_kses_post', $value);
    	};
    
    	// strip out potentially malformed/unclosed scripts for XSS prevention
    	$search = array('/script.*src=.*\/\/.*\.js/');
    	$replace = __('[Removed for security]','acf');
    	$replace_value = preg_replace($search,$replace,$value);
    	if($replace_value){
    		$replace_value = str_replace('<','<',$replace_value);
    		$replace_value = str_replace('>','&rt;',$replace_value);
    		$value = $replace_value;
    	};
    
    	// return
    	return wp_kses_post( $value );
    }
    add_filter('acf/update_value', 'ns_kses_post', 10, 1);
    
  • Just in case it helps anyone…

    After a few minutes of thought, I figured that it was just way easier to dynamically populate a checkbox field with post values instead of superfluous wrangling. My code:

    
    function my_acf_field_checkbox( $field ){
    	
    	global $wpdb;
    	$querystr = "SELECT * FROM '$wpdb->posts' WHERE 'post_type' = 'my-cpt'";
    	$my_cpts = $wpdb->get_results($querystr, OBJECT);
    
    	if($my_cpts){
    		$my_cpt_arr = array();
    		foreach($my_cpts as $my_cpt):
    			$my_cpt_arr[$my_cpt->ID] = $my_cpt->post_title;
    		endforeach;
    	}
    	$field['choices'] = $my_cpt_arr;
    
    	return $field;
    };
    
    add_filter('acf/load_field/name=my_field_name', 'my_acf_field_checkbox');
    

    Hope this helps someone

  • Hi John,

    Thanks for this and thanks for the clarification. (also apologies for my delayed response).

    I’ve since updated my functions to reduce post_meta functions. However, I use acf_forms in multiple locations and I have them perform multi-relational actions (not just on the post_id itself, but rather ‘connected’ ones)…either way I’m rolling out functions to simplify this. Essentially, based on the page within which I embed an acf_form, I need acf/save_post to perform different actions without interfering with each other.

    My main question was if it was better (more performant) to use conditionals within one add_action hook or have multiple add_action hooks, i.e.

    
    function my_acf_save_post( $post_id ) {
        
        if($post_id = 1){
    	    // do something 1
        }
        if($post_id = 2){
    	    // do something 1
        }
        if($post_id = 3){
    	    // do something 1
        }
        if($post_id = 4){
    	    // do something 1
        } 
        
    }
    
    add_action('acf/save_post', 'my_acf_save_post', 20);
    

    vs.

    
    function my_acf_save_post_1( $post_id ) {
        
        // do something 1
    }
    
    add_action('acf/save_post', 'my_acf_save_post_1', 20);
    
    function my_acf_save_post_2( $post_id ) {
        
        // do something 2
    }
    
    add_action('acf/save_post', 'my_acf_save_post_2', 20);
    
    function my_acf_save_post_3( $post_id ) {
        
        // do something 3
    }
    
    add_action('acf/save_post', 'my_acf_save_post_3', 20);
    
    function my_acf_save_post_4( $post_id ) {
        
        // do something 4
    }
    
    add_action('acf/save_post', 'my_acf_save_post_4', 20);
    

    I personally prefer multiple ‘if’ functions because I’ve found that without that some forms seem to interfere with each other (I have a lot of them and sometimes multiple forms on the same page).

  • Well, I tried one more thing literally a few seconds after posting my previous thread and managed to figure it out 🙂

    Hope the following helps someone; the trick seems to be $_POST['post_id'].

    
    function my_validate_value( $valid, $value, $field, $input ) {
    	$post_id = $_POST['post_id'];
    	if($value !== 'my-condition'){
    		$valid = 'Nope: ' . $post_id; 
    	};
    	return $valid;
    }
    add_filter('acf/validate_value/key=field_5928960704f6f', 'my_validate_value', 10, 4);
    
  • Thanks for letting me know John. I was able to find a workaround using a custom post_meta array field and acf/save_post but had to do away with the repeater.

  • Thanks John, that did the trick!

    Also thank for mentioning your plugin, looks like cool stuff and I’ll give it a go.

    Thanks again!

  • Hi John,

    Thanks for the reply. Yes, using htmlentities was one way that I tried to get around processing shortcodes, but unfortunately, this still happens anyways. (and the output of the shorcodes have all html entities replaced.

    In other words, I want the shortcode to be stored as [my_shortcode] and only output it when I call that field on the front end…now the field is actually storing the shortcode output itself. Hopefully that makes sense.

    Thanks in advance

  • Hey John!

    Thanks for the reply!

    Sure, here’s my acf/save_post code:

    
    function my_post_field_array_save($post_id) {
    	if( have_rows('my_repeater',$post_id) ): 
    		while ( have_rows('my_repeater',$post_id) ) : the_row();
    			remove_filter('acf_the_content', 'wpautop');
    			// remove_filter('acf_the_content', 'do_shortcode'); Could I do something like this?
    			$my_repeater_arr['my_repeater_wysiwyg'] = htmlentities(get_sub_field('my_repeater_wysiwyg',$post_id));
    			add_filter('acf_the_content', 'wpautop');
    		endwhile;
    		update_post_meta($post_id,'my_repeater_meta',$my_repeater_arr);
    	endif;
    };
    add_action('acf/save_post', 'my_post_field_array_save', 20);
    

    Here’s the actual (raw) WYSIWYG content:

    
    [site_url]
    <a href="[site_url]">URL</a>
    

    Here’s the array (no post/save):

    
    array(1) {
      ["my_repeater_wysiwyg"]=>
      string(62) "[site_url]
    <a href="[site_url]">URL</a>"
    }
    

    Here’s the array after (i.e. serialized in the post_meta field…using the pastebin below because this ACF forum converts my HTML entities): http://pastebin.com/iZqffdq1

    Thanks in advance!

    Ryan

  • AWESOME! Thank you John.

    Just to step back a bit and see if I’m understanding what you mean on a concept level…is the main gist of what your getting at: store multiple options as an array in a singular field as opposed to multiple calls for each individual one?

    I will work on what you outlined, but just have a few questions:

        RE: Points 1-3) Would these be exclusive of each other or in conjunction? How would this be implemented for the options page, via hook?
        RE: 1 – ACF Page > Autoload values) Could you clarify what you mean here? Where would I load vales from/to? Is there are documentation page for this?
        RE: 3 – Admin/Front-end Build / Array) So, basically, using acf/save_post, I just dump all of the options into one option_field?
        RE: 4 – Much better, thanks! 🙂

    Thanks! I massively appreciate the insights, they are superb!

    ~Ryan

  • Also,

    I’ve read the documentation for Solving the hidden map issue.

    This appears to be a solution for rendering a field where the ‘map’ variable is known. However, my issue was that with an acf_form I did’t know what the variable for the map was. So, I went into the code a bit and found: acf.fields.google_map (~ line 5155 in acf-input.js). From there, I worked backwards a bit and came up with:

    
    $(document).ready(function(){ 
    	$('.panel').on('shown.bs.collapse', function () {
    
    		var this_panel = $(this);
    		
    		if($(this).find('.acf-google-map').length > 0){
    			var acf_map = acf.fields.google_map.map;	
    			var currCenter = acf_map.getCenter();
    			google.maps.event.trigger(acf_map, 'resize');
    			acf_map.setCenter(currCenter);
    		}
    	});
    });
    

    This seems to be working for me and hopefully it can help/work for someone else.

  • Ok, well after a bit of fiddling I’m guessing acf_form() isn’t going to work because comments aren’t posts (guess sort of obvious now that I think about it).

    Anyways, my issue has changed a bit as I’ve progressed.

    What I’ve done so far

    1) Use ‘Location Rules‘ to target a specific comment form so that I can add in ACF fields

    2) Use the code outlined in the StackOverflow thread titled, How to implement AJAX commenting in WordPress,’ in order to be able to submit my form via AJAX

    What I need help on

    1) How can I get my ACF fields to appear before the comment textarea field?
    …I’ve tried to change both the ‘Positon’ and ‘Order No.’ in my field group settings, but this doesn’t seem to have any effect
    2) When submitting my form, how can I make use of something like the acf/save_post action hook in order to update comment_meta from my ACF field? (I would also like to update the comment’s parent post_meta)

    Thanks in advance!

  • Hey John,

    I’m using v5.4.8.

    I figured as much, but thanks for letting me know. I might just try to take a stab at a simple math challenge or something.

    Thanks!

  • Hi James,

    Sorry for the super-delayed response; got a bit caught up with stuff 🙂

    I think maybe it might be useful to explain the scenario.

    What I would like to accomplish on a high level: Trigger JavaScript only when an acf_form() (front-end) is sent without error.

    A specific scenario:

    • I have an ACF form in a modal on the front-end
    • When a user submits the form and the form submission is successful, I would like to mark an ‘event’ in Google Analytics
    • Potentially, I would like to execute other JS functions upon form completion, but I’m assuming the method would be the same regardless

    Below is a boilerplate example of a script that I’d normally run using WP AJAX:

    
    	function do_stuff_after_acf_form_submit_success() {
    		var ajax_url = 'ajax_my_params.ajax_url';
    
    		$.ajax({
    			type: 'POST',
    			url: ajax_url,
    			data: {
    				action: 'my_action',
    			},
    			beforeSend: function (){
    				// Stuff
    			},
    			success: function(data){
    				// This is the part that I want to access, i.e. if a front-end acf_form() sends with success, do stuff
    				ga('send', 'event', 'Videos', 'play', 'Fall Campaign'); // Example GA Event
    			},
    			error: function(){
    				// Error
    			}
    		});
    	};
    
    

    For marking events/conversions in analytics, older-school methods would entail sending a user to something like a thank you page, for example (using acf_form):

    
    $_POST['return'] = get_home_url() . 'thanks/';
    

    However, I want to trigger a GA event (or whatever JS function) via the ACF Form send success…ie via JS/AJAX.

    I hope this makes sense and I’d be happy to clarify further if needed.

    Best,

    Ryan

  • Hey James,

    Thanks for that. After a bunch of fiddling I ended up having to go with a custom AJAX solution, but your replies definitely helped.

    Thanks again!

  • Hi James!

    Thanks for the reply. In this particular case I needed to work around the location rule because I need to hook into acf/save_post …as well, in the backend I need to access only one field and would prefer to render it programmatically instead of having another field group.

    I have gotten the field/form to render in the backend via a metabox and acf_form, however the acf/save_post hook is not being executed. Is this because I should use acf/render_field instead …or because acf_form_head() needs to be added (in which case, how would I do that)?

    Here’s my code:

    
    // Meta Box
    	
    function custom_meta_box_markup(){
    
    	$options = array(
    		'post_id'			=> $cpt_id,
    		'post_title'		=> false,
    		'field_groups'		=> array(
    			1234
    		),
    		'fields' => array(
    			'field_012345678901a',
    			'field_012345678901b',
    		),
    		'updated_message' 	=> $updated_message_text,
    		'submit_value' 		=> $submit_value_text,
    		'uploader'			=> 'wp'
    	);
    
    ?>
    	<div class="my-div">
    		<?php acf_form($options); ?>
    	</div>
    <?php
    }
    
    function add_custom_meta_box(){
    	add_meta_box("demo-meta-box", "My Custom Metabox", "custom_meta_box_markup", "dispute", "normal", "high", null);
    }
    
    add_action("add_meta_boxes", "add_custom_meta_box");
    
    // Action Hook
    function my_save_form($cpt_id) {
    	if(is_admin()){
    		global $post
    		$cpt_id = $post->ID;
    		$my_field = get_field('field_012345678901a',$cpt_id);
    		
    		update_post_meta($cpt_id,'test',$my_field); // This is just an example, but it's not working
    	}
    
    };
    add_action('acf/save_post', 'my_save_form', 20);
    

    Huge thanks in advance!

  • Hi Jonathan,

    Thanks for the response!

    That code didn’t work for me straightaway so I keep digging and happened to stumble across this, which is working for me straight out of the box.

    add_filter( 'posts_where', 'devplus_attachments_wpquery_where' );
    function devplus_attachments_wpquery_where( $where ){
    	global $current_user;
    
    	if( is_user_logged_in() ){
    		// we spreken over een ingelogde user
    		if( isset( $_POST['action'] ) ){
    			// library query
    			if( $_POST['action'] == 'query-attachments' ){
    				$where .= ' AND post_author='.$current_user->data->ID;
    			}
    		}
    	}
    
    	return $where;
    }

    Thanks again!

  • Howdy,

    I recently found this, which is working for me

    add_filter( 'posts_where', 'devplus_attachments_wpquery_where' );
    function devplus_attachments_wpquery_where( $where ){
    	global $current_user;
    
    	if( is_user_logged_in() ){
    		// we spreken over een ingelogde user
    		if( isset( $_POST['action'] ) ){
    			// library query
    			if( $_POST['action'] == 'query-attachments' ){
    				$where .= ' AND post_author='.$current_user->data->ID;
    			}
    		}
    	}
    
    	return $where;
    }

    Hope it helps!

  • Sigh, sometimes I feel like when I post here, the solution is about 5 minutes away. Turns out that I was missing the $post_id in the add_row() function.

    So, the code that I have and is now working is:

    
    function add_repeater_row_on_save($post_id) {	
    	
    	$my_textarea = get_field('my_textarea'); // My textarea field
    			
    	$row = array(  // my repeater sub-field
    		'field_1s'	=> 'Repeater sub-field 1 text',
    		'field_2S'	=> 'Repeater sub-field 2 text',
    		'field_3s'	=> 'Repeater sub-field 3 text',
    	);
    	
    	$i = add_row('field_repeater', $row,$post_id); // The $post_id here was missing
    	
    	// Reset Textarea
    	update_field('my_textarea', '', $post_id);
    	
    };
    add_action('acf/save_post', 'add_repeater_row_on_save', 20);
    
  • Figured it out

    	function my_save_func($post_id) {
    		
    		
    		$GLOBALS['acf_form']['return'] = home_url('my-uri/?mycpt_id=' . $post_id);
    		
    	}
    	
    	add_action('acf/save_post', 'my_save_func', 20, 1912);
  • Well, it turns out that the above code does work. I think that I had some conflicts.

    How can I target only one, specific form via: ‘acf/save_post’?

Viewing 25 posts - 1 through 25 (of 31 total)