• Resolved jeremycaris

    (@jeremycaris)


    I’m following this example: https://github.com/CMB2/CMB2-Snippet-Library/blob/master/front-end/cmb2-front-end-submit.php

    $cmb = cmb2_get_metabox( 'sofw_vendors_options_page', 'fake-oject-id' );
    
    $sanitized_values = $cmb->get_sanitized_values( $_POST );
    
    // result is this array
    $sanitized_values = Array
    (
        [business_name] => Test Business
        [point_of_contact] => John Doe
        [point_of_contact_position] => Owner
        [email] => [email protected]
        [website] => https://testbusiness.com
        [category] => Web Services
        [video] => https://youtu.be/7AoJwMImQZE
        [about_us] => About us.
        [services] => Services.
        [incentive] => Give us a call!
    )
    
    // Set our post data arguments
    $post_data = array();
    $post_data['post_title'] = $sanitized_values['business_name'];
    $post_data['post_content'] = '';
    $post_data['post_status'] = 'publish';
    $post_data['post_type'] = 'vendor';
    $user_id = get_current_user_id();
    $post_data['post_author'] = $user_id ? $user_id : 1;
    
    // This successfully creates new vendor cpt and new_submission_id = post_ID
    $new_submission_id = wp_insert_post( $post_data, true );
    
    // But save_fields isn't working here. No post meta saved...
    $cmb->save_fields( $new_submission_id, 'vendor', $sanitized_values );
    

    What am I missing, or is this a bug?

