Crocoblock / suggestions

The suggestions for CrocoBlock project
195 stars 78 forks source link

Getting an options page field value right after it's set doesn't work #7774

Open aayla-secura opened 2 weeks ago

aayla-secura commented 2 weeks ago

Describe the bug When using combined options storage (i.e. store all page's options as an array under the page slug), if I set an option page's field using update_options and then straight after I try to get the option using the page's get method, it returns the old value.

To Reproduce Steps to reproduce the behavior:

$page = jet_engine()->options_pages->registered_pages['option-slug'];
$page->update_options([ 'some_field' => 'value' ]);
get_option('option-slug'); // this contains the updated value inside
$page->get('some_field'); // this returns old value or false if first time

The reason is that, when not using separate storage, Jet_Engine_Options_Page_Factory::get only refetches the options array with get_option if the options property is null:

493:            if ( null === $this->options ) {
494:                $this->options = get_option( $this->slug, array() );
495:            }

However Jet_Engine_Options_Page_Factory::update_options calls Jet_Engine_Options_Page_Factory::get_prepared_fields, which calls Jet_Engine_Options_Page_Factory::get before it sets the options, which results in the options property holding the old values, but then it never updates the options property.

Expected behavior Setting an option and then getting it should return the new value.

aayla-secura commented 2 weeks ago

Just to add, I have not tested how it behaves with separate storage, but looking at the code now seems like it's also not returning the updated value for the same reason: the options property is not updated/reloaded.

aayla-secura commented 2 days ago

Sigh... I don't want to post yet another issue on the same note (there's already #7797 that's similar). But also, getting related items via relation doesn't work in the same request after updating the relation, because the cached result isn't cleared. This kind of failure to clear cached results seems prevalent throughout and requires lots of tie digging through code and then using ugly workarounds like:

        add_action(
            'jet-engine/options-pages/updated',
            function ($page) {
                try {
                    $page->options = null;
                    // catch in case they make this property private
                    /* @phpstan-ignore-next-line catch.neverThrown */
                } catch (\Error $e) {
                }
            }
        );

        add_action(
            'jet-engine/relation/update/after',
            function ($parent_object, $child_object, $item_id, $relation) {
                try {
                    $relation->db->table_exists = true;
                    // catch in case they make this property private
                    /* @phpstan-ignore-next-line catch.neverThrown */
                } catch (\Error $e) {
                }

                try {
                    wp_cache_delete(
                        $relation->get_cache_key($parent_object, '0'),
                        'jet_engine_rel'
                    );
                    wp_cache_delete(
                        $relation->get_cache_key('0', $child_object),
                        'jet_engine_rel'
                    );
                    wp_cache_delete(
                        $relation->get_cache_key($child_object, $child_object),
                        'jet_engine_rel'
                    );
                    // catch in case they make this method private
                } catch (\Error $e) {
                }
            },
            10,
            4
        );

I really hope this gets look into.