Blog

  • Migrating a GravityView Without Losing Fields

    Exporting a GravityView and importing it into a different site is easy, and there are official instructions right here.

    This process works very smoothly when the Gravity Forms and GravityViews on both sites are identical. That’s usually not the world I live in, however. I’m a back-end developer in sites that sometimes have multiple teams working on them. I am usually only responsible for some of the Gravity Forms in the site, and that means the IDs of the forms I import into the site aren’t predictable.

    Migrating a GravityView from one site to another is easy as long as the ID of the Gravity Form on which the GravityView is built does not change. If the ID of the underlying form changes, the view loses all the fields on the multi, single, and edit lists. This is frustrating because GravityViews take quite a while to configure, and those field lists are the bulk of the work.

    Let’s Run Some Database Queries

    If you have the ability to run MySQL queries against the database of your WordPress installation, you can run a couple queries after importing a GravityView to update the view with the ID of the Gravity Form on the new site.

    Query #1

    UPDATE wp_postmeta SET meta_value = 1 WHERE meta_value = 42 AND '_gravityview_form_id' = meta_key;

    You need to change the numbers 1 and 42, which are the new Gravity Form ID and the old Gravity Form ID, respectively. The IDs of your Gravity Forms are listed when you click Forms in the dashboard. Also, take care to make sure your table prefix is the default wp_ like this example, or change wp_postmeta to match.

    Query #2

    UPDATE wp_postmeta SET meta_value = REPLACE( meta_value, 's:7:"form_id";s:2:"42";', 's:7:"form_id";s:1:"1";' ) WHERE '_gravityview_directory_fields' = meta_key;

    Look for our form IDs "42" and "1" again. If your form IDs aren’t two and one digits like this example, you’ll also have to change the s:2: and s:1: that precede the values to match. These are pieces of a serialized PHP array, where s means string and the :2 means that the string "42" has a length of two characters. (Likewise for s:7 identifying "form_id" as a string with a length of seven characters.)

  • Sometimes, an array is passed to the get_callback provided to register_rest_field() instead of an object

    When using register_rest_field() to add fields to terms in the WordPress REST API, the $object sent to your get_callback function will be an array instead of an object like the documentation describes.

    An object will still be passed, sometimes, too. Here is an example of how I work around this problem:

    
    	function add_api_term_fields() {
    
    		//location-phone-hours
    		register_rest_field( 'location', 'location-phone-hours', array(
    			'get_callback'    => array( $this, 'get_term_meta_via_rest' ),
    			'update_callback' => array( $this, 'set_term_meta_via_rest' ),
    			'schema'          => array(
    				'description' => __( 'An array of phone numbers and hours of operation for this location.', 'inventory-portal' ),
    				'type'        => 'string',
    				'context'     => array( 'view', 'edit' ),
    			),
    		) );
    	}
    
    	static function get_term_meta_via_rest( $term, $attr, $request, $object_type ) {
    		$term_id = 0;
    
    		if(  is_array( $term ) ) {
    			$term_id = $term['id']
    		} else {
    			$term_id = $term->term_id;
    		}
    
    		return maybe_serialize( get_term_meta( $term_id, $attr, true ) );
    	}
    

    Why is this happening? See the definition of prepare_item_for_response() method on line 683 of wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php. The call to add_additional_fields_to_object() on line 725 is the method that passes an array to your get_callback.

    Perhaps this is an acceptable design. I believe the only reference to the data type of $object in the documentation is this comment. It certainly feels like a bug.