0

Been working on a method for my Custom Post Type PHP Class to add a submenu page to the Admin Menu for use in the template.

The add subpage method is as follows:

/**
 * Adds a sub menu to the custom post type menu for things like adding options to be stored in the database.
 *
 * @since 1.0.0
 * @access public
 *
 * @param string $title What appears in the browser window's title
 * @param array $settings What option fields the user wants to add to the options page
 * @param string $capability (optional) What capabilities the user must have to access page (default is admin)
 */
public function add_submenu_page( $title, $settings = array(), $capability = 'administrator' ) {

    // Set variables
    $post_type = self::uglify( $this->post_type_name );
    $menu_title = self::beautify( $title );
    $menu_capability = $capability;
    $parent_slug = 'edit.php?post_type=' . $post_type;
    $menu_slug = $post_type . '_' . 'menu_' . self::uglify( $title );
    $menu_settings = $settings;

    add_action( 'admin_menu',
        function() use( $post_type, $parent_slug, $menu_title, $menu_capability, $menu_slug, $menu_settings ) {

            add_submenu_page(
                $parent_slug,
                $menu_title,
                $menu_title,
                $menu_capability,
                $menu_slug,
                function() use( $post_type, $menu_settings, $menu_title ) {
                    $menu_page_name = self::beautify( $this->post_type_name ) . ' ' . $menu_title;

                    $option_group = $post_type . '_' . self::uglify( $menu_title ) . '_options';
                    settings_fields( $option_group );
                    do_settings_sections( $option_group );

                    echo '<div class="wrap">';
                    echo '<h1>' . $menu_page_name . '</h1>';

                    echo '<form method="post" action="options.php">';
                    echo '<table class="form-table">';
                    echo '<tbody>';

                    foreach ( $menu_settings as $label => $setting ) {

                        if ( isset( $setting['attributes'] ) ) {
                            $attributes = $setting['attributes'];
                        } else {
                            $attributes = array();
                        }

                        if ( isset( $setting['select_options'] ) ) {
                            $select_options = $setting['select_options'];
                        } else {
                            $select_options = array();
                        }

                        $input_id = self::uglify( $menu_page_name ) . '_' . self::uglify( $label );
                        // Create Label
                        echo '<tr>';
                        echo '<th scope="row">';
                        echo self::add_input_label( $input_id, $label );
                        echo '</th>';

                        // Create input element
                        echo '<td>';
                        echo self::add_admin_option_field( $option_group, $input_id, $setting['type'],
                            $attributes, $select_options );
                        echo '</td>';
                        echo '</tr>';
                    }

                    echo '</tbody>';
                    echo '</table>';

                    submit_button();

                    echo '</form>';
                    echo '</div>';
                }
            );
    } );
}

I also have two helper methods that construct the <label> element as well as the appropriate form field. Both of these functions in terms of the HTML output sent to the browser is working fine. The code for add_admin_option_field is as follows:

/**
 * Builds and HTML form field for use in an admin options page
 *
 * @since 1.0.0
 * @access public
 *
 * @param string $option_group The option group the admin page settings will be stored in WordPress database
 * @param string $field_id_name The value of the element's id attribute
 * @param string $field_type The type of form field being created
 * @param array $attributes (optional) An array of attributes for an input element
 * @param array $select_options (optional) An array of options for use in a select element
 *
 * @return string The form element to be displayed by the browser
 */
public static function add_admin_option_field(
    $option_group, $field_id_name, $field_type, $attributes, $select_options
) {

    // Initialze the form element
    $form_element = '';

    if ( $field_type == 'text' ) {
        $form_element = '<input type="' . $field_type . '" name="' . $field_id_name . '" id="' .
                        $field_id_name . '" value="' . esc_attr( get_option( $field_id_name ) ) . '" ';

        if ( isset( $attributes ) && ! empty( $attributes) ) {
            $form_element .= self::input_attributes( $attributes );
        }

        $form_element .= ' />';
    }

    if ( $field_type == 'select' ) {
        $form_element .= '<select>';

        foreach ( $select_options as $option ) {
            $form_element .= '<option value="' . $option . '" ' . selected( get_option( $field_id_name ), $option ) . '>' .
                             $option . '</option>';
        }

        $form_element .= '</select>';
    }

    if ( $field_type == 'checkbox' ) {
        $form_element .= '<input type="' . $field_type . '" name="' . $field_id_name . '" id="' . $field_id_name . '" value="' . $field_id_name . '" ' . checked( get_option( $field_id_name ), $field_id_name, false ) . ' />';
    }

    // Register Setting
    add_action( 'admin_init', function () use ( $option_group, $field_id_name ) {
        register_setting( $option_group, $field_id_name );
    });

    return $form_element;
}

The problem I am having is that while the HTML output is correct, it seems like the add_action() call is not firing. When I click on the submit button on the options page I created, the Admin menu switches views and default Settings menu is highlighted and the form displayed in the content area is actually forms for every line in the wp_options table and my custom values are nowhere to be found.

I am using the WP Codex page Creating Options Page as my model but cannot see where I am going on as nothing is being sent to debug.log even if I put an error_log() call inside the add_action().

Is this not possible in an anonymous function or am I simply missing something?

  • your anon function takes two args but you have not specified this (fourth param of add_action) – inarilo Dec 30 '17 at 4:43
  • you set the form action to "options.php", are you sure this is good ? – mmm Dec 30 '17 at 17:04
  • @inarilo - I added , 10, 2 as parameters and it still does not save them to the database and still gives me the admin page with everything in wp_options table when I click on the submit button. @mmm Yes, this is how it is shown in the WP Codex. – Cedon Dec 30 '17 at 17:56
  • sorry that was wrong, just realised those are not function params :s i think it could have to do with scope, when the function is called, the variable values are already lost? but i have not used use so not sure. – inarilo Dec 30 '17 at 18:29
  • @inarilo use() basically is another means to pass variables into a function. WordPress will generate an error if I create a dynamic action/filter like this and try to pass the variables in directly. – Cedon Dec 30 '17 at 18:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.