Add Standard Page Attributes Metabox for Page Parent

I have a custom post type ‘product’ supplied to me by a WordPress eCommerce plugin that does not offer the option to change the Page Parent in the Page Attributes Metabox. I’d like to remedy that.

I found this post on WordPress StackExchange, but it deals specifically with the Page Template element of the Page Attributes Metabox. Can anyone extrapolate on the very good answer provided in this other WSE question to suit my purposes? It can even include all the Page Attributes Metabox options. It doesn’t have to be stripped down to Page Parent. But Page Parent is the one I need.

Read More

Edit #2:
Here is what I have so far. The metabox shows up with the appropriate drop down, but I can’t save the parent_id. It seems like the admin/post.php page isn’t catching the $_POST[‘parent_id’] variable. Is there some feature of WordPress that doesn’t allow non-hierarchical custom post types to have parent ids? Or should I be looking somewhere in the Woocommerce code?

    function product_attributes_meta_box($post) {
        $dropdown_args = array(
            'post_type'        => 'page',
            'exclude_tree'     => $post->ID,
            'selected'         => $post->post_parent,
            'name'             => 'parent_id',
            'show_option_none' => __('(no parent)'),
            'sort_column'      => 'menu_order, post_title',
            'echo'             => 0,
            'child_of'         => 282, // Sales Page
        );

        $dropdown_args = apply_filters( 'page_attributes_dropdown_pages_args', $dropdown_args, $post );
        $pages = wp_dropdown_pages( $dropdown_args );
        if ( ! empty($pages) ) {
?>
<p><strong><?php _e('Parent') ?></strong></p>
<label class="screen-reader-text" for="parent_id"><?php _e('Parent') ?></label>
<?php echo $pages; ?>
<?php
        } // end empty pages check
    }
    add_action('add_meta_boxes','add_post_template_metabox');
    function add_post_template_metabox() {
        add_meta_box('postparentdiv', __('Page Parent'), 'product_attributes_meta_box', 'product', 'side', 'core');
    }
    add_action('save_post','save_post_parent',10,2);
    function save_post_parent($post_id,$post) {
      if ($post->post_type=='product' && !empty($_POST['parent_id'])
      ) {
        update_post_meta($post->ID,'_parent_id',$_POST['parent_id']);
      }
    }

Edit #3:
I changed the custom post type ‘product’ to hierarchical => true but the post.php page is still not catching the $_POST[‘parent_id’] variable. I also tried commenting out remove_meta_box( 'pageparentdiv', 'product', 'side' ); in the woocommerce.php file and removing ALL of my custom code above, but the Parent Page is still not being saved.

Related posts

Leave a Reply

1 comment

  1. Although not listed in the following resources, seems that parent_id is a reserved name in $_POST and $_REQUEST:

    This code works in a Woocommerce product page to show a dropdown of regular pages. Also, in your code, you were missing the get_post_meta to fill the selected argument value.

    add_action( 'add_meta_boxes','add_metabox_wpse_83542' );
    add_action( 'save_post', 'save_post_wpse_83542', 10, 2 );
    
    function add_metabox_wpse_83542() 
    {
        add_meta_box(
            'postparentdiv', 
            __('Page Parent'), 
            'meta_box_content_wpse_83542', 
            'product', 
            'side', 
            'core'
        );
    }
    
    function meta_box_content_wpse_83542( $post ) 
    {
        $meta = get_post_meta( $post->ID, '_parent_id', true );
        $selected = ( isset( $meta ) ) ? $meta : '';
        $dropdown_args = array(
            'post_type'        => 'page',
            'exclude_tree'     => $post->ID,
            'selected'         => $selected,
            'name'             => '_parent_id',
            'show_option_none' => __( '(no parent)' ),
            'sort_column'      => 'menu_order, post_title',
            'echo'             => 0,
            'child_of'         => 97, // Sales Page
        );
    
        $dropdown_args = apply_filters( 'page_attributes_dropdown_pages_args', $dropdown_args, $post );
        $pages = wp_dropdown_pages( $dropdown_args );
    
        if ( ! empty($pages) ) 
        {
            wp_nonce_field( plugin_basename( __FILE__ ), 'noncename_wpse_83542' );          
            ?>
            <p><strong><?php _e('Parent') ?></strong></p>
            <label class="screen-reader-text" for="parent_id"><?php _e('Parent') ?></label>
            <?php 
            echo $pages; 
        } // end empty pages check
    }    
    
    function save_post_wpse_83542( $post_id, $post ) 
    {
        // Block on Autosave
        if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )  
            return;
    
        // Block Revisions
        if ( 'revision' == $post->post_type )
            return;
    
        // Nonce verify
        if ( !wp_verify_nonce( $_POST['noncename_wpse_83542'], plugin_basename( __FILE__ ) ) )
            return;
    
        if ( $post->post_type == 'product' && !empty( $_POST['_parent_id'] ) ) 
        {
            update_post_meta( $post->ID, '_parent_id', $_POST['_parent_id'] );
        }
    }