0

For my custom settings field, I am looking to insert it right after the Site Address (URL) field in the General settings page.

I'm able to add the custom field sucessfully using the add_settings_field(). Be default, it add the custom field at the bottom. Using jQuery, I was able to display my custom field after the Site Address (URL):

add_action( 'admin_footer', 'wpse_243810_admin_footer' );
function wpse_243810_admin_footer() {
    ?>
    <script type="text/javascript">
    jQuery('#protocol_relative').closest('tr').insertAfter('#home-description').closest('tr');
    </script>
    <?php
}

However, it looks like the following instead:

Looking at the code, it inserts my custom field within the Site Address field's <tr> element. How get I have it inserted outide of it instead? Below are the seperate code snippets of each field.

<tr>
    <th scope="row"><label for="home">Site Address (URL)</label></th>
    <td>
        <input name="home" type="url" id="home" aria-describedby="home-description" value="http://example.com" class="regular-text code">
        <p class="description" id="home-description">Enter the address here if you <a href="//codex.wordpress.org/Giving_WordPress_Its_Own_Directory">want your site home page to be different from your WordPress installation directory.</a></p>
    </td>
</tr>

This is the custom field that my plugin generates which I want ot insert after:

<tr>
    <th scope="row">Protocol Relative URL</th>
    <td>
        <fieldset>
            <legend class="screen-reader-text"><span>Protocol Relative URL</span></legend>
            <label for="remove_http">
            <input name="protocol_relative" type="checkbox" id="protocol_relative" value="1" checked="checked">Do not apply to external links
            </label>
            <p class="description">Only the internal links will be affected.</p>
        </fieldset>
    </td>
</tr>
1

Figured it out by using the following jQuery function. The #protocol_relative is the field I am inserting and #home-description is the field I am inserting it after:

add_action( 'admin_footer', 'insert_field' );
function insert_field() {
    # Insert the settings field after the 'Site Address (URL)'
    ?> <script type="text/javascript">
    jQuery( '#protocol_relative' ).closest( 'tr' ).insertAfter( jQuery( '#home-description' ).closest( 'tr' ) );
    </script> <?php
}
0

I think that this is not possible without modifying the core-files. We only have one time do_settings_fields and do_settings_sections in the options-permalink.php between line 226 and 232 for the optional section.

...
    </tr>
    <?php do_settings_fields('permalink', 'optional'); ?>
</table>

<?php do_settings_sections('permalink'); ?>

<?php submit_button(); ?>
...

The WordPress functions add_settings_field and add_settings_section are using the settings api. In the core files are the do_settings_fields and do_settings_sections functions which will add custom fields or sections (which u added with this api). These are required to place anything in a page. Also these functions are only placed (hardcoded) in the options section of the permalink page. You dont have an access-point in the geneal section like for the options section.

0

You might just be missing the add_settings_section before add_settings_field. This works, and saves the field to an option, but I might button up that portion. I just wanted to hook earlier than the checks in options-permalink.php.

<?php

// ADD SETTINGS

add_action('admin_head', function(){

    // Create a section after the permalink

    add_settings_section(
        'permalink_relative_setting_section_options',           // id
        __( 'Protocol Relative URL', 'textdomain' ),            // title
        'premalink_relative_setting_section_callback_function', // callback
        'permalink'                                             // page
    );

    // Add a field to the section

    add_settings_field(
        'permalink_relative_settings_field-id',          // id
        '',                                              // title
        'permalink_relative_settings_field_callback',    // callback
        'permalink',                                     // page
        'permalink_relative_setting_section_options',    // section
        array( 'some_arg' => 'For use in the callback' ) // args
    );

});

// SECTION

function premalink_relative_setting_section_callback_function( $args ) {

    // Echo SECTION intro text here

    /*
    echo '<p>id: ' . esc_html( $args['id'] ) . '</p>';                         // id: eg_setting_section
    echo '<p>title: ' . apply_filters( 'the_title', $args['title'] ) . '</p>'; // title: Example settings section in reading
    echo '<p>callback: ' . esc_html( $args['callback'] ) . '</p>';             // callback: eg_setting_section_callback_function
    */
}

// FIELD

function permalink_relative_settings_field_callback( $args ) {

    $options = get_option( 'permalink_relative_setting_section_options' );

    $html = '<input type="checkbox" id="relative_checkbox" name="permalink_relative_setting_section_options[relative_checkbox]" value="1"' . checked( 1, $options[ 'relative_checkbox' ], false ) . '/>';

    $html .= '<label for="relative_checkbox">Do not apply to external links</label>';

    echo $html;
}

// UPDATE

add_action( 'init', function() {

    // If permalink structure is detected, let's update our option before the page can act

    if ( isset( $_POST[ 'permalink_structure' ] ) || isset( $_POST[ 'category_base' ] ) ) {

        check_admin_referer( 'update-permalink' );

        $options = get_option( 'permalink_relative_setting_section_options' );

        $options[ 'relative_checkbox' ] = ( isset( $_POST[ 'permalink_relative_setting_section_options' ][ 'relative_checkbox' ] ) && $_POST[ 'permalink_relative_setting_section_options' ][ 'relative_checkbox' ] === '1' )
            ? '1' // checked
            : '';

        update_option( 'permalink_relative_setting_section_options', $options );
    }
} );

Alternate

If you look at https://github.com/WordPress/WordPress/blob/master/wp-admin/options-permalink.php#L178 there aren't any hooks to do what you want you want.

Consider jQuery's manipulation methods like detach and insertAfter which you could utilize in the admin_footer.

jQuery('<h1>Protocol Relative URL Form!</h1>').insertAfter('.form-table.permalink-structure');
  • Thanks for giving it a go. Unfortunately, after playing around with your code, it still adds a section to the bottom of the permalinks page, rather than a custom field after the Common Settings section. I've update my question with another alternative that I'm willing to take. – Ethan Jinks O'Sullivan Oct 25 '16 at 6:29
  • Sorry about that. I must have glossed over where you wanted it. Have you considered jQuery in the admin_footer to move it exactly where you want? That could save you a lot of effort in the long run. – jgraup Oct 25 '16 at 6:36
  • I was thinking about that after I updated my option. Honestly, the end result is what matters, I'm open to whatever option is needed to achieve that goal. – Ethan Jinks O'Sullivan Oct 25 '16 at 6:49
  • Well, by admin_footer, I think I just mean enqueue scripts or inline them in the footer to trigger the form field shuffle after the page loads. – jgraup Oct 25 '16 at 6:53

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.