admin管理员组文章数量:1434916
I have a class used for a plugin's admin form, using the Settings API. It has a lot of fields, and some of those fields depend on already existing values in wp_options
.
The existing options determine how often to render a field (in this case, it's a MailChimp API integration that renders a field for each list in the API, which is several layers down the stored API data).
In the admin interface, I have nine fields that get displayed. This is as it should be. But only the first three will save any data. I've tried changing the field types around on those first three and they always work, and I've also tried changing the types around on the last six, and they never work.
One other thing I tried was hardcoding the full ID values of the last six fields outside the big nested foreach
. The fields save their data then.
Here's the code:
add_action( 'admin_init', array( $this, 'admin_settings_form' ) );
/**
* Register items for the settings api
* @return void
*
*/
public function admin_settings_form() {
$get_data = filter_input_array( INPUT_GET, FILTER_SANITIZE_STRING );
$page = isset( $get_data['tab'] ) ? sanitize_key( $get_data['tab'] ) : 'minnpost_mailchimp_settings';
$section = isset( $get_data['tab'] ) ? sanitize_key( $get_data['tab'] ) : 'minnpost_mailchimp_settings';
$this->form_settings( 'form_settings', 'form_settings' );
}
private function form_settings( $page, $section ) {
$form_sections = $this->setup_form_sections();
$settings = array();
if ( ! empty( $form_sections ) ) {
foreach ( $form_sections as $key => $value ) {
$section = $key;
// translators: 1 is the name of the shortcode
$title = sprintf( 'Shortcode: [%1$s]',
esc_attr( strtolower( $value ) )
);
$page = $section;
add_settings_section( $section, $title, null, $page );
$settings[ $section . '_resource_type' ] = array(
'title' => __( 'Resource type'),
'callback' => 'display_select',
'page' => $page,
'section' => $section,
'args' => array(
'type' => 'select',
'items' => $this->get_resource_types(),
),
);
$resource_type = get_option( $this->option_prefix . 'newsletter_form_resource_type', '' );
$settings[ $section . '_resource_id' ] = array(
'title' => __( 'Resource name' ),
'callback' => 'display_select',
'page' => $page,
'section' => $section,
'args' => array(
'type' => 'select',
'items' => $this->get_resource_ids( $resource_type ),
),
);
$resource_id = get_option( $this->option_prefix . 'newsletter_form_resource_id', '' );
if ( 'lists' === $resource_type ) {
$settings[ $section . '_' . $resource_type . '_default_member_status' ] = array(
'title' => __( 'Default member status' ),
'callback' => 'display_select',
'page' => $page,
'section' => $section,
'args' => array(
'type' => 'select',
'items' => $this->get_member_statuses(),
),
);
}
$item_keys = array();
$subresource_types = get_option( $this->parent_option_prefix . 'subresource_types_' . $resource_type, array() );
if ( ! empty( $subresource_types[ $resource_type ] ) ) {
$subresource_types = $subresource_types[ $resource_type ];
foreach ( $subresource_types as $subresource_type ) {
$items = get_option( $this->parent_option_prefix . 'subresources_' . $resource_id . '_' . $subresource_type, array() );
if ( ! empty( $items[ $resource_type ][ $resource_id ][ $subresource_type ] ) ) {
$subresources = $items[ $resource_type ][ $resource_id ][ $subresource_type ];
$methods = get_option( $this->parent_option_prefix . 'subresource_methods', array() );
if ( ! empty( $methods[ $resource_type ][ $resource_id ][ $subresource_type ] ) ) {
$methods = $methods[ $resource_type ][ $resource_id ][ $subresource_type ];
foreach ( $subresources as $subresource ) {
foreach ( $methods as $method ) {
$test_all_items = $this->get_all_items( $resource_type, $resource_id, $subresource_type, $subresource, $method );
if ( ! empty( $test_all_items ) ) {
foreach ( $test_all_items as $test_item ) {
$settings[ $section . '_' . $subresource_type . '_' . $subresource . '_' . $method . '_' . $test_item['id'] . '_title' ] = array(
'title' => __( 'Title' ),
'callback' => 'display_input_field',
'page' => $page,
'section' => $section,
'args' => array(
'type' => 'text',
),
);
} // End foreach().
}
} // End foreach().
} // End foreach().
} // End if().
} // End if().
} // End foreach().
} // End if().
} // End foreach().
} // End if().
foreach ( $settings as $key => $attributes ) {
$id = $this->option_prefix . $key;
$name = $this->option_prefix . $key;
$title = $attributes['title'];
$callback = $attributes['callback'];
$page = $attributes['page'];
$section = $attributes['section'];
$args = array_merge(
$attributes['args'],
array(
'title' => $title,
'id' => $id,
'label_for' => $id,
'name' => $name,
'class' => $class,
)
);
add_settings_field( $id, $title, $callback, $page, $section, $args );
register_setting( $section, $id );
} // End foreach().
}
/**
* Default display for <input> fields
*
* @param array $args
*/
public function display_input_field( $args ) {
$type = $args['type'];
$id = $args['label_for'];
$name = $args['name'];
$checked = '';
$class = 'regular-text';
$value = esc_attr( get_option( $id, '' ) );
if ( 'checkbox' === $type ) {
$value = filter_var( get_option( $id, false ), FILTER_VALIDATE_BOOLEAN );
if ( true === $value ) {
$checked = 'checked ';
}
$value = 1;
}
if ( '' === $value && isset( $args['default'] ) && '' !== $args['default'] ) {
$value = $args['default'];
}
echo sprintf( '<input type="%1$s" value="%2$s" name="%3$s" id="%4$s" class="%5$s"%6$s>',
esc_attr( $type ),
esc_attr( $value ),
esc_attr( $name ),
esc_attr( $id ),
sanitize_html_class( $class, esc_html( ' code' ) ),
esc_html( $checked )
);
}
/**
* Display for a dropdown
*
* @param array $args
*/
public function display_select( $args ) {
$type = $args['type'];
$id = $args['label_for'];
$name = $args['name'];
$desc = $args['desc'];
if ( ! isset( $args['constant'] ) || ! defined( $args['constant'] ) ) {
$current_value = get_option( $name );
echo sprintf( '<div class="select"><select id="%1$s" name="%2$s"><option value="">- Select one -</option>',
esc_attr( $id ),
esc_attr( $name )
);
foreach ( $args['items'] as $key => $value ) {
$text = $value['text'];
$value = $value['value'];
$selected = '';
if ( $key === $current_value || $value === $current_value ) {
$selected = ' selected';
}
echo sprintf( '<option value="%1$s"%2$s>%3$s</option>',
esc_attr( $value ),
esc_attr( $selected ),
esc_html( $text )
);
}
echo '</select>';
if ( '' !== $desc ) {
echo sprintf( '<p class="description">%1$s</p>',
esc_html( $desc )
);
}
echo '</div>';
} else {
echo sprintf( '<p><code>%1$s</code></p>',
esc_html__( 'Defined in wp-config.php', 'minnpost-form-processor-mailchimp' )
);
}
}
I'm able to run an error log where the register_setting
and add_settings_field
methods are called, and all the values match what they should. In this case, section displays as "newsletter_form". The HTML template (which is added earlier via add_options_page
) looks like this:
<div id="main">
<form method="post" action="options.php">
<?php
settings_fields( 'newsletter_form' ) . do_settings_sections( 'newsletter_form' );
?>
<?php submit_button( __( 'Save settings', 'minnpost-form-processor-settings' ) ); ?>
</form>
</div>
I'm having trouble figuring out why the nested options don't save. I went into wp-includes/option.php
to try some debugging.
I ran error_log( 'post is ' . print_r( $_POST, true ) );
inside there and it did have the missing data. Then I went to the foreach ( $options as $option ) {
line and ran error_log( 'option is ' . $option );
and it did not have the missing data.
So something is keeping my missing fields from being added to the $options
array.
What can I try next on this?
I have a class used for a plugin's admin form, using the Settings API. It has a lot of fields, and some of those fields depend on already existing values in wp_options
.
The existing options determine how often to render a field (in this case, it's a MailChimp API integration that renders a field for each list in the API, which is several layers down the stored API data).
In the admin interface, I have nine fields that get displayed. This is as it should be. But only the first three will save any data. I've tried changing the field types around on those first three and they always work, and I've also tried changing the types around on the last six, and they never work.
One other thing I tried was hardcoding the full ID values of the last six fields outside the big nested foreach
. The fields save their data then.
Here's the code:
add_action( 'admin_init', array( $this, 'admin_settings_form' ) );
/**
* Register items for the settings api
* @return void
*
*/
public function admin_settings_form() {
$get_data = filter_input_array( INPUT_GET, FILTER_SANITIZE_STRING );
$page = isset( $get_data['tab'] ) ? sanitize_key( $get_data['tab'] ) : 'minnpost_mailchimp_settings';
$section = isset( $get_data['tab'] ) ? sanitize_key( $get_data['tab'] ) : 'minnpost_mailchimp_settings';
$this->form_settings( 'form_settings', 'form_settings' );
}
private function form_settings( $page, $section ) {
$form_sections = $this->setup_form_sections();
$settings = array();
if ( ! empty( $form_sections ) ) {
foreach ( $form_sections as $key => $value ) {
$section = $key;
// translators: 1 is the name of the shortcode
$title = sprintf( 'Shortcode: [%1$s]',
esc_attr( strtolower( $value ) )
);
$page = $section;
add_settings_section( $section, $title, null, $page );
$settings[ $section . '_resource_type' ] = array(
'title' => __( 'Resource type'),
'callback' => 'display_select',
'page' => $page,
'section' => $section,
'args' => array(
'type' => 'select',
'items' => $this->get_resource_types(),
),
);
$resource_type = get_option( $this->option_prefix . 'newsletter_form_resource_type', '' );
$settings[ $section . '_resource_id' ] = array(
'title' => __( 'Resource name' ),
'callback' => 'display_select',
'page' => $page,
'section' => $section,
'args' => array(
'type' => 'select',
'items' => $this->get_resource_ids( $resource_type ),
),
);
$resource_id = get_option( $this->option_prefix . 'newsletter_form_resource_id', '' );
if ( 'lists' === $resource_type ) {
$settings[ $section . '_' . $resource_type . '_default_member_status' ] = array(
'title' => __( 'Default member status' ),
'callback' => 'display_select',
'page' => $page,
'section' => $section,
'args' => array(
'type' => 'select',
'items' => $this->get_member_statuses(),
),
);
}
$item_keys = array();
$subresource_types = get_option( $this->parent_option_prefix . 'subresource_types_' . $resource_type, array() );
if ( ! empty( $subresource_types[ $resource_type ] ) ) {
$subresource_types = $subresource_types[ $resource_type ];
foreach ( $subresource_types as $subresource_type ) {
$items = get_option( $this->parent_option_prefix . 'subresources_' . $resource_id . '_' . $subresource_type, array() );
if ( ! empty( $items[ $resource_type ][ $resource_id ][ $subresource_type ] ) ) {
$subresources = $items[ $resource_type ][ $resource_id ][ $subresource_type ];
$methods = get_option( $this->parent_option_prefix . 'subresource_methods', array() );
if ( ! empty( $methods[ $resource_type ][ $resource_id ][ $subresource_type ] ) ) {
$methods = $methods[ $resource_type ][ $resource_id ][ $subresource_type ];
foreach ( $subresources as $subresource ) {
foreach ( $methods as $method ) {
$test_all_items = $this->get_all_items( $resource_type, $resource_id, $subresource_type, $subresource, $method );
if ( ! empty( $test_all_items ) ) {
foreach ( $test_all_items as $test_item ) {
$settings[ $section . '_' . $subresource_type . '_' . $subresource . '_' . $method . '_' . $test_item['id'] . '_title' ] = array(
'title' => __( 'Title' ),
'callback' => 'display_input_field',
'page' => $page,
'section' => $section,
'args' => array(
'type' => 'text',
),
);
} // End foreach().
}
} // End foreach().
} // End foreach().
} // End if().
} // End if().
} // End foreach().
} // End if().
} // End foreach().
} // End if().
foreach ( $settings as $key => $attributes ) {
$id = $this->option_prefix . $key;
$name = $this->option_prefix . $key;
$title = $attributes['title'];
$callback = $attributes['callback'];
$page = $attributes['page'];
$section = $attributes['section'];
$args = array_merge(
$attributes['args'],
array(
'title' => $title,
'id' => $id,
'label_for' => $id,
'name' => $name,
'class' => $class,
)
);
add_settings_field( $id, $title, $callback, $page, $section, $args );
register_setting( $section, $id );
} // End foreach().
}
/**
* Default display for <input> fields
*
* @param array $args
*/
public function display_input_field( $args ) {
$type = $args['type'];
$id = $args['label_for'];
$name = $args['name'];
$checked = '';
$class = 'regular-text';
$value = esc_attr( get_option( $id, '' ) );
if ( 'checkbox' === $type ) {
$value = filter_var( get_option( $id, false ), FILTER_VALIDATE_BOOLEAN );
if ( true === $value ) {
$checked = 'checked ';
}
$value = 1;
}
if ( '' === $value && isset( $args['default'] ) && '' !== $args['default'] ) {
$value = $args['default'];
}
echo sprintf( '<input type="%1$s" value="%2$s" name="%3$s" id="%4$s" class="%5$s"%6$s>',
esc_attr( $type ),
esc_attr( $value ),
esc_attr( $name ),
esc_attr( $id ),
sanitize_html_class( $class, esc_html( ' code' ) ),
esc_html( $checked )
);
}
/**
* Display for a dropdown
*
* @param array $args
*/
public function display_select( $args ) {
$type = $args['type'];
$id = $args['label_for'];
$name = $args['name'];
$desc = $args['desc'];
if ( ! isset( $args['constant'] ) || ! defined( $args['constant'] ) ) {
$current_value = get_option( $name );
echo sprintf( '<div class="select"><select id="%1$s" name="%2$s"><option value="">- Select one -</option>',
esc_attr( $id ),
esc_attr( $name )
);
foreach ( $args['items'] as $key => $value ) {
$text = $value['text'];
$value = $value['value'];
$selected = '';
if ( $key === $current_value || $value === $current_value ) {
$selected = ' selected';
}
echo sprintf( '<option value="%1$s"%2$s>%3$s</option>',
esc_attr( $value ),
esc_attr( $selected ),
esc_html( $text )
);
}
echo '</select>';
if ( '' !== $desc ) {
echo sprintf( '<p class="description">%1$s</p>',
esc_html( $desc )
);
}
echo '</div>';
} else {
echo sprintf( '<p><code>%1$s</code></p>',
esc_html__( 'Defined in wp-config.php', 'minnpost-form-processor-mailchimp' )
);
}
}
I'm able to run an error log where the register_setting
and add_settings_field
methods are called, and all the values match what they should. In this case, section displays as "newsletter_form". The HTML template (which is added earlier via add_options_page
) looks like this:
<div id="main">
<form method="post" action="options.php">
<?php
settings_fields( 'newsletter_form' ) . do_settings_sections( 'newsletter_form' );
?>
<?php submit_button( __( 'Save settings', 'minnpost-form-processor-settings' ) ); ?>
</form>
</div>
I'm having trouble figuring out why the nested options don't save. I went into wp-includes/option.php
to try some debugging.
I ran error_log( 'post is ' . print_r( $_POST, true ) );
inside there and it did have the missing data. Then I went to the foreach ( $options as $option ) {
line and ran error_log( 'option is ' . $option );
and it did not have the missing data.
So something is keeping my missing fields from being added to the $options
array.
What can I try next on this?
Share Improve this question asked Apr 4, 2019 at 16:37 Jonathan StegallJonathan Stegall 2692 silver badges13 bronze badges 6 | Show 1 more comment1 Answer
Reset to default 0I figured it out. It's not actually in the code above at all, but in one of the lower methods I use to generate the array keys for $settings
.
The problem was that in one of those other methods, I had the following code:
if ( ! isset( $_GET['page'] ) || $this->slug !== $_GET['page'] ) {
return $options;
}
I often use this to avoid making unnecessary API calls when users are doing other things inside the admin. But in this case, it was also preventing the plugin from getting the settings key names for those fields when the data was posted to Core's options.php
, since of course options.php
does not have the $_GET['page']
value expected by this plugin.
I still need to do some investigating to make sure I only call these things when needed, but at least for this question that is the problem, and is thus solved.
本文标签: wp adminSome fields in Settings API form are savingothers are not
版权声明:本文标题:wp admin - Some fields in Settings API form are saving, others are not 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1745622237a2666755.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
$settings[ $section . '_' . $subresource_type . '_' . $subresource . '_' . $method . '_' . $test_item['id'] . '_title' ]
which is quite long. – MikeNGarrett Commented Apr 5, 2019 at 14:31array_map
are your friends. – MikeNGarrett Commented Apr 5, 2019 at 14:50array_map
in this context? Specifically where you're loading a variable in each level that the lower levels depend on? – Jonathan Stegall Commented Apr 5, 2019 at 17:54