Home Forums WC Vendors Pro Support Custom Taxonomy Saving Improperly

NOTICE: We've Moved to a Ticket System for Support

As of August 31, 2017 (12am EST) our support forums will be retired (read-only), and we will be moving to a support ticket system.  This will allow us to better organize and answer support requests, and provide a more personalized experience as we assist our customers.

For the time being, we will leave our forums open for reading and learning while we work on creating a more robust Knowledge Base for everyone to use.

If you are a WC Vendors Pro customer please open a support ticket here. 

If you are a WC Vendors user please open a support ticket on the Wordpress.org forums.

The information on this forum is outdated and in most instances no longer relevant. Please be sure to check our documentation for the most up to date information.

https://docs.wcvendors.com/

Thank you to all of our customers!

 

Viewing 17 posts - 1 through 17 (of 17 total)
  • Author
    Posts
  • #67928
    Scott Lengacher
    Participant

    I’ve created a custom product taxonomy, and it displays and saves properly in the backend. When I use the WCV helper to add it to product-edit.php, it displays fine, but saves improperly. When I save, the result is that the term’s id is saved as a new term. So, for example, the term male is chosen, the product is saved, and then on refresh the value displayed is 1281, which is the term ID for male.

    			// Puppy Sex Custom Field
    			$puppy_sex_field = (array)get_the_terms( $object_id, 'puppy_sex' );
    			
    			WCVendors_Pro_Form_Helper::select2( apply_filters( 'wcv_custom_product_puppy_sex', array( 
    				'post_id'		=> $object_id, 
    				'id' 			=> 'wcv_custom_product_puppy_sex[]', 
    				'label'   		=> __( 'Puppy Sex (Select one)', 'wcvendors-pro' ), 
    				'placeholder'   	=> __( 'Puppy Sex', 'wcvendors-pro' ), 
    				'wrapper_start' 	=> '',
    				'wrapper_end' 		=> '', 
    				'desc_tip'   		=> 'false', 
    				'taxonomy'		=> 'puppy_sex',
    				'is_taxonomy'	=> true,
    				'taxonomy_args'		=> array( 'hide_empty'=>false ),
    				'value' 		=> $puppy_sex_field,
    				'custom_attributes'	=> array( 'multiple' => 'multiple' )
    				
    				) )
    			);

    Tangential issue: I would prefer to use select instead of select2, but when I do so, it seems impossible to set a default selected value that is equal to whatever is already saved.

    #67974
    Scott Lengacher
    Participant

    Pretty sure I copied the wrong code earlier. This is the code that saves the term ID rather that the term name, thereby creating a new term with a name equal to the other term’s ID (as describer above):

    WCVendors_Pro_Form_Helper::select2( apply_filters( 'wcv_custom_taxonomy_puppy_sex', array( 
    				'post_id'	=> $object_id, 
    				'id' 		=> 'wcv_custom_taxonomy_puppy_sex[]', 
    				'label'   	=> __( 'Puppy Sex', 'wcvendors-pro' ), 
    				'placeholder'   => __( 'Puppy Sex', 'wcvendors-pro' ),
    				'show_option_none'	=> __('Select a sex', 'wcvendors-pro'),
    				'wrapper_start' => '',
    				'wrapper_end' 	=> '', 
    				'desc_tip'   	=> 'false', 
    				'taxonomy'	=> 'puppy_sex',
    				'is_taxonomy'	=> true,
    				'taxonomy_args'	=> array( 'hide_empty'=>false ),
    				'value' 	=> $puppy_sex_field				
    				) )
    			);

    BTW, if I eliminate the taxonomy arguments and instead use an array of options, then it saves properly.

    'options' 	=> array(
    			'male'		=> __( 'Male', 'wcvendors-pro' ),
    			'female' 	=> __( 'Female', 'wcvendors-pro' )
    			),

    However, if I do this, there’s no way to have the currently set value selected by default when editing an existing product. Besides, the addition of another term (in other use cases) would mean needing to manually edit the options array.

    #68031
    Scott Lengacher
    Participant

    It’s worse. I’ve added the following code to a clean copy of product-edit.php:

    WCVendors_Pro_Form_Helper::input( 
    	array( 
    	 	'post_id' 	=> $object_id, 
    	 	'id'	 	=> '_wcv_custom_product_puppy_vaccinated', 
    	 	'label' 	=> __( 'Current Vaccinations', 'wcvendors-pro' ),
    	 	'type' 		=> 'checkbox',
    		'wrapper_start' 	=> '',
    		'wrapper_end' 		=> ''
    	 )
    );

    On page load, it is properly displaying the state of the checkbox as I have set it on the backend (either yes or no). If it starts as unchecked (no), and I check it, then the change is saved properly. However, if it begins in a checked state and I uncheck it, then it doesn’t get saved.

    I have inspected the POST data using Chrome dev tools and can see the _wcv_custom_product_puppy_vaccinated value set to yes when I set it from unchecked to checked. But when I do the opposite, _wcv_custom_product_puppy_vaccinated doesn’t appear in the POST data at all.

    @ben or @digitalchild , any ideas here? This is strange.

    #68042
    Anna
    Member

    @scott,
    Hello Scott,
    Working with Custom Taxonomies in the front end forms in Pro is tricky.
    Perhaps this could be of help to you– Using the following format I was able to add “product condition” in a drop-down on the product add/edit form.

    The first part of the code should be placed within one of the DIV on the product-edit.php template, as instructed.
    ( Just in case you’ve not modified templates.. though I am guess you have! : https://www.wcvendors.com/kb/changing-vendor-templates/ )

    The second part of the code will go within your theme/child theme functions.php.

    https://gist.github.com/fervous/048b04a4a73cde43fd77b34405917f54

    You may be able to use this and modify it to suit your needs.. let me know.
    I am not 100% certain why the other method you have used is not properly saving.

    #68079
    Scott Lengacher
    Participant

    Anna, I’ve seen that code before, and it does work. However, the main difference between the code you shared and my scenario is that I’m dealing with a taxonomy. And if I write my code with an options array, as yours has, then it saves properly, but the correct value isn’t shown after save. In other words, the product edit page always shows the first item from the options array, rather than showing what’s in the db.

    I might be willing to abandon using a taxonomy for this, but that would still leave the big problem of being unable to save checkboxes. We can make that the priority issue.

    #68083
    Scott Lengacher
    Participant

    @digitalchild

    Concerning taxonomies, here’s what I think is going wrong:

    The form helper generates an option with a value set to the key (ID) for the particular term:

    		foreach ( $field['options'] as $key => $value ) {
    			echo '<option value="' . esc_attr( $key ) . '" ' . selected( esc_attr( $field['value'] ), esc_attr( $key ), false ) . '>' . esc_html( $value ) . '</option>';
    		}

    That looks like this, in my case:

    <select id=... ><option value>Select a sex</option>
    <option value="1301" >1280</option><option value="1300" >1281</option>
    <option value="1281" >Female</option><option value="1280" >Male</option></select>

    Naturally, the value is what gets sent with POST. Then, when saving the POST data, WCV saves that value (which is the ID, not the term name), like this:

    $wcv_custom_tax = array_intersect_key( $_POST, array_flip( preg_grep('/^wcv_custom_taxonomy_/', array_keys( $_POST ) ) ) );
    	if ( !empty( $wcv_custom_tax ) ) { 
    
    		foreach ( $wcv_custom_tax as $taxonomy => $data) {
    					
    			$taxonomy = str_replace( 'wcv_custom_taxonomy_', '', $taxonomy ); 
    			$tax_data = array_map( 'intval', $data ); 
    			$tax_data = array_unique( $data ); 
    
    			wp_set_post_terms( $post_id, $tax_data, $taxonomy ); 
    		}
    	}

    So, the ID gets saved as a term, causing the problem. So, I think this is a bug. ( @fervous, can you bring this to Ben and Jamie’s attention? Thank you.) I see two ways of fixing it: either the form helper sets the option value to the term name, or the product controller handles the save differently. The first seems easier, and…

    Due to the way the form helper handles taxonomies and generating the options, selected='selected' never gets set.

    #68094
    Scott Lengacher
    Participant

    @digitalchild & @ben

    In order to get this working, I had to do two things. First, in my frontend template, I needed to set a value, but I had to do it in an unexpected way. Including this in the documentation/knowledgebase would be a good idea).

    	$puppy_sex_field_terms = get_the_terms( $object_id, 'puppy_sex' );
    	$puppy_sex_field = $puppy_sex_field_terms[0]->name;
    		WCVendors_Pro_Form_Helper::select( array( 
    			'post_id'	=> $object_id, 
    			'id' 		=> 'wcv_custom_taxonomy_puppy_sex[]', 
    			'label'   	=> __( 'Puppy Sex', 'wcvendors-pro' ), 
    			'placeholder'   => __( 'Puppy Sex', 'wcvendors-pro' ),
    			'show_option_none'	=> __('Select a sex', 'wcvendors-pro'),
    			'wrapper_start' => '',
    			'wrapper_end' 	=> '', 
    			'desc_tip'   	=> 'false', 
    			'taxonomy'	=> 'puppy_sex',
    			'taxonomy_field'	=> 'puppy_sex',
    			'taxonomy_args'	=> array(	'hide_empty'	=>false,
    							'hierarchical'	=> true ),
    			'value' 	=> $puppy_sex_field
    			)
    		);

    I had to retrieve the terms, which are returned in an array of objects, and cannot be passed thru the helper. Since this allows for only a single term, I took the array of objects and extracted the single term name, and then I set it as the 'value' for the helper array.

    That wasn’t enough though, because as I noted earlier, the html options output include the term ID for the value attribute rather than the term name. This causes two problems: the form saves the term ID as a new term unto itself, and the method WCV uses to determine which option should have the selected attribute fails to identify any option.

    Now, with the value for the helper array properly set, I had to make one change to line 227 in class-wcvendors-pro-form-helper.php. (I wouldn’t touch these files normally, except, as noted, I think this is a bug.)

    From:

    		$options[ $term->term_id ] = $term->name; 
    

    To:

    		$options[ $term->name ] = $term->name; 
    

    And that solved it. The proper option has the selected attribute, and the form saves correctly, since it’s now passing the term name rather than its ID in POST.

    Whether or not this was the proper or best way to fix the problem, I don’t know. I’ll leave that judgement to you.

    #68127
    Scott Lengacher
    Participant

    And I’m 99% sure that this is what’s going wrong with checkboxes, but I’d still appreciate some help…

    It is normal behavior for empty checkboxes to not be included in POST. So there are two common ways to handle that. Either create an accompanying hidden field with the same name that will POST and be used if the checkbox is empty, or overriden if the checkbox is checked. Otherwise, the server can expect certain fields, and interprets the absence of a POST value as the unchecked state and handles it accordingly. Best I can tell, that is how the Virtual and Downloadable checkboxes are handled.

    #68154
    Jamie
    Keymaster

    Hi @scott,

    Looking into this. Will report back. Your definition of the form is different to my examples. Will create a test install and see if I can replicate your issues.

    cheers,

    Jamie.

    #68181
    Arjan Ros
    Participant

    Scott said

    I’ve created a custom product taxonomy, and it displays and saves properly in the backend. When I use the WCV helper to add it to product-edit.php, it displays fine, but saves improperly. When I save, the result is that the term’s id is saved as a new term. So, for example, the term male is chosen, the product is saved, and then on refresh the value displayed is 1281, which is the term ID for male.

    Exactly the same issue here, and I will follow this thread.

    #68191
    Jamie
    Keymaster

    Hello,

    Can you provide a gist of your taxonomy definitions for me please?

    thanks,

    Jamie.

    #68212
    Scott Lengacher
    Participant
    #68214
    Scott Lengacher
    Participant

    Continuing what I said earlier about the server expecting certain fields in POST, and that being the way checkboxes are turned off when they’re absent from the POST data…

    This is how it’s handled by WCV for Virtual and Downloadable checkboxes:

    	$is_downloadable = isset( $_POST[ '_downloadable' ] ) ? 'yes' : 'no';
    	$is_virtual      = isset( $_POST[ '_virtual' ] ) ? 'yes' : 'no';

    So, I have temporarily resolved my issue with checkboxes by doing the following: I already had the checkboxes in the backend product edit form by using woocommerce functions like this:

    woocommerce_wp_checkbox( array(
    		'id' 		=> '_wcv_custom_product_puppy_vaccinated',
    		'label' 	=> __( 'Current Vaccinations', 'woocommerce' ),
    		'desc_tip' 	=> true,
    		'description'	=> __( 'Check the box if the dog is up-to-date on vaccinations.', 'woocommerce' ),
    	) );

    And saving those was handled with:

    function save_puppy_info_option_fields( $post_id ) {
    	$puppy_vaccinated = isset( $_POST['_wcv_custom_product_puppy_vaccinated'] ) ? 'yes' : 'no';
    	update_post_meta( $post_id, '_wcv_custom_product_puppy_vaccinated', $puppy_vaccinated );
    …
    }
    add_action( 'woocommerce_process_product_meta_simple', 'save_puppy_info_option_fields'  );
    add_action( 'woocommerce_process_product_meta_variable', 'save_puppy_info_option_fields'  );

    So, all I had to do was add the following action to go along with those last two:
    add_action( 'wcv_save_product', 'save_puppy_info_option_fields', 10, 1 );

    Now the frontend checkboxes save too. This, of course, doesn’t change the fact that the WCV form helper is only doing half the work. But I think it’s pretty clear what would need to happen with an upgraded form helper — it would need to look for checkbox type fields being generated and then “anticipate” those fields to be in POST, and set them to no if they aren’t sent in POST. Probably not the easiest task; I can’t quickly think of a method to accomplish that.

    #68311
    Jamie
    Keymaster

    Hello,

    I’ve fixed the custom taxonomy saving issue in pro and the update will be available in 1.4.4. With the following definition you can add and save the custom taxonomy with no modifications necessary. If you need to select more than one option then add the multiple = multiple custom attribute and you’re good to go.

    https://gist.github.com/digitalchild/67b9094442ac05fb04679982492e1b1e

    Regarding checkboxes this is a limitation of php in that you need to know what ALL your fields are after post to be able to verify them. Currently your hook to save the checkbox separately is the correct way to do this. The only way I can see the solution for knowing fields is to create a registration system that the controller then references to grab fields and save them. I’ll put that into the what ifs bucket for now.

    On a side note, why is puppy sex a taxonomy? There are only 2 options. Unless this shop is selling creations from the Island of Dr Moreau ?

    cheers,

    Jamie.

    #68400
    Scott Lengacher
    Participant

    Thanks, Jamie.

    Would it be possible to add a filter to the next release that will allow me to modify the settings for a custom type box that I have added?

    Long version: I added a custom type box _puppy_type. I want it checked by default on the frontend, but I want it unchecked by default in the backend. You have a filter product_type_options, but it only applies to the _virtual and _downloadable checkboxes. It would be nice to have a filter that applied to all or just to the custom ones. Thanks.

    #68476
    Arjan Ros
    Participant

    Hello,

    I’ve fixed the custom taxonomy saving issue in pro and the update will be available in 1.4.4.

    Thanks Jamie.

    When will 1.4.4. be released?

    #68516
    Anna
    Member

    @arjanhague
    Soon!
    We are testing it now.

Viewing 17 posts - 1 through 17 (of 17 total)
  • The forum ‘WC Vendors Pro Support’ is closed to new topics and replies.