Wikus
Wikus

Reputation: 65

Woocommerce Integration Settings API

I'm not really sure whether this needs to go in WooCommerce, Wordpress or PHP questions, I also don't really know what to call it as I have no idea what is going wrong, but hopefully one of you braniacs can help me here.

I'm doing a WooCommerce integration. Here is my code (stripped down for readability):

if ( ! class_exists( 'WC_My_Integration' ) ) :

    class WC_My_Integration extends WC_Integration {

    public function __construct() {

        global $woocommerce;

        $this->id = 'my_id';
        $this->method_title       = __( 'My Title', 'my-text-domain' );

        $this->test_select = $this->get_option('test_select');

        $this->init_form_fields();

        add_action( 'woocommerce_update_options_integration', array( &$this, 'process_admin_options' ) );
        // If I don't do this the changes aren't showing immediately
        $this->process_admin_options();
        var_dump($this->test_select);  // Returns correct result on save, but then disappears after page reload 
    }

    public function init_form_fields() {
        $this->form_fields = array(
            'test_select'   => array(
                'title'       => __( 'Test Select', 'my-text-domain' ),
                'type'        => 'select',
                'options'     => array(
                    'yes' => 'Yes',
                    'no'  => 'No'
                )
            ),
        );
    }

    public function test_function() {
        if('yes' === $this->test_select) {
            echo "Yes";
        } else {
            echo "No";
        }
    }

    public function process_admin_options() {    
        parent::process_admin_options();

        $this->test_select = get_option('test_select');
    }

    public function admin_options() {
        parent::admin_options();

    }
}
endif;

The problem is when I change the select option to yes / no, the change only reflects after I reload the page.

So, in other words, let's say the select option is set to "yes". I change it to "no", click the save button and the page reloads. The form shows that "no" is selected now, and the value of the var_dump() is "string 'no' (length=2)". The expected output of text_function() should now be "no". However, it still shows "yes".

Then, when I refresh the page the result of test_function() is correct and it echoes "no", but only after I refresh the page. Can anyone shed some light on this matter please?

I'm initializing the plugin correctly in my plugin file. Don't know if I need to include that as well?

Update:

I've updated the code above to reflect my changes after Magnavode's answer. Problem now is that the values are correct after save, but then disappear after page reload.

Upvotes: 0

Views: 3887

Answers (3)

mittah
mittah

Reputation: 41

My goal was to show/hide some settings depending on value of another. Since by default init_form_fields() is called before process_admin_options(), the show/hide wasn't work right after saving settings, but after settings page is reloded. I've achieved the goal by overriding process_admin_options():

public function process_admin_options() {

    $saved = parent::process_admin_options();
    $this->init_form_fields();
    return $saved;

}

and adding init_settings() call to init_form_fields():

public function init_form_fields() {

    $this->init_settings();
    $this->form_fields = [];

    if ( ! empty( $this->settings['one'] ) ) {
        // build a depending settings
    }

}

Upvotes: 1

Magnavode
Magnavode

Reputation: 53

The bug you're having is because at the time your contructor is called process_admin_options() hasn't been called yet and so the posted form has not been saved to the database yet. Causing get_option to retreive the old value.

You can fix it by setting the class variables again after processing the post data. Overwrite process_admin_options like so:

public function process_admin_options() {
    parent::process_admin_options();

    $this->test_select = $this->get_option('test_select');
}

Or by dropping the class variables altogether and just calling get_option each time instead.

Also you should overwrite init_form_fields() and init your form fields from there.

Also your admin_options() is hiding the parent's admin_options(). Use this instead:

public function admin_options() {
    parent::admin_options();

    var_dump($this->test_select);
    var_dump($this->get_option('test_select'));
}

I hope it helps.

Upvotes: 2

Wikus
Wikus

Reputation: 65

I'm sure this is not the way to do it, but I'm left with no choice until someone can shed some further light on this.

I ended up adding the following to the admin_options() function:

if($this->test_select !== $this->get_option('test_select')) {
    header("Refresh:0");
}

This forces the page to reload if the two (exact same!!!) variables don't match. Obviously it will need to check all the options, but that is the basic idea.

Upvotes: 0

Related Questions