rhubarbgroup / redis-cache

A persistent object cache backend for WordPress powered by Redis. Supports Predis, PhpRedis, Relay, replication, sentinels, clustering and WP-CLI.
https://wordpress.org/plugins/redis-cache/
GNU General Public License v3.0
427 stars 149 forks source link

Redis Conflicting with API Call #452

Closed bigboss97lnt closed 1 year ago

bigboss97lnt commented 1 year ago

Hello,

I would like to report an issue regarding Redis usage. While using Redis for the past few days, I have noticed that certain API calls return the same values despite different parameters being used. These API calls are intended to connect our mobile app with Woocommerce in order to display categories based on the selected language.

For instance, both of the following API calls return the same result, even though they use different language parameters:

The expected behavior would be to receive different results.

However, when Redis is enabled it gives the same result for both calls.

Could you please advise on how to exclude this call from being cached or avoid having Redis ignore the parameters used?

Thank you.

tillkruss commented 1 year ago

This will very likely need to be fixed by mobile builder, they probably don't account for it.

Tell them to test it during development with Redis Object Cache.

bigboss97lnt commented 1 year ago

Actually their support is very poor and I don't think they will help, I contacted them already but I'm trying to solve it my self, I just need little guidance through it.

This is the code that is responsible of the API call:

    /**
     * Get categories by parent
     *
     * @param $request
     *
     * @return array
     * @since 1.3.4
     * @author ngocdt
     */
    function categories( $request ) {
        $parent = $request->get_param( 'parent' );

        $result = wp_cache_get( 'category_' . $parent, 'rnlab' );

        if ( $result ) {
            return $result;
        }

        $result = $this->get_category_by_parent_id( $parent );
        wp_cache_set( 'category_' . $parent, $result, 'rnlab' );

        return $result;
    }

    function get_category_by_parent_id( $parent ) {
        $args = array(
            'hierarchical'     => 1,
            'show_option_none' => '',
            'hide_empty'       => 0,
            'parent'           => $parent,
            'taxonomy'         => 'product_cat',
        );

        $categories = get_categories( $args );

        if ( count( $categories ) ) {
            $with_subs = [];
            foreach ( $categories as $category ) {

                $image = null;

                // Get category image.
                $image_id = get_term_meta( $category->term_id, 'thumbnail_id', true );
                if ( $image_id ) {
                    $attachment = get_post( $image_id );

                    $image = array(
                        'id'   => (int) $image_id,
                        'src'  => wp_get_attachment_url( $image_id ),
                        'name' => get_the_title( $attachment ),
                        'alt'  => get_post_meta( $image_id, '_wp_attachment_image_alt', true ),
                    );
                }

                // Get Translated Category id / slug / name
                // $translated_category_id = apply_filters( 'wpml_object_id', $category->term_id, 'product_cat', true );
                $en_translation_category_id = apply_filters( 'wpml_object_id', $category->term_id, 'category', FALSE, 'en' );
                $en_translation_category = get_term( $en_translation_category_id, 'product_cat' );
                $ar_translation_category_id = apply_filters( 'wpml_object_id', $category->term_id, 'category', FALSE, 'ar' );
                $ar_translation_category = get_term( $ar_translation_category_id, 'product_cat' );

                $with_subs[] = array(
                    'id'         => (int) $category->term_id,
                    'name'       => $category->name,
                    'parent'     => $category->parent,
                    'slug'       => $category->slug,
                    'show_template' => get_term_meta( $category->term_id, 'wh_is_special', true ),
                    'hide_sub_categories' => get_term_meta( $category->term_id, 'wh_show_subs', true ),
                    'hide_category' => get_term_meta( $category->term_id, 'wh_hide_cat', true ),
                    'image'      => $image,
                    'count'      => (int) $category->count,
                    'entranslation' => array(
                        'id'   => $en_translation_category_id,
                        'name' => $en_translation_category->name,
                        'slug' => $en_translation_category->slug,
                    ),
                    'artranslation' => array(
                        'id'   => $ar_translation_category_id,
                        'name' => $ar_translation_category->name,
                        'slug' => $ar_translation_category->slug,
                    ),
                    'categories' => $this->get_category_by_parent_id( (int) $category->term_id )
                );
            }

            return $with_subs;

        } else {
            return [];
        }
    }

And this is the part for the language:

    public function settings( $request ) {

        $decode = $request->get_param( 'decode' );

        $result = wp_cache_get( 'settings_' . $decode, 'rnlab' );

        if ( $result ) {
            return $result;
        }

        try {
            global $woocommerce_wpml;

            $admin = new Mobile_Builder_Admin( MOBILE_BUILDER_PLUGIN_NAME, MOBILE_BUILDER_CONTROL_VERSION );

            $currencies = array();

            $languages    = apply_filters( 'wpml_active_languages', array(), 'orderby=id&order=desc' );
            $default_lang = apply_filters( 'wpml_default_language', substr( get_locale(), 0, 2 ) );

            error_log( 'Active languages: ' . print_r( $languages, true ) );
            error_log( 'Default language: ' . $default_lang );

            $currency = function_exists( 'get_woocommerce_currency' ) ? get_woocommerce_currency() : 'USD';

            if ( ! empty( $woocommerce_wpml->multi_currency ) && ! empty( $woocommerce_wpml->settings['currencies_order'] ) ) {
                $currencies = $woocommerce_wpml->multi_currency->get_currencies( 'include_default = true' );
            }

            $configs = get_option( 'mobile_builder_configs', array(
                "requireLogin"       => false,
                "toggleSidebar"      => false,
                "isBeforeNewProduct" => 5
            ) );

            $gmw = get_option( 'gmw_options' );

            $templates      = array();
            $templates_data = $admin->template_configs();

            if ( $decode ) {
                foreach ( $templates_data as $template ) {
                    $template->data     = json_decode( $template->data );
                    $template->settings = json_decode( $template->settings );
                    $templates[]        = $template;
                }
            }

            $result = array(
                'language'               => $default_lang,
                'languages'              => $languages,
                'currencies'             => $currencies,
                'currency'               => $currency,
                'enable_guest_checkout'  => get_option( 'woocommerce_enable_guest_checkout', true ),
                'timezone_string'        => get_option( 'timezone_string' ) ? get_option( 'timezone_string' ) : wc_timezone_string(),
                'date_format'            => get_option( 'date_format' ),
                'time_format'            => get_option( 'time_format' ),
                'configs'                => maybe_unserialize( $configs ),
                'default_location'       => $gmw ? $gmw['post_types_settings'] : $gmw,
                'templates'              => $decode ? $templates : $templates_data,
                'checkout_user_location' => apply_filters( 'wcfmmp_is_allow_checkout_user_location', true ),
            );

            wp_cache_set( 'settings_' . $decode, $result, 'rnlab' );

            wp_send_json( $result );
        } catch ( Exception $e ) {
            return new WP_Error(
                'error_setting',
                __( 'Some thing wrong.', "mobile-builder" ),
                array(
                    'status' => 403,
                )
            );
        }
    }
tillkruss commented 1 year ago

Sorry, I can't help you patch the plugin. If their support team is bad, I'd suggest not using "mobile-builder".

It looks like they are using their own cache group:

$result = wp_cache_get( 'settings_' . $decode, 'rnlab' );

You can ignore that cache group:

define('WP_REDIS_IGNORED_GROUPS', ['counts', 'plugins', 'themes', 'rnlab']);