• geowb

    (@geowb)


    I am trying to understand how to use WP_Customize_Setting::validate(). For example, a setting named rma_user_data_uri should be saved if filter_var($data, FILTER_VALIDATE_URL)
    returns $data (where $data is submitted value of rma_user_data_uri) and allow save, or not save if filter_var(…) is false and return to the settings form ‘Invalid URI’. How might this be constructed using WP_Customize_Setting::validate()?

    Or do I need to create a custom settings form to do server-side validation and $_SESSION to return unaccepted values?

Viewing 5 replies - 1 through 5 (of 5 total)
  • Thread Starter geowb

    (@geowb)

    Here is how the current form is created:
    rma.php

    function rma_init() {
        $plugin = new Plugin(); // Create container
        $plugin['path'] = realpath(plugin_dir_path(__FILE__)) . DIRECTORY_SEPARATOR;
        $plugin['url'] = plugin_dir_url(__FILE__);
        $plugin['version'] = '0.1.0';
        $plugin['properties'] = [
            'parent_slug' => 'options-general.php',
            'page_title' => '<h2>Remote Member Authentication</h2>',
            'menu_title' => 'Remote Member Authentication',
            'capability' => 'manage_options',
            'menu_slug' => 'rma-settings',
            'option_group' => 'rma_option_group',
            'section_heading' => '',
            'submit_label' => 'Save stuff',
            'options' => [
                ['fieldName' => 'rma_user_data_uri',
                    'label' => 'User data URI',],
                ['fieldName' => 'rma_auth_type',
                    'label' => 'Authentication type'],
                ['fieldName' => 'rma_auth_type_none',
                    'label' => ''],
                ['fieldName' => 'rma_auth_type_api_key',
                    'label' => 'API key'],
                ['fieldName' => 'rma_auth_type_basic_username',
                    'label' => 'Username'],
                ['fieldName' => 'rma_auth_type_basic_password',
                    'label' => 'Password'],
            ],
        ];
        $plugin['settings_page'] = function ( $plugin ) {
            static $object;
    
            if (null !== $object) {
                return $object;
            }
            return new SettingsPage($plugin['properties']);
        };
        $templates = [
            './Templates/member-content.php' => 'Restricted Member Content',
        ];
        //initialization functions
        $templater = new Rma\PageTemplater($templates);
        add_action('init', ['Rma\Tools', 'member_password_check']);
        add_action( 'admin_enqueue_scripts', 'rmaQueueScripts' );
        add_action('plugins_loaded', array('Rma\PageTemplater', 'get_instance'));
        add_shortcode('member_sign_in', ['Rma\Shortcodes\SigninForm', 'createSignInForm']);
        $plugin->run();
    }
    

    SettingsPage.php

    
    namespace Rma;
    
    class SettingsPage extends WpSubPage
    {
    
        public function render_settings_page() {
            $option_group = $this->properties['option_group'];
            $page = $this->properties['menu_slug'];
            $submit = $this->properties['submit_label'];
            echo $this->properties['page_title'];
            ?>
            <div class="wrap">
                <form method="post" action="options.php">
                    <?php
                    settings_fields($option_group);
                    do_settings_sections($page);
                    submit_button($submit);
                    ?>
                </form>
            </div>
            <?php
        }
    }
    

    WpSubPage.php

    
    namespace Rma;
    
    abstract class WpSubPage
    {
    
        protected $properties;
    
        public function __construct($properties) {
            $this->properties = $properties;
        }
    
        public function run() {
            add_action('admin_menu', array($this, 'add_menu_and_page'));
            add_action('admin_init', array($this, 'register_settings'));
        }
    
        public function add_menu_and_page() {
    
            add_submenu_page(
                    $this->properties['parent_slug'], $this->properties['page_title'], $this->properties['menu_title'], $this->properties['capability'], $this->properties['menu_slug'], array($this, 'render_settings_page')
            );
        }
    
        public function register_settings() {
            $group = $this->properties['option_group'];
            $options = $this->properties['options'];
            $page = $this->properties['menu_slug'];
            add_settings_section($page . '_main', '', function() {
                echo $this->properties['section_heading'];
            }, $page);
            foreach ($options as $option) {
                $fieldName = $option['fieldName'];
                if (method_exists('Rma\Tools', 'validate_' . $fieldName)) {
                    register_setting($group, $fieldName, ['Rma\Tools', 'validate_' . $fieldName]);
                } else {
                    register_setting($group, $fieldName);
                }
                add_settings_field($fieldName, $option['label'], ['Rma\Fields', 'fieldHtml'], $page, $page . '_main', ['fieldName' => $fieldName]);
            }
        }
    
        public function render_settings_page() {
            
        }
    
    }
    
    Moderator bcworkz

    (@bcworkz)

    WP_Customize_Setting::validate() is intended for use when using setting fields in the customizer. As you are using the Settings API, a similar but different method of validation is used, which it appears you are already doing when you register your setting. The customizer validation doesn’t do anything special, it just sets up a filter system which theme devs hook into in order to validate their settings.

    By supplying a validation callback when your setting is registered, you are essentially doing the same thing — providing a path to get to your own validation function.

    That said, there is a lot to be said for moving some of your theme settings away from a settings page and into the customizer. Maybe you’ve already seen the customizer docs in the Theme Handbook since you mentioned WP_Customize_Setting, but just in case not, it’s here: https://developer.wordpress.org/themes/customize-api/

    Thread Starter geowb

    (@geowb)

    Thanks for your reply. Having read this I got the impression that WP_Customize_Settings::validate() was a step toward true full-form validation. The register_setting() callback argument appears to be intended to tidy up settings rather than perform validation. Also, the form I’m trying to validate is a plugin’s settings form.

    It appears that to validate a form by requiring all inputs to be valid before saving any values requires coding the form from scratch. So be it.

    Moderator bcworkz

    (@bcworkz)

    Coding from scratch is not necessary to cause everything to be validated, but you may decide that is the best approach anyway. I often do myself, but the register_setting() function ultimately ends up validating the entire form because all the fields are looped through and in each case the callback specified in register_setting() is called. Any callback can call add_settings_error() if something is amiss and the setting will not be updated and the error message will be displayed on the form.

    The customizer’s validate method is essentially the same thing for the customizer. In both cases you specify what callback should be used to validate each field and the setting update process loops though all the fields, calling the callback for each in turn. I don’t see the Trac ticket you linked to as any overall improvement in the situation. It’s more bringing the customizer functionality in line with the way the Settings API works. Mainly by allowing something like add_settings_error() to be used, as opposed to merely sanitizing and saving.

    I think the add_settings_error() function is the missing information that you are seeking. Without such functionality, the Settings API would indeed be limited.

    Thread Starter geowb

    (@geowb)

    I think you’re right about add_settings_error() as the missing link. I’d not seen that before; it’ll be much easier to add to existing code than starting over again. Thanks.

Viewing 5 replies - 1 through 5 (of 5 total)

The topic ‘Validate plugin setting’ is closed to new replies.