diff --git a/includes/dynamic-tags/class-dynamic-tags.php b/includes/dynamic-tags/class-dynamic-tags.php index 82b2c79e9..09a57f99c 100644 --- a/includes/dynamic-tags/class-dynamic-tags.php +++ b/includes/dynamic-tags/class-dynamic-tags.php @@ -499,15 +499,32 @@ public function register_rest_routes() { * @return WP_REST_Response */ public function get_dynamic_tag_replacements( $request ) { - $content = urldecode( $request->get_param( 'content' ) ); + $content = $request->get_param( 'content' ); $context = $request->get_param( 'context' ); - $fallback_id = $context['postId'] ?? 0; + $client_id = $request->get_param( 'clientId' ); + $post_id = $context['postId'] ?? 0; + $fallback_id = $post_id; $instance = new stdClass(); $replacements = []; // Set up an instance object with a context key. $instance->context = $context; + // Create a unique cache key. + $cache_key = sprintf( + 'replacements_%s_%s_%s', + md5( $content ), + $client_id, + $post_id + ); + + $replacements = wp_cache_get( $cache_key, 'generate_blocks_dynamic_tags' ); + + // Return the cache here if present. + if ( false !== $replacements ) { + return rest_ensure_response( $replacements ); + } + $all_tags = GenerateBlocks_Register_Dynamic_Tag::get_tags(); $tags_list = []; @@ -567,6 +584,16 @@ public function get_dynamic_tag_replacements( $request ) { } } + // Set the cache with filterable duration. + /** + * Set the duration of the cache for dynamic tag replacements. + * + * @since 2.0.0 + */ + $cache_duration = apply_filters( 'generateblocks_dynamic_tags_replacement_cache_duration', 3600, $content, $context, $request ); + + wp_cache_set( $cache_key, $replacements, 'generateblocks_dynamic_tags', $cache_duration ); + return rest_ensure_response( $replacements ); } diff --git a/src/dynamic-tags/components/DynamicTagBlockToolbar.jsx b/src/dynamic-tags/components/DynamicTagBlockToolbar.jsx index 16b510b7d..2ddea315a 100644 --- a/src/dynamic-tags/components/DynamicTagBlockToolbar.jsx +++ b/src/dynamic-tags/components/DynamicTagBlockToolbar.jsx @@ -74,11 +74,11 @@ export function DynamicTagBlockToolbar( { return contentValue.substring( selectionStart.offset, selectionEnd.offset ); }, [ selectionStart, selectionEnd, value ] ); - useEffect( () => { - if ( foundTags.length && ! isSelected ) { - setContentMode( 'preview' ); - } - }, [ foundTags.length, isSelected ] ); + // useEffect( () => { + // if ( foundTags.length && ! isSelected ) { + // setContentMode( 'preview' ); + // } + // }, [ foundTags.length, isSelected ] ); return ( diff --git a/src/dynamic-tags/utils.js b/src/dynamic-tags/utils.js index 1e5af18d5..f9df2c396 100644 --- a/src/dynamic-tags/utils.js +++ b/src/dynamic-tags/utils.js @@ -1,7 +1,7 @@ import apiFetch from '@wordpress/api-fetch'; import { applyFilters } from '@wordpress/hooks'; -export async function replaceTags( content, context = {} ) { +export async function replaceTags( { content, context = {}, clientId } ) { // Define an async function to fetch data try { const response = await apiFetch( { @@ -9,7 +9,8 @@ export async function replaceTags( content, context = {} ) { method: 'POST', data: { content, - context: applyFilters( 'generateblocks.editor.preview.context', context, { content } ), + context: applyFilters( 'generateblocks.editor.preview.context', context, { content, clientId } ), + clientId, }, } ); diff --git a/src/editor/style-html-attribute.js b/src/editor/style-html-attribute.js index 1c7df9fe1..36a798344 100644 --- a/src/editor/style-html-attribute.js +++ b/src/editor/style-html-attribute.js @@ -6,7 +6,6 @@ const cache = {}; function getCacheKey( clientId, context ) { const { 'generateblocks/loopIndex': loopIndex, - 'generateblocks/loopPreviewId': previewId, postId, } = context; @@ -16,9 +15,7 @@ function getCacheKey( clientId, context ) { key += `${ loopIndex }_`; } - if ( previewId ) { - key += `${ previewId }_`; - } else if ( postId ) { + if ( postId ) { key += `${ postId }_`; } @@ -47,11 +44,10 @@ addFilter( // Get the cached result if available. if ( cache[ clientId ][ style ] ) { - console.log( 'Using cached data', cache[ clientId ][ style ] ); return cache[ style ]; } - const replacements = await replaceTags( style, context ); + const replacements = await replaceTags( { content: style, context, clientId } ); if ( ! replacements.length ) { return style; @@ -59,7 +55,6 @@ addFilter( // Cache the result. cache[ clientId ][ style ] = replacements; - console.log( 'Cache miss, setting data', cache[ clientId ][ style ] ); const withReplacements = replacements.reduce( ( acc, { original, replacement, fallback } ) => { if ( ! replacement ) { diff --git a/src/hoc/withDynamicTag.js b/src/hoc/withDynamicTag.js index 7e39ad2fc..15a355867 100644 --- a/src/hoc/withDynamicTag.js +++ b/src/hoc/withDynamicTag.js @@ -1,4 +1,4 @@ -import { useState, useEffect } from '@wordpress/element'; +import { useState, useEffect, useMemo } from '@wordpress/element'; import { useSelect } from '@wordpress/data'; import { replaceTags } from '../dynamic-tags/utils'; @@ -7,7 +7,6 @@ const cache = {}; function getCacheKey( clientId, context ) { const { 'generateblocks/loopIndex': loopIndex, - 'generateblocks/loopPreviewId': previewId, postId, } = context; @@ -17,9 +16,7 @@ function getCacheKey( clientId, context ) { key += `${ loopIndex }_`; } - if ( previewId ) { - key += `${ previewId }_`; - } else if ( postId ) { + if ( postId ) { key += `${ postId }_`; } @@ -34,6 +31,7 @@ export function withDynamicTag( WrappedComponent ) { context, attributes, clientId, + isSelected, } = props; const { @@ -43,7 +41,7 @@ export function withDynamicTag( WrappedComponent ) { } = attributes; const [ dynamicTagValue, setDynamicTagValue ] = useState( '' ); - const [ contentMode, setContentMode ] = useState( 'edit' ); + const [ contentMode, setContentMode ] = useState( 'preview' ); const isSavingPost = useSelect( ( select ) => select( 'core/editor' ).isSavingPost() ); const blockCacheKey = getCacheKey( clientId, context ); @@ -51,7 +49,7 @@ export function withDynamicTag( WrappedComponent ) { cache[ blockCacheKey ] = {}; } - const getContentValue = () => { + const contentValue = useMemo( () => { if ( 'img' === tagName ) { return htmlAttributes?.src; } @@ -61,8 +59,7 @@ export function withDynamicTag( WrappedComponent ) { } return content?.text ?? content; - }; - const contentValue = getContentValue(); + }, [ tagName, htmlAttributes?.src, content ] ); useEffect( () => { if ( ! contentValue || ! contentValue.includes( '{{' ) ) { @@ -75,18 +72,13 @@ export function withDynamicTag( WrappedComponent ) { return; } - console.log( contentMode ); - if ( cache[ blockCacheKey ][ contentValue ] ) { - console.log( 'Using cached data', cache[ blockCacheKey ][ contentValue ] ); setDynamicTagValue( cache[ blockCacheKey ][ contentValue ] ); return; } async function fetchData() { - const response = await replaceTags( contentValue, context ); - - console.log( 'cache miss, setting cache', cache[ blockCacheKey ][ contentValue ] ); + const response = await replaceTags( { content: contentValue, context, clientId } ); setDynamicTagValue( response ); @@ -95,7 +87,15 @@ export function withDynamicTag( WrappedComponent ) { } fetchData(); - }, [ contentValue, contentMode, context, tagName, isSavingPost, blockCacheKey ] ); + }, [ + contentValue, + contentMode, + context, + tagName, + isSavingPost, + blockCacheKey, + isSelected, + ] ); return (