0

So I can't seem to get the Settings API to save a field properly, I feel like I've followed ever single step, but I'm having no luck, so I wanted to reach out and see if someone might be able to spot anything that I might be doing wrong.

Whenever I input something in the field and I click on "Save Settings", it just refreshes and nothing get written to the database nor does it input anything into the field.

This is how the form looks on the backend:
enter image description here

This the output of the form:
enter image description here

This is the code:

class FH_Pardot_Settings
{
    private static string $option_group = 'pardot_settings';
    private static string $page = 'pardot';

    /**
     * Fields for Settings API
     *
     * @var array
     */
    private static array $fields = [
        'client_id' => '',
        'submit' => ''
    ];

    public function __construct()
    {
        if (is_admin()) {
            add_action('admin_init', [$this, 'admin_init']);
            add_action('admin_menu', [$this, 'admin_menu']);
        }
    }

    public function admin_menu()
    {
        $title = __('Pardot', 'pardot');
        add_options_page(
                $title,
                $title,
                'manage_options',
                self::$page,
                [$this, 'settings_page']
        );
    }

    /**
     * Register API Credentials Settings
     */
    public function admin_init(): void
    {
        self::$fields = [
            'client_id' => [__('Consumer Key', 'pardot'), ''],
            'submit' => '',
        ];
        register_setting(
                self::$option_group,
                self::$option_group,
        );
        add_settings_section(
                self::$option_group,
                __('Pardot Settings', 'pardot'),
                [$this, 'user_account_section'],
                self::$page
        );

        foreach (self::$fields as $name => $array) {
            $title = $array[0] ?? null;
            $class = $array[1] ?? null;
            add_settings_field(
                    $name,
                    $title,
                    [$this, "{$name}_field"],
                    self::$page,
                    self::$option_group,
                    $class
            );
        }
    }

    public function user_account_section(): void
    {
        $msg = __('Use the below section to input settings for the Pardot API', 'pardot');
        echo "<span id=\"instructions\">{$msg}</span>";
    }

    public function settings_page()
    {
        $html = <<<HTML
                <form action="options.php" method="post">
                HTML;
        echo $html;

        settings_fields(self::$option_group);
        do_settings_sections(self::$page);

        echo "</form>";
    }

    private function get_html_name($field_name)
    {
        return self::$option_group . "[{$field_name}]";
    }

    public function client_id_field()
    {
        $client_id = get_option('pardot_client_id');
        $html_name = $this->get_html_name('pardot_client_id');
        $msg = __('Input the consumer key', 'pardot');
        $html = <<<HTML
                <div id="client-id-wrap">
                    <input type="text" size="30" id="pardot_client_id" name="pardot_client_id" value="{$client_id}" />
                    <p>{$msg}</p>
                </div>
                HTML;
        echo $html;
    }

    public function submit_field()
    {
        $value = __('Save Settings', 'pardot');
        $html = <<<HTML
                <input type="submit" class="button-primary" name="save" value="{$value}" />
                HTML;
        echo $html;
    }
}

new FH_Pardot_Settings();
2
  • Noting that in the heredocs in submit_field, get_html_name, user_account_section and client_id_field there's no escaping which is a big security concern. Consider moving away from heredocs and using esc_attr, esc_html and wp_kses_post to escape the variables so that they're output safely
    – Tom J Nowell
    Jun 20, 2022 at 15:05
  • Thanks @TomJNowell, I don't usually do that, but thanks for explaining the reasoning behind that, I will go back and make udates.
    – Sem
    Jun 20, 2022 at 15:53

1 Answer 1

0

The <input> generated by your client_id_field() function is using the wrong name which is pardot_client_id, and by "wrong", I mean there's no database option registered with that name and the one you've registered is named pardot_settings.

  • The database option is the second parameter for register_setting().

  • And it should be used in the name attribute of form fields like <input> and <select>, e.g. <input name="DATABASE OPTION NAME">.

So looking at your class, you should have used <input type="text" size="30" id="pardot_client_id" name="{$html_name}" value="{$client_id}" /> there.

And then get the saved option like so:

// Get all settings in the option array.
$options = (array) get_option( self::$option_group );

// Get the pardot_client_id setting.
$client_id = $options['pardot_client_id'] ?? '';
1
  • 2
    Thanks so much @Sally, that worked perfectly! I can't believe I didn't catch that. The options are now saved and retrieved.
    – Sem
    Jun 20, 2022 at 14:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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