Viewing 15 replies - 1 through 15 (of 22 total)
  • Thread Starter jeremycaris

    (@jeremycaris)

    Here’s the entire class just in case it helps:

    if ( !class_exists('SOFW_Vendors_Options_Page') ) {
    
        class SOFW_Vendors_Options_Page {
            
            function __construct() {
                add_action( 'cmb2_admin_init', array($this, 'sofw_vendors_options_page_setup') );
                add_action( 'cmb2_after_init', array($this, 'sofw_vendors_save_override' ) );
            }
    
            /**
             * Hook in and register a metabox to handle a theme options page and adds a menu item.
             */
            public function sofw_vendors_options_page_setup() {
    
                /**
                 * Registers main options page menu item and form.
                 */
                $main_options = new_cmb2_box( array(
                    'id'           => 'sofw_vendors_options_page',
                    'title'        => esc_html__( 'Create New Vendor', 'sofw-vendors' ),
                    'desc'       => esc_html__( 'Creates a New Vendor, generates a new Gravity Form, and assigns it to the Vendor.', 'sofw-vendors' ),
                    'object_types' => array( 'options-page' ),
    
                    /*
                     * The following parameters are specific to the options-page box
                     * Several of these parameters are passed along to add_menu_page()/add_submenu_page().
                     */
    
                    'option_key'      => 'sofw_vendors_options', // The option key and admin menu page slug.
                    'icon_url'        => 'dashicons-groups', // Menu icon. Only applicable if 'parent_slug' is left empty.
                    // 'menu_title'      => esc_html__( 'Options', 'cmb2' ), // Falls back to 'title' (above).
                    // 'parent_slug'     => 'themes.php', // Make options page a submenu item of the themes menu.
                    // 'capability'      => 'manage_options', // Cap required to view options-page.
                    'position'        => 91, // Menu position. Only applicable if 'parent_slug' is left empty.
                    // 'admin_menu_hook' => 'network_admin_menu', // 'network_admin_menu' to add network-level options page.
                    // 'display_cb'      => false, // Override the options-page form output (CMB2_Hookup::options_page_output()).
                    'save_button'     => esc_html__( 'Add Vendor', 'sofw-vendors' ), // The text for the options-page save button. Defaults to 'Save'.
                    // 'disable_settings_errors' => true, // On settings pages (not options-general.php sub-pages), allows disabling.
                    // 'message_cb'      => 'yourprefix_options_page_message_callback',
                ) );
    
                /**
                 * Options fields ids only need
                 * to be unique within this box.
                 * Prefix is not needed.
                 */
                $main_options->add_field( array(
                    'name'       => esc_html__( 'Business Name*', 'sofw-vendors' ),
                    'id'         => 'business_name',
                    'type'       => 'text',
                    'attributes' => array(
                        'data-validation' => 'required',
                    ),
                ) );
                
                $main_options->add_field( array(
                    'name'       => esc_html__( 'Point of Contact*', 'sofw-vendors' ),
                    'id'         => 'point_of_contact',
                    'type'       => 'text',
                    'attributes' => array(
                        'data-validation' => 'required',
                    ),
                ) );
                
                $main_options->add_field( array(
                    'name'       => esc_html__( 'Point of Contact\'s Position*', 'sofw-vendors' ),
                    'id'         => 'point_of_contact_position',
                    'type'       => 'text',
                    'attributes' => array(
                        'data-validation' => 'required',
                    ),
                ) );
    
                $main_options->add_field( array(
                    'name' => esc_html__( 'Email Address*', 'sofw-vendors' ),
                    'id'   => 'email',
                    'type' => 'text_email',
                    'attributes' => array(
                        'data-validation' => 'required',
                    ),
                ) );
    
                $main_options->add_field( array(
                    'name' => esc_html__( 'Website', 'sofw-vendors' ),
                    'id'   => 'website',
                    'type' => 'text_url',
                ) );
    
                $main_options->add_field( array(
                    'name'             => esc_html__( 'Category*', 'sofw-vendors' ),
                    'id'               => 'category',
                    'type'             => 'select',
                    'show_option_none' => true,
                    'options'          => array(
                        'Appraiser' => esc_html__( 'Appraiser', 'sofw-vendors' ),
                        'Cleaning Service' => esc_html__( 'Cleaning Services', 'sofw-vendors' ),
                        'Flooring' => esc_html__( 'Flooring', 'sofw-vendors' ),
                        'Handyman' => esc_html__( 'Handyman', 'sofw-vendors' ),
                        'Heating / Cooling Companies' => esc_html__( 'Heating / Cooling Companies', 'sofw-vendors' ),
                        'Home Interior Designers & Stagers' => esc_html__( 'Home Interior Designers & Stagers', 'sofw-vendors' ),
                        'Home Inspectors' => esc_html__( 'Home Inspectors', 'sofw-vendors' ),
                        'Home Remodel Companies' => esc_html__( 'Home Remodel Companies', 'sofw-vendors' ),
                        'Insurance' => esc_html__( 'Insurance', 'sofw-vendors' ),
                        'Landscaping Services' => esc_html__( 'Landscaping Services', 'sofw-vendors' ),
                        'Lawyers / Attorneys'   => esc_html__( 'Lawyers / Attorneys', 'sofw-vendors' ),
                        'Lenders'   => esc_html__( 'Lenders', 'sofw-vendors' ),
                        'Movers'   => esc_html__( 'Movers', 'sofw-vendors' ),
                        'Paint Companies'   => esc_html__( 'Paint Companies', 'sofw-vendors' ),
                        'Pest Control / Termites'   => esc_html__( 'Pest Control / Termites', 'sofw-vendors' ),
                        'Pool Services'   => esc_html__( 'Pool Services', 'sofw-vendors' ),
                        'Plumber Services'   => esc_html__( 'Plumber Services', 'sofw-vendors' ),
                        'Roofing'   => esc_html__( 'Roofing', 'sofw-vendors' ),
                        'Septic Pumping'   => esc_html__( 'Septic Pumping', 'sofw-vendors' ),
                        'Title Company'   => esc_html__( 'Title Company', 'sofw-vendors' ),
                        'Lenders'   => esc_html__( 'Lenders', 'sofw-vendors' ),
                        'Water Filtration'   => esc_html__( 'Water Filtration', 'sofw-vendors' ),
                        'Web Services'     => esc_html__( 'Web Services', 'sofw-vendors' ),
                        'Window’s & Glass'     => esc_html__( 'Window’s & Glass', 'sofw-vendors' ),
                    ),
                    'attributes' => array(
                        'data-validation' => 'required',
                    ),
                ) );
    
                $main_options->add_field( array(
                    'name'         => esc_html__( 'Photo or Logo', 'sofw-vendors' ),
                    'id'           => 'photo_or_logo',
                    'type'         => 'file_list',
                    'preview_size' => 'medium',
                    'query_args' => array(
                        'type' => array(
                            'image/jpeg', // Make library only display these.
                            'image/jpg',
                            'image/png',
                            ),
                    ),
                ) );
                
                $main_options->add_field( array(
                    'name' => esc_html__( 'Video', 'sofw-vendors' ),
                    'desc' => esc_html__( 'Enter a youtube or vimeo URL. URL\'s for videos from the following services will also work: Amazon Kindle instant previews, Animoto, DailyMotion, Flickr, TED, TikTok, VideoPress, and WordPress.tv.', 'sofw-vendors' ),
                    'id'   => 'video',
                    'type' => 'oembed',
                ) );
    
                $main_options->add_field( array(
                    'name'    => esc_html__( 'About Us*', 'sofw-vendors' ),
                    'id'      => 'about_us',
                    'type'    => 'wysiwyg',
                    'options' => array(
                        'textarea_rows' => 5,
                    ),
                    'attributes' => array(
                        'data-validation' => 'required',
                    ),
                ) );
    
                $main_options->add_field( array(
                    'name'    => esc_html__( 'Services', 'sofw-vendors' ),
                    'id'      => 'services',
                    'type'    => 'wysiwyg',
                    'options' => array(
                        'textarea_rows' => 5,
                    ),
                ) );
                
                $main_options->add_field( array(
                    'name'       => esc_html__( 'Incentive / Form Title (Call to Action)*', 'sofw-vendors' ),
                    'id'         => 'incentive',
                    'type'       => 'text',
                    'attributes' => array(
                        'data-validation' => 'required',
                    ),
                ) );
                
    
                /**
                 * Registers secondary options page, and set main item as parent.
                 */
                $secondary_options = new_cmb2_box( array(
                    'id'           => 'sofw_vendors_secondary_options_page',
                    'title'        => esc_html__( 'Settings', 'cmb2' ),
                    'object_types' => array( 'options-page' ),
                    'option_key'   => 'sofw_vendors_secondary_options',
                    'parent_slug'  => 'sofw_vendors_options',
                ) );
                
                $secondary_options->add_field( array(
                    'name'       => esc_html__( 'Available Vendor Categories*', 'sofw-vendors' ),
                    'id'         => 'avaible_vendor_categories',
                    'type'       => 'text',
                    'repeatable' => true,
                    'attributes' => array(
                        'data-validation' => 'required',
                    ),
                ) );
                
    
            }
    
            
            public function sofw_vendors_save_override() {
                $cmb = cmb2_get_metabox( 'sofw_vendors_options_page', 'fake-oject-id' );
                
                // Check security nonce
                if ( ! isset( $_POST[ $cmb->nonce() ] ) || ! wp_verify_nonce( $_POST[ $cmb->nonce() ], $cmb->nonce() ) ) {
                    return $cmb->prop( 'submission_error', new WP_Error( 'security_fail', __( 'Security check failed.' ) ) );
                }
    
                // Check title submitted
                if ( empty( $_POST['business_name'] ) ) {
                    return $cmb->prop( 'submission_error', new WP_Error( 'post_data_missing', __( 'New post requires a Business Name.' ) ) );
                }
                
                // Fetch sanitized values
                $sanitized_values = $cmb->get_sanitized_values( $_POST );
                
                // Set our post data arguments
                $post_data = array();
                $post_data['post_title'] = $sanitized_values['business_name'];
                $post_data['post_content'] = '';
                $post_data['post_status'] = 'publish';
                $post_data['post_type'] = 'vendor';
                $user_id = get_current_user_id();
                $post_data['post_author'] = $user_id ? $user_id : 11;
                
                // Create the new post
                $new_submission_id = wp_insert_post( $post_data, true );
                
                // If we hit a snag, update the user
                if ( is_wp_error( $new_submission_id ) ) {
                    return $cmb->prop( 'submission_error', $new_submission_id );
                }
                
                $cmb->save_fields( $new_submission_id, 'vendor', $sanitized_values );
     
                /*
                 * Redirect back to the form page with a query variable with the new post ID.
                 * This will help double-submissions with browser refreshes
                 */
                $redirect = add_query_arg( array(
                    'page' => 'sofw_vendors_options',
                    'post_submitted' => $new_submission_id,
                    ), 
                    $_SERVER["HTTP_REFERER"],
                );
                wp_redirect( $redirect );
                
                exit;
            }
            
        }
    }
    • This reply was modified 3 years, 10 months ago by jeremycaris.
    Plugin Contributor Michael Beckwith

    (@tw2113)

    The BenchPresser

    I would need to potentially step through it with something like XDEBUG to really see the process, but I guess my main question is you’re trying to save fields in an options page, after processing as a new post in a ‘vendor’ post type?

    Thread Starter jeremycaris

    (@jeremycaris)

    Actually, I’m trying to create a new post (custom post type “vendor”, which is working) and then save the submitted form fields as custom post meta for the post that was created.

    Thread Starter jeremycaris

    (@jeremycaris)

    I can just use the standard update_post_meta function, but I’m trying to learn CMB2.

    Plugin Contributor Michael Beckwith

    (@tw2113)

    The BenchPresser

    Then I’m perhaps a bit confused why you’re going through an options page for this, when you could just set the object_types parameters for the new_cmb2_box calls to be ‘vendor’ and render these metaboxes in the standard post editor. Just click “add new vendor” etc, fill it in like a standard post, and then fill in the fields from your configuration. It’d save all automatically for you to post meta.

    That said though, I may be missing context for why you went this route, and willing to hear the thought process.

    Thread Starter jeremycaris

    (@jeremycaris)

    I need to follow up with several other custom functions. For instance, on post creation, I’m creating a new Gravity Form with the submitted email as the notification recipient, and assigning that gform id to the vendor post, so the custom page template pulls it automatically. I’m successfully doing all of this with Advanced Custom Fields, but I was trying to move toward not being dependent on ACF so that I could roll it all up into one plugin. If I just create a new vendor post type without having the custom meta defined, I don’t have all the data I need to create the form.

    Plugin Contributor Michael Beckwith

    (@tw2113)

    The BenchPresser

    I’m curious how far you could get with the hook inside this function from includes/CMB2.php

    /**
     * Fires the "cmb2_{$object_type}_process_fields_{$cmb_id}" action hook.
     *
     * @since 2.2.2
     *
     * @return CMB2
     */
    public function pre_process() {
    	$object_type = $this->object_type();
    
    	/**
    	 * Fires before fields have been processed/saved.
    	 *
    	 * The dynamic portion of the hook name, $object_type, refers to the
    	 * metabox/form's object type
    	 *    Usually <code>post</code> (this applies to all post-types).
    	 *    Could also be <code>comment</code>, <code>user</code> or <code>options-page</code>.
    	 *
    	 * The dynamic portion of the hook name, $this->cmb_id, is the meta_box id.
    	 *
    	 * @param array $cmb       This CMB2 object
    	 * @param int   $object_id The ID of the current object
    	 */
    	do_action( "cmb2_{$object_type}_process_fields_{$this->cmb_id}", $this, $this->object_id() );
    
    	return $this;
    }
    

    It’s called in this function from the same file, so you can see how it iterates over all the fields to save as post meta.

    public function process_fields() {
    
    	$this->pre_process();
    
    	// Remove the show_on properties so saving works.
    	$this->prop( 'show_on', array() );
    
    	// save field ids of those that are updated.
    	$this->updated = array();
    
    	foreach ( $this->prop( 'fields' ) as $field_args ) {
    		$this->process_field( $field_args );
    	}
    
    	return $this;
    }
    

    You could grab the email field out of this, and use it with your creation of the gravity form and set things up from there. Then save that new gforms ID and whatnot to the same post’s post meta using the passed in object ID.

    If I’m reading things right, the hook to use in add_action would be:

    cmb2_vendor_process_fields_sofw_vendors_options_page'
    

    so

    
    function my_custom_code( $cmb2_obj, $cmb2_obj_id ) {
    	// Create your gform in here, save to post meta with $cmb2_obj_id
    }
    add_action( 'cmb2_vendor_process_fields_sofw_vendors_options_page', 'my_custom_code', 10, 2 );
    

    Worth a shot.

    Thread Starter jeremycaris

    (@jeremycaris)

    Thank you! I’m going to play around with this later today. I appreciate your time and help!

    Plugin Contributor Michael Beckwith

    (@tw2113)

    The BenchPresser

    Welcome.

    Thread Starter jeremycaris

    (@jeremycaris)

    This hook worked:

    add_action( 'cmb2_options-page_process_fields_sofw_vendors_options_page', 'my_custom_code', 10, 2 );
    

    Which allowed me to access the email field like this:

    $email = $cmb->data_to_save[email];

    From there, I can do everything I need to do. Thank again!

    Thread Starter jeremycaris

    (@jeremycaris)

    Actually, I have one more question… So that worked for my option page, now I’m wondering if I can accomplish this just by publishing a new custom Vendor post type with the fields filled out using the same hook, but it’s not passing any data. Here’s my meta box:

    $sofw_vendor_post_box = new_cmb2_box( array(
        'id'            => 'sofw_vendor_metabox',
        'title'         => __( 'Create New Vendor', 'sofw-vendors' ),
        'object_types'  => array( 'vendor', ), // Post type
        'context'       => 'normal',
        'priority'      => 'high',
        'show_names'    => true, // Show field names on the left
    ) );

    And here’s the hook I’m using:

    add_action( 'cmb2_vendor_process_fields_sofw_vendor_metabox', 'my_custom_code', 10, 2 );
    
    function my_custom_code( $cmb2_obj, $cmb2_obj_id ) {
        $log_time = date('Y-m-d h:i:sa');
        $log_filename = get_stylesheet_directory()."/log";
        if (!file_exists($log_filename)) 
        {
            // create directory/folder uploads.
            mkdir($log_filename, 0777, true);
        }
        $log_file_data = $log_filename.'/log_debug' . '.log';
        file_put_contents($log_file_data, date('d-M-Y G:i:s') . "\n\n" . print_r($cmb2_obj, true) . "\n\n", FILE_APPEND);
    }

    I’m just logging the $cmb2_obj. This works with the code I last posted for the options page, but I don’t get anything at all when I publish or update a new vendor post with the metabox fields filled out.

    Any thoughts?

    Thread Starter jeremycaris

    (@jeremycaris)

    In fact, I just revised to make sure the hook is firing off:

    add_action( 'cmb2_vendor_process_fields_sofw_vendor_metabox', 'my_custom_code', 10, 2 );
    function my_custom_code( $cmb2_obj, $cmb2_obj_id ) {
        // here I updated my funtion to log 'test' to the file (instead of $cmb2_obj), and nothing is logged... which tells my the hook is never triggered.
    }

    What am I missing?

    Plugin Contributor Michael Beckwith

    (@tw2113)

    The BenchPresser

    Hmm, not quite sure as the hook looks like it was properly constructed at the moment.

    “cmb2_{$object_type}_process_fields_{$this->cmb_id}”

    What file are you adding these hooks/callbacks into ?

    Thread Starter jeremycaris

    (@jeremycaris)

    I’m adding it in functions.php just to test. So I’ve been playing around. This works when I publish or update the post:

    add_action( 'cmb2_override_meta_save', 'my_custom_code', 10, 4 );
    function my_custom_code( $null,  $a,  $this_args,  $instance ) {
        my_log( $instance );
    }

    But this doesn’t fire off:

    add_action( 'cmb2_vendor_process_fields_sofw_vendor_metabox', 'my_custom_code', 10, 2 );
    function my_custom_code( $cmb2_obj, $cmb2_obj_id ) {
        my_log( $cmb2_obj );
    }

    And this doesn’t fire either:

    add_action( 'cmb2_save_vendor_fields_sofw_vendor_metabox', 'my_custom_code', 10, 3 );
    function my_custom_code( $object_id,  $this_updated,  $instance ) {
        my_log( $instance );
    }

    My object type is definitely ‘vendor’ and my metabox id is definitely ‘sofw_vendor_metabox’. I’m stumped.

    Plugin Contributor Michael Beckwith

    (@tw2113)

    The BenchPresser

    I’d have to tinker and test things out myself to see what may be going on. Won’t be able to do that till a bit later right now.

Viewing 15 replies - 1 through 15 (of 22 total)
  • The topic ‘save_fields isn’t working’ is closed to new replies.