From cdf28d2aaa235fdf36cc8ef58d1b0adfdd9ea069 Mon Sep 17 00:00:00 2001 From: Vlad Date: Mon, 19 Feb 2024 18:20:56 -0500 Subject: [PATCH] Implement long-lived caching for View entries This reintroduces long-lived caching as documented in https://docs.gravitykit.com/article/58-about-gravityview-caching. If caching is enabled (either globally or for a specific View), we use the GV caching class to store entries. Otherwise, we cache entries for the duration of the request, unless disabled by a filter. --- future/includes/class-gv-view.php | 42 ++++++++++++++++--- tests/unit-tests/GravityView_Field_Test.php | 6 ++- tests/unit-tests/GravityView_Future_Test.php | 13 ++++++ tests/unit-tests/GravityView_Joins_Test.php | 2 + .../unit-tests/GravityView_Shortcode_Test.php | 4 ++ .../GravityView_Widget_Search_Test.php | 2 + 6 files changed, 62 insertions(+), 7 deletions(-) diff --git a/future/includes/class-gv-view.php b/future/includes/class-gv-view.php index 2c75ab0fd..0e28bfcc8 100644 --- a/future/includes/class-gv-view.php +++ b/future/includes/class-gv-view.php @@ -4,6 +4,7 @@ use GravityKit\GravityView\Foundation\Helpers\Arr; use GF_Query; +use GravityView_Cache; /** If this file is called directly, abort. */ if ( ! defined( 'GRAVITYVIEW_DIR' ) ) { @@ -1434,6 +1435,7 @@ function () use ( $query ) { /** * Queries database and conditionally caches results. + * First, checks if the long-lived cache is enabled and if the query is cached. If not, it checks if the short-lived cache is enabled and if the query is cached. * * @since 2.18.2 * @@ -1442,8 +1444,38 @@ function () use ( $query ) { * @return array{0: array, 1: GF_Query} Array of entries and the query object. The latter may be needed as it is modified during the query. */ private function run_db_query( GF_Query $query ) { + $db_entries = null; + + $query_hash = md5( serialize( $query->_introspect() ) ); + + $atts = $this->settings->all(); + + $atts['query_hash'] = $query_hash; + + $long_lived_cache = new GravityView_Cache( $this->form->ID, $atts ); + + if ( $long_lived_cache->use_cache() ) { + $cached_entries = $long_lived_cache->get(); + + if ( $cached_entries ) { + return [ + $cached_entries, + $query, + ]; + } + + $db_entries = $query->get(); + + if ( $long_lived_cache->set( $db_entries, 'entries' ) ) { + return [ + $db_entries, + $query, + ]; + } + } + /** - * Controls whether the query is cached. + * Controls whether the query is cached per request. This is a short-lived cache. * * @filter gk/gravityview/view/entries/cache * @@ -1454,16 +1486,14 @@ private function run_db_query( GF_Query $query ) { if ( ! apply_filters( 'gk/gravityview/view/entries/cache', true ) ) { $db_entries = $query->get(); - return array( + return [ $db_entries, $query, - ); + ]; } - $query_hash = md5( serialize( $query->_introspect() ) ); - if ( ! Arr::get( self::$cache, $query_hash ) ) { - $db_entries = $query->get(); + $db_entries = $db_entries ?? $query->get(); self::$cache[ $query_hash ] = array( $db_entries, diff --git a/tests/unit-tests/GravityView_Field_Test.php b/tests/unit-tests/GravityView_Field_Test.php index 40e053c4e..8856d6824 100644 --- a/tests/unit-tests/GravityView_Field_Test.php +++ b/tests/unit-tests/GravityView_Field_Test.php @@ -116,6 +116,7 @@ function test_GravityView_Field_Post_Image_explode_value() { */ function test_GravityView_Field_Other_Entries_get_entries() { add_filter( 'gk/gravityview/view/entries/cache', '__return_false' ); + add_filter( 'gravityview_use_cache', '__return_false' ); $form = $this->factory->form->import_and_get( 'complete.json' ); $post = $this->factory->view->create_and_get( array( @@ -224,6 +225,7 @@ function test_GravityView_Field_Other_Entries_get_entries() { $this->assertEquals( $valid_date_entry->ID, $entries[0]->ID ); remove_all_filters( 'gk/gravityview/view/entries/cache' ); + remove_all_filters( 'gravityview_use_cache' ); } function test_GravityView_Field_Sequence() { @@ -312,7 +314,8 @@ function test_GravityView_Field_Sequence() { } function test_GravityView_Field_Sequence_single() { - add_filter( 'gk/gravityview/view/entries/cache', $disable_cache_filter = '__return_false' ); + add_filter( 'gk/gravityview/view/entries/cache', '__return_false' ); + add_filter( 'gravityview_use_cache', '__return_false' ); $form = $this->factory->form->import_and_get( 'simple.json' ); $post = $this->factory->view->create_and_get( array( @@ -362,6 +365,7 @@ function test_GravityView_Field_Sequence_single() { $this->assertEquals( 1, $field->field->get_sequence( $context ) ); remove_all_filters( 'gk/gravityview/view/entries/cache' ); + remove_all_filters( 'gravityview_use_cache' ); } function test_GravityView_Field_Unsubscribe_render_permissions() { diff --git a/tests/unit-tests/GravityView_Future_Test.php b/tests/unit-tests/GravityView_Future_Test.php index 210888034..db7378dc3 100644 --- a/tests/unit-tests/GravityView_Future_Test.php +++ b/tests/unit-tests/GravityView_Future_Test.php @@ -1690,6 +1690,7 @@ public function test_filter_entries() { // Disable caching as we'll be running the same query but after creating new entries. add_filter( 'gk/gravityview/view/entries/cache', '__return_false' ); + add_filter( 'gravityview_use_cache', '__return_false' ); /** Some more */ foreach ( range( 1, 25 ) as $i ) { @@ -1731,6 +1732,7 @@ public function test_filter_entries() { remove_all_filters( 'gravityview/view/anchor_id' ); remove_all_filters( 'gravityview/widget/search/append_view_id_anchor' ); remove_all_filters( 'gk/gravityview/view/entries/cache' ); + remove_all_filters( 'gravityview_use_cache' ); } /** @@ -1807,6 +1809,7 @@ public function test_frontend_view_renderer_table() { add_filter( 'gravityview/view/anchor_id', '__return_false' ); add_filter( 'gravityview/widget/search/append_view_id_anchor', '__return_false' ); add_filter( 'gk/gravityview/view/entries/cache', '__return_false' ); + add_filter( 'gravityview_use_cache', '__return_false' ); gravityview()->request = new \GV\Mock_Request(); gravityview()->request->returns['is_view'] = $view; @@ -1985,6 +1988,7 @@ public function test_frontend_view_renderer_table() { remove_all_filters( 'gravityview/view/anchor_id' ); remove_all_filters( 'gravityview/widget/search/append_view_id_anchor' ); remove_all_filters( 'gk/gravityview/view/entries/cache' ); + remove_all_filters( 'gravityview_use_cache' ); } /** @@ -2166,6 +2170,7 @@ public function test_frontend_widgets() { $form = $this->factory->form->import_and_get( 'complete.json' ); add_filter( 'gk/gravityview/view/entries/cache', '__return_false' ); + add_filter( 'gravityview_use_cache', '__return_false' ); global $post; @@ -2244,6 +2249,7 @@ public function test_frontend_widgets() { remove_all_filters( 'gravityview/view/anchor_id' ); remove_all_filters( 'gravityview/widget/search/append_view_id_anchor' ); remove_all_filters( 'gk/gravityview/view/entries/cache' ); + remove_all_filters( 'gravityview_use_cache' ); } /** @@ -2955,6 +2961,7 @@ public function test_frontend_field_html_other_entries() { // Disable caching as we'll be running the same query but after creating new entries. add_filter( 'gk/gravityview/view/entries/cache', '__return_false' ); + add_filter( 'gravityview_use_cache', '__return_false' ); $entry_2 = $this->factory->entry->create_and_get( array( 'form_id' => $form['id'], @@ -2981,6 +2988,7 @@ public function test_frontend_field_html_other_entries() { unset( $GLOBALS['post'] ); remove_all_filters( 'gk/gravityview/view/entries/cache' ); + remove_all_filters( 'gravityview_use_cache' ); } /** @@ -5213,6 +5221,9 @@ public function test_mocks_legacy_context() { * @covers \GravityView_Shortcode::shortcode() */ public function test_shortcodes_gravityview() { + add_filter( 'gk/gravityview/view/entries/cache', '__return_false' ); + add_filter( 'gravityview_use_cache', '__return_false' ); + $form = $this->factory->form->import_and_get( 'complete.json' ); $post = $this->factory->view->create_and_get( array( @@ -5332,6 +5343,8 @@ public function test_shortcodes_gravityview() { remove_all_filters( 'gravityview/view/anchor_id' ); remove_all_filters( 'gravityview/widget/search/append_view_id_anchor' ); + remove_all_filters( 'gk/gravityview/view/entries/cache' ); + remove_all_filters( 'gravityview_use_cache' ); } /** diff --git a/tests/unit-tests/GravityView_Joins_Test.php b/tests/unit-tests/GravityView_Joins_Test.php index d60d4401b..9a33fb42b 100644 --- a/tests/unit-tests/GravityView_Joins_Test.php +++ b/tests/unit-tests/GravityView_Joins_Test.php @@ -287,6 +287,7 @@ public function test_basic_list_joins() { public function test_joins_with_approves() { add_filter('gk/gravityview/view/entries/cache', '__return_false'); + add_filter('gravityview_use_cache', '__return_false'); $this->_reset_context(); @@ -376,6 +377,7 @@ public function test_joins_with_approves() { $this->_reset_context(); remove_all_filters( 'gk/gravityview/view/entries/cache' ); + remove_all_filters( 'gravityview_use_cache' ); } public function test_legacy_template_table_joins() { diff --git a/tests/unit-tests/GravityView_Shortcode_Test.php b/tests/unit-tests/GravityView_Shortcode_Test.php index 7a091b874..016cd2bbf 100644 --- a/tests/unit-tests/GravityView_Shortcode_Test.php +++ b/tests/unit-tests/GravityView_Shortcode_Test.php @@ -52,6 +52,7 @@ function test_shortcode_get_view_detail_PAGING() { // Disable caching as we'll be running the same query but after creating new entries. add_filter( 'gk/gravityview/view/entries/cache', '__return_false' ); + add_filter( 'gravityview_use_cache', '__return_false' ); foreach ( range( 1, 50 ) as $i ) { $entry = $this->factory->entry->create_and_get( array( @@ -71,6 +72,7 @@ function test_shortcode_get_view_detail_PAGING() { $this->assertEquals( '10', $value ); remove_all_filters( 'gk/gravityview/view/entries/cache' ); + remove_all_filters( 'gravityview_use_cache' ); $view->settings->update( array( 'offset' => 20, @@ -131,6 +133,7 @@ function test_shortcode_get_view_detail_TOTAL_ENTRIES() { // Disable caching as we'll be running the same query but after creating new entries. add_filter( 'gk/gravityview/view/entries/cache', '__return_false' ); + add_filter( 'gravityview_use_cache', '__return_false' ); foreach ( range( 1, 1050 ) as $i ) { $entry = $this->factory->entry->create_and_get( array( @@ -151,6 +154,7 @@ function test_shortcode_get_view_detail_TOTAL_ENTRIES() { gravityview()->request = new \GV\Frontend_Request(); remove_all_filters( 'gk/gravityview/view/entries/cache' ); + remove_all_filters( 'gravityview_use_cache' ); } /** diff --git a/tests/unit-tests/GravityView_Widget_Search_Test.php b/tests/unit-tests/GravityView_Widget_Search_Test.php index a0b8afaa1..841a04f53 100644 --- a/tests/unit-tests/GravityView_Widget_Search_Test.php +++ b/tests/unit-tests/GravityView_Widget_Search_Test.php @@ -957,6 +957,7 @@ public function test_created_by_text_search() { $this->assertEquals( 0, $view->get_entries()->count() ); add_filter( 'gk/gravityview/view/entries/cache', '__return_false' ); + add_filter( 'gravityview_use_cache', '__return_false' ); update_user_meta( $gamma, 'custom_meta', 'custom' ); add_filter( 'gravityview/widgets/search/created_by/user_meta_fields', function() { @@ -966,6 +967,7 @@ public function test_created_by_text_search() { remove_all_filters( 'gravityview/widgets/search/created_by/user_meta_fields' ); remove_all_filters( 'gk/gravityview/view/entries/cache' ); + remove_all_filters( 'gravityview_use_cache' ); $_GET = array(); }