public function print_form()
 {
     if (!empty($this->form)) {
         foreach ($this->form as $f) {
             switch ($f['item_type']) {
                 case 'metabox':
                     echo x_add_metadata_group($f['name'], $f['post_type'], $f['fields']);
                     break;
                 case 'field':
                     echo x_add_metadata_field($f['name'], $f['post_type'], $f['fields']);
                     break;
                 case 'multifield':
                     echo x_add_metadata_multifield($f['name'], $f['post_type'], $f['fields']);
                     break;
             }
         }
     }
 }
function x_init_custom_fields()
{
    // adds a new group to the test post type
    x_add_metadata_group('x_metaBox1', 'x_test', array('label' => 'Group with Multiple Fields'));
    // adds another group to the test post type + posts + users
    x_add_metadata_group('x_metaBox2', array('x_test', 'post', 'user'), array('label' => 'Group for Post and User', 'description' => "Here's a group with a description!"));
    // adds a text field to the first group
    x_add_metadata_field('x_fieldName1', 'x_test', array('group' => 'x_metaBox1', 'description' => 'This is field #1. It\'s a simple text field.', 'label' => 'Text Field', 'display_column' => true));
    // adds a text field to the 2nd group
    x_add_metadata_field('x_fieldName2', 'x_test', array('group' => 'x_metaBox1', 'display_column' => 'My Column (with Custom Callback)', 'display_column_callback' => 'x_field_name2_callback', 'label' => 'Text with Custom Callback'));
    // adds a cloneable textarea field to the 1st group
    x_add_metadata_field('x_fieldTextarea1', 'x_test', array('group' => 'x_metaBox1', 'field_type' => 'textarea', 'multiple' => true, 'label' => 'Repeatable Text Area'));
    // adds a readonly textarea field to the 1st group
    x_add_metadata_field('x_fieldTextareaReadOnly1', 'x_test', array('group' => 'x_metaBox1', 'field_type' => 'textarea', 'readonly' => true, 'label' => 'Read Only Text Area'));
    // adds a readonly text field to the 1st group
    x_add_metadata_field('x_fieldTextReadOnly1', 'x_test', array('group' => 'x_metaBox1', 'readonly' => true, 'label' => 'Read Only Text Area'));
    // adds a wysiwyg (full editor) field to the 2nd group
    x_add_metadata_field('x_fieldWysiwyg1', array('x_test', 'user'), array('group' => 'x_metaBox2', 'field_type' => 'wysiwyg', 'label' => 'TinyMCE / Wysiwyg field'));
    // adds a datepicker field to the 1st group
    x_add_metadata_field('x_fieldDatepicker1', 'x_test', array('group' => 'x_metaBox1', 'field_type' => 'datepicker', 'label' => 'Datepicker field'));
    // adds a datetimepicker field to the 1st group
    x_add_metadata_field('x_fieldDatetimepicker1', 'x_test', array('group' => 'x_metaBox1', 'field_type' => 'datetimepicker', 'label' => 'Datetimepicker field'));
    // adds a timepicker field to the 1st group
    x_add_metadata_field('x_fieldTimepicker1', 'x_test', array('group' => 'x_metaBox1', 'field_type' => 'timepicker', 'label' => 'Timepicker field'));
    // adds an upload field to the 1st group
    x_add_metadata_field('x_fieldUpload1', 'x_test', array('group' => 'x_metaBox1', 'field_type' => 'upload', 'readonly' => true, 'label' => 'Upload field'));
    // adds a checkbox field to the first group
    x_add_metadata_field('x_fieldCheckbox1', 'x_test', array('group' => 'x_metaBox1', 'field_type' => 'checkbox', 'label' => 'Checkbox field'));
    // adds a radio button field to the first group
    x_add_metadata_field('x_fieldRadio1', 'x_test', array('group' => 'x_metaBox1', 'field_type' => 'radio', 'values' => array('option1' => 'Option #1', 'option2' => 'Option #2'), 'label' => 'Radio field'));
    // adds a select box in the first group
    x_add_metadata_field('x_fieldSelect1', 'x_test', array('group' => 'x_metaBox1', 'field_type' => 'select', 'values' => array('option1' => 'Option #1', 'option2' => 'Option #2'), 'label' => 'Select field'));
    // adds a multi-select field in the first group
    x_add_metadata_field('x_field_multi_select', 'x_test', array('group' => 'x_metaBox1', 'field_type' => 'multi_select', 'values' => array('option1' => 'Option #1', 'option2' => 'Option #2', 'option3' => 'Option #3', 'option4' => 'Option #4'), 'label' => 'Multi Select field'));
    // adds a multi-select field with chosen in the first group
    // note: `select2` and `chosen` args do the exact same (add select2)
    // but for the purposes of testing, we're using chosen here
    x_add_metadata_field('x_field_multi_select_chosen', 'x_test', array('group' => 'x_metaBox1', 'field_type' => 'multi_select', 'values' => array('option1' => 'Option #1', 'option2' => 'Option #2', 'option3' => 'Option #3', 'option4' => 'Option #4'), 'label' => 'Multi Select field (with chosen)', 'chosen' => true));
    // adds a select field with select2 in the first group
    x_add_metadata_field('x_field_select_select2', 'x_test', array('group' => 'x_metaBox1', 'field_type' => 'select', 'values' => array('option1' => 'Option #1', 'option2' => 'Option #2', 'option3' => 'Option #3', 'option4' => 'Option #4'), 'label' => 'Select field (with select2)', 'select2' => true));
    // adds a taxonomy checkbox field in the first group
    x_add_metadata_field('x_field_taxonomy_checkbox', 'x_test', array('group' => 'x_metaBox1', 'field_type' => 'taxonomy_checkbox', 'taxonomy' => 'category', 'label' => 'Category checkbox field'));
    // adds a taxonomy select field in the first group
    x_add_metadata_field('x_field_taxonomy_select', 'x_test', array('group' => 'x_metaBox1', 'field_type' => 'taxonomy_select', 'taxonomy' => 'category', 'label' => 'Category select field'));
    // adds a taxonomy multiselect field in the first group
    x_add_metadata_field('x_field_taxonomy_multi_select', 'x_test', array('group' => 'x_metaBox1', 'field_type' => 'taxonomy_multi_select', 'taxonomy' => 'category', 'label' => 'Category multiselect field'));
    // adds a taxonomy multiselect w/ select2 field in the first group
    x_add_metadata_field('x_field_taxonomy_multi_select2', 'x_test', array('group' => 'x_metaBox1', 'field_type' => 'taxonomy_multi_select', 'taxonomy' => 'category', 'label' => 'Category multiselect w/ select2 field', 'select2' => true));
    // adds a number field in the first group (with no min/max)
    x_add_metadata_field('x_field_number', 'x_test', array('group' => 'x_metaBox1', 'field_type' => 'number', 'label' => 'Number field'));
    // adds a number field in the first group (with min/max)
    x_add_metadata_field('x_field_number_with_min_max', 'x_test', array('group' => 'x_metaBox1', 'field_type' => 'number', 'min' => '-3', 'max' => '25', 'multiple' => true, 'label' => 'Number field (with min/max + cloneable)'));
    // adds an email field in the first group
    x_add_metadata_field('x_field_email', 'x_test', array('group' => 'x_metaBox1', 'field_type' => 'email', 'label' => 'Email field'));
    // adds a link field in the first group
    x_add_metadata_field('x_field_link', 'x_test', array('group' => 'x_metaBox1', 'field_type' => 'link', 'label' => 'Link field'));
    // adds a telephone field in the first group (with default value)
    x_add_metadata_field('x_field_telephone', 'x_test', array('group' => 'x_metaBox1', 'field_type' => 'tel', 'label' => 'Telephone field', 'default_value' => '123-4567'));
    // adds a text field with a default value
    x_add_metadata_field('x_field_text_default', 'x_test', array('group' => 'x_metaBox1', 'field_type' => 'text', 'label' => 'Text field with default value', 'default_value' => 'lorem ipsum'));
    // adds a text field with placeholder
    x_add_metadata_field('x_field_textarea_placeholder', 'x_test', array('group' => 'x_metaBox1', 'field_type' => 'textarea', 'label' => 'Textarea field with placeholder', 'placeholder' => 'some placeholder text'));
    // adds a password field with placeholder
    x_add_metadata_field('x_field_password_placeholder', 'x_test', array('group' => 'x_metaBox1', 'field_type' => 'password', 'label' => 'Password field with placeholder', 'placeholder' => 'some placeholder text'));
    // adds a number field with placeholder
    x_add_metadata_field('x_field_number_placeholder', 'x_test', array('group' => 'x_metaBox1', 'field_type' => 'number', 'label' => 'Number field with placeholder', 'placeholder' => 'some placeholder text'));
    // adds an email field with placeholder
    x_add_metadata_field('x_field_email_placeholder', 'x_test', array('group' => 'x_metaBox1', 'field_type' => 'email', 'label' => 'Email field with placeholder', 'placeholder' => 'some placeholder text'));
    // adds a link field with placeholder
    x_add_metadata_field('x_field_link_placeholder', 'x_test', array('group' => 'x_metaBox1', 'field_type' => 'link', 'label' => 'Link field with placeholder', 'placeholder' => 'some placeholder text'));
    // adds an telephone field with placeholder
    x_add_metadata_field('x_field_telephone_placeholder', 'x_test', array('group' => 'x_metaBox1', 'field_type' => 'tel', 'label' => 'Telephone field with placeholder', 'placeholder' => 'some placeholder text'));
    // adds an upload field with placeholder
    x_add_metadata_field('x_field_upload_placeholder', 'x_test', array('group' => 'x_metaBox1', 'field_type' => 'upload', 'label' => 'Upload field with placeholder', 'placeholder' => 'some placeholder text'));
    // adds an datepicker field with placeholder
    x_add_metadata_field('x_field_datepicker_placeholder', 'x_test', array('group' => 'x_metaBox1', 'field_type' => 'datepicker', 'label' => 'Datepicker field with placeholder', 'placeholder' => 'some placeholder text'));
    // adds a datetimepicker field with placeholder
    x_add_metadata_field('x_field_datetimepicker_placeholder', 'x_test', array('group' => 'x_metaBox1', 'field_type' => 'datetimepicker', 'label' => 'Datetimepicker field with placeholder', 'placeholder' => 'some placeholder text'));
    // adds a timepicker field with placeholder
    x_add_metadata_field('x_field_timepicker_placeholder', 'x_test', array('group' => 'x_metaBox1', 'field_type' => 'timepicker', 'label' => 'Timepicker field with placeholder', 'placeholder' => 'some placeholder text'));
    // adds a mulitifield
    x_add_metadata_multifield('x_test_multifield', 'x_test', array('group' => 'x_metabox1', 'label' => 'Multifield test', 'description' => 'This is a great multifield'));
    // adds a text field to the multifield
    x_add_metadata_field('multifield_field_1', 'x_test', array('group' => 'x_metabox1', 'multifield' => 'x_test_multifield', 'description' => 'This is field #1 of the multifield.', 'label' => 'Text Field', 'field_type' => 'text'));
    // adds an upload text field to the multifield
    x_add_metadata_field('multifield_field_2', 'x_test', array('group' => 'x_metabox1', 'multifield' => 'x_test_multifield', 'description' => 'This is field #2 of the multifield.', 'label' => 'Upload Field', 'field_type' => 'upload'));
    // adds an upload text field to the multifield
    x_add_metadata_field('multifield_field_3', 'x_test', array('group' => 'x_metabox1', 'multifield' => 'x_test_multifield', 'description' => 'This is field #4 of the multifield.', 'label' => 'Telephone Field', 'field_type' => 'tel'));
    // adds a text field to the multifield
    x_add_metadata_field('multifield_field_4', 'x_test', array('group' => 'x_metabox1', 'multifield' => 'x_test_multifield', 'description' => 'This is field #4 of the multifield.', 'label' => 'Password Field', 'field_type' => 'password'));
    // adds a field to posts and users
    x_add_metadata_field('x_fieldName2', array('post', 'user'), array('group' => 'x_metaBox2', 'label' => 'Text field'));
    // adds a field with a custom display callback (see below)
    x_add_metadata_field('x_fieldCustomHidden1', 'x_test', array('group' => 'x_metaBox1', 'display_callback' => 'x_field_customhidden1_callback', 'label' => 'Hidden field'));
    // field with capabilities limited
    x_add_metadata_field('x_cap-limited-field', 'x_test', array('label' => 'Cap Limited Field (edit_posts)', 'required_cap' => 'edit_posts'));
    // field with role limited
    x_add_metadata_field('x_author-cap-limited-field', 'user', array('label' => 'Cap Limited Field (author)', 'required_cap' => 'author'));
    // comment field
    x_add_metadata_field('x_commentField1', 'comment', array('label' => 'Field for Comment', 'display_column' => true));
    // field that exludes posts
    x_add_metadata_field('x_fieldNameExcluded1', 'post', array('description' => 'This field is excluded from Post ID#2476', 'label' => 'Excluded Field', 'exclude' => 2476));
    // field that includes certain posts only
    x_add_metadata_field('x_fieldNameIncluded1', 'post', array('description' => 'This field is only included on Post ID#2476', 'label' => 'Included Field', 'include' => 2476));
    x_add_metadata_field('x_fieldExcludeCallback', 'post', array('description' => 'This field is excluded using a custom callback; will be excluded from posts in the "aside" category', 'label' => 'Excluded Field (with callback)', 'exclude' => 'x_custom_exclude_callback'));
    /**
     *
     *
     * @param unknown $thing_slug  string Slug of the field or group
     * @param unknown $thing       object Field or Group args set up when registering
     * @param unknown $object_type string What type of object (post, comment, user)
     * @param unknown $object_id   int|string ID of the object
     * @param unknown $object_slug string
     */
    function x_custom_exclude_callback($thing_slug, $thing, $object_type, $object_id, $object_slug)
    {
        // exclude from all posts that are in the aside category
        return in_category('aside', $object_id);
    }
    x_add_metadata_field('x_fieldIncludedCallback', 'post', array('description' => 'This field is included using a custom callback; will only be included for posts that are not published', 'label' => 'Included Field (with callback)', 'include' => 'x_custom_include_callback'));
    function x_custom_include_callback($thing_slug, $thing, $object_type, $object_id, $object_slug)
    {
        $post = get_post($object_id);
        return 'publish' != $post->post_status;
    }
}