Skip to content

Commit c1383d1

Browse files
authored
Merge pull request #453 from cloudinary/fix/cache-srcset
clear cache and manage srcset
2 parents eda536b + 870e52a commit c1383d1

File tree

4 files changed

+152
-99
lines changed

4 files changed

+152
-99
lines changed

php/class-delivery.php

Lines changed: 76 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99

1010
use Cloudinary\Component\Setup;
1111
use Cloudinary\Media\Filter;
12+
use Cloudinary\Media\Global_Transformations;
1213
use Cloudinary\String_Replace;
1314
use Cloudinary\UI\Component\HTML;
15+
use WP_Post;
1416

1517
/**
1618
* Plugin Delivery class.
@@ -62,29 +64,36 @@ public function __construct( Plugin $plugin ) {
6264
*/
6365
protected function setup_hooks() {
6466
add_filter( 'cloudinary_filter_out_local', '__return_false' );
67+
add_action( 'update_option_cloudinary_media_display', array( $this, 'clear_cache' ) );
68+
}
69+
70+
/**
71+
* Clear cached meta.
72+
*/
73+
public function clear_cache() {
74+
delete_post_meta_by_key( self::META_CACHE_KEY );
6575
}
6676

6777
/**
6878
* Setup component.
6979
*/
7080
public function setup() {
71-
add_filter( 'wp_calculate_image_srcset', array( $this->media, 'image_srcset' ), 10, 5 );
7281
$this->filter = $this->media->filter;
7382
// Add filters.
7483
add_filter( 'the_content', array( $this, 'filter_local' ) );
75-
// @todo: Add filter for `cloudinary_string_replace` with method `convert_urls` To catch non ID's tags.
7684
add_action( 'save_post', array( $this, 'remove_replace_cache' ), 10, 2 );
85+
add_action( 'cloudinary_string_replace', array( $this, 'catch_urls' ) );
86+
add_filter( 'post_thumbnail_html', array( $this, 'rebuild_tag' ), 100, 5 );
7787
}
7888

7989
/**
8090
* Delete the content replacement cache data.
8191
*
82-
* @param int $post_id The post ID to remove cache from.
83-
* @param string $content The post content.
92+
* @param int $post_id The post ID to remove cache from.
93+
* @param WP_Post $post The post object.
8494
*/
85-
public function remove_replace_cache( $post_id, $content ) {
95+
public function remove_replace_cache( $post_id, $post ) {
8696
delete_post_meta( $post_id, self::META_CACHE_KEY );
87-
$this->convert_tags( $post_id, $content );
8897
}
8998

9099
/**
@@ -95,7 +104,7 @@ public function remove_replace_cache( $post_id, $content ) {
95104
* @return string
96105
*/
97106
public function filter_local( $content ) {
98-
$post_id = get_queried_object_id();
107+
$post_id = get_the_ID();
99108
if ( ! empty( $post_id ) ) {
100109
$replacements = get_post_meta( $post_id, self::META_CACHE_KEY, true );
101110
if ( empty( $replacements ) ) {
@@ -109,43 +118,6 @@ public function filter_local( $content ) {
109118
return $content;
110119
}
111120

112-
/**
113-
* Get the attachment ID from the media tag.
114-
*
115-
* @param string $html The HTML.
116-
*
117-
* @return int[]
118-
*/
119-
public function get_id_from_tags( $html ) {
120-
$attachment_ids = array();
121-
// Get attachment id from class name.
122-
if ( preg_match_all( '#class=["|\']?[^"\']*(wp-image-|wp-video-)([\d]+)[^"\']*["|\']?#i', $html, $found ) ) {
123-
$attachment_ids = array_map( 'intval', $found[2] );
124-
}
125-
126-
return $attachment_ids;
127-
}
128-
129-
/**
130-
* Get known urls from image tags that have a wp-image-id.
131-
*
132-
* @param string $content The HTML content to get known urls from.
133-
*
134-
* @return array
135-
*/
136-
public function get_known_urls( $content ) {
137-
$ids = $this->get_id_from_tags( $content );
138-
$urls = array();
139-
foreach ( $ids as $id ) {
140-
if ( ! $this->media->cloudinary_id( $id ) ) {
141-
continue;
142-
}
143-
$urls = array_merge( $urls, $this->get_attachment_size_urls( $id ) );
144-
}
145-
146-
return $urls;
147-
}
148-
149121
/**
150122
* Get all sizes URLS for an attachment.
151123
*
@@ -224,66 +196,85 @@ public function find_attachment_size_urls( $urls ) {
224196
*
225197
* @param int $post_id The post ID.
226198
* @param string $content The HTML to find tags and prep replacement in.
199+
*
200+
* @return array
227201
*/
228202
public function convert_tags( $post_id, $content ) {
229-
230-
$tags = $this->filter->get_media_tags( $content );
231-
$replacements = array();
203+
$tags = $this->filter->get_media_tags( $content );
204+
$replacements = array();
205+
$attachment_ids = array();
232206
foreach ( $tags as $element ) {
233207
$attachment_id = $this->filter->get_id_from_tag( $element );
234208
if ( empty( $attachment_id ) ) {
235209
continue;
236210
}
211+
// Register replacement.
212+
$replacements[ $element ] = $this->rebuild_tag( $element, null, $attachment_id );
213+
$attachment_ids[] = $attachment_id;
214+
}
237215

238-
// Get the tag type.
239-
$tag = strstr( trim( $element, '<' ), ' ', true );
240-
241-
// Break element up.
242-
$atts = shortcode_parse_atts( $element );
243-
244-
// Remove the old srcset if it has one.
245-
if ( isset( $atts['srcset'] ) ) {
246-
unset( $atts['srcset'] );
216+
// Create other image sizes for ID's found.
217+
foreach ( $attachment_ids as $attachment_id ) {
218+
$urls = $this->get_attachment_size_urls( $attachment_id );
219+
foreach ( $urls as $local => $remote ) {
220+
$replacements[ $local ] = $remote;
247221
}
222+
}
223+
// Update the post meta cache.
224+
update_post_meta( $post_id, self::META_CACHE_KEY, $replacements );
248225

249-
// Remove head and tail.
250-
array_shift( $atts );
251-
array_pop( $atts );
252-
253-
// Get overwrite flag.
254-
$overwrite = (bool) strpos( $atts['class'], 'cld-overwrite' );
226+
return $replacements;
227+
}
255228

256-
// Get size.
257-
$size = $this->get_size_from_atts( $atts['class'] );
229+
/**
230+
* Rebuild a tag with cloudinary urls.
231+
*
232+
* @param string $element The original HTML tag.
233+
* @param null|int $post_id The optional associated post ID.
234+
* @param null|int $attachment_id The attachment ID.
235+
*
236+
* @return string
237+
*/
238+
public function rebuild_tag( $element, $post_id, $attachment_id ) {
239+
// Add our filter if not already added.
240+
if ( ! has_filter( 'wp_calculate_image_srcset', array( $this->media, 'image_srcset' ) ) ) {
241+
add_filter( 'wp_calculate_image_srcset', array( $this->media, 'image_srcset' ), 10, 5 );
242+
}
243+
$element = trim( $element, '</>' );
258244

259-
// Get transformations if present.
260-
$transformations = $this->get_transformations_maybe( $atts['src'] );
245+
// Break element up.
246+
$atts = shortcode_parse_atts( $element );
261247

262-
// Create new src url.
263-
$atts['src'] = $this->media->cloudinary_url( $attachment_id, $size, $transformations, null, $overwrite );
248+
// Remove tag.
249+
$tag = array_shift( $atts );
264250

265-
// Setup new tag.
266-
$new_tag = array(
267-
$tag,
268-
HTML::build_attributes( $atts ),
269-
);
251+
// Remove the old srcset if it has one.
252+
if ( isset( $atts['srcset'] ) ) {
253+
unset( $atts['srcset'] );
254+
}
270255

271-
$replace = HTML::compile_tag( $new_tag );
256+
// Get overwrite flag.
257+
$overwrite = false;
258+
if ( is_null( $post_id ) && isset( $atts['class'] ) ) {
259+
$overwrite = (bool) strpos( $atts['class'], 'cld-overwrite' );
260+
} elseif ( $post_id ) {
261+
$overwrite = (bool) $this->media->get_post_meta( $post_id, Global_Transformations::META_FEATURED_IMAGE_KEY, true );
262+
}
272263

273-
// Add new srcset.
274-
$replace = $this->media->apply_srcset( $replace, $attachment_id, $overwrite );
264+
// Get size.
265+
$size = $this->get_size_from_atts( $atts );
275266

276-
// Register replacement.
277-
$replacements[ $element ] = $replace;
278-
}
267+
// Get transformations if present.
268+
$transformations = $this->get_transformations_maybe( $atts['src'] );
279269

280-
// Update the post meta cache.
281-
update_post_meta( $post_id, self::META_CACHE_KEY, $replacements );
270+
// Create new src url.
271+
$atts['src'] = $this->media->cloudinary_url( $attachment_id, $size, $transformations, null, $overwrite );
282272

283-
// Catch others.
284-
$this->catch_urls( $content );
273+
// Setup new tag.
274+
$replace = HTML::build_tag( $tag, $atts );
285275

286-
return $replacements;
276+
// Add new srcset.
277+
return $this->media->apply_srcset( $replace, $attachment_id, $overwrite );
287278
}
288279

289280
/**
@@ -346,7 +337,7 @@ function ( $url ) use ( $dirs ) {
346337
$urls
347338
);
348339

349-
$urls = array_filter( $urls );
340+
$urls = array_filter( array_filter( $urls ), array( 'Cloudinary\String_Replace', 'string_not_set' ) );
350341
$unknown = array_diff( $urls, array_keys( $known ) );
351342
if ( ! empty( $unknown ) ) {
352343
$known = array_merge( $known, $this->find_attachment_size_urls( $unknown ) );

php/class-string-replace.php

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,64 @@ class String_Replace {
3434
public function __construct( Plugin $plugin ) {
3535
$this->plugin = $plugin;
3636
add_action( 'template_redirect', array( $this, 'init' ), 1 );
37+
add_action( 'template_include', array( $this, 'init_debug' ), 1 );
38+
$types = get_post_types_by_support( 'editor' );
39+
foreach ( $types as $type ) {
40+
$post_type = get_post_type_object( $type );
41+
// Check if this is a rest supported type.
42+
if ( true === $post_type->show_in_rest ) {
43+
// Add filter only to rest supported types.
44+
add_filter( 'rest_prepare_' . $type, array( $this, 'pre_filter_rest_content' ), 10, 3 );
45+
}
46+
}
47+
}
48+
49+
/**
50+
* Filter out local urls in an 'edit' context rest request ( i.e for Gutenburg ).
51+
*
52+
* @param \WP_REST_Response $response The post data array to save.
53+
* @param \WP_Post $post The current post.
54+
* @param \WP_REST_Request $request The request object.
55+
*
56+
* @return \WP_REST_Response
57+
*/
58+
public function pre_filter_rest_content( $response, $post, $request ) {
59+
$context = $request->get_param( 'context' );
60+
if ( 'view' === $context ) {
61+
$data = $response->get_data();
62+
$data['content']['rendered'] = $this->replace_strings( $data['content']['rendered'] );
63+
$response->set_data( $data );
64+
}
65+
66+
return $response;
3767
}
3868

3969
/**
4070
* Init the buffer capture and set the output callback.
4171
*/
4272
public function init() {
43-
ob_start( array( $this, 'replace_strings' ) );
73+
if ( ! defined( 'WP_DEBUG' ) || false === WP_DEBUG ) {
74+
ob_start( array( $this, 'replace_strings' ) );
75+
}
76+
}
77+
78+
/**
79+
* Init the buffer capture in debug mode.
80+
*
81+
* @param string $template The template being loaded.
82+
*
83+
* @return null|string
84+
*/
85+
public function init_debug( $template ) {
86+
if ( defined( 'WP_DEBUG' ) && true === WP_DEBUG ) {
87+
ob_start();
88+
include $template;
89+
$html = ob_get_clean();
90+
echo $this->replace_strings( $html ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
91+
$template = null;
92+
}
93+
94+
return $template;
4495
}
4596

4697
/**
@@ -50,10 +101,21 @@ public function init() {
50101
*
51102
* @return bool
52103
*/
53-
public function string_set( $string ) {
104+
public static function string_set( $string ) {
54105
return isset( self::$replacements[ $string ] );
55106
}
56107

108+
/**
109+
* Check if a string is not set for replacement.
110+
*
111+
* @param string $string String to check.
112+
*
113+
* @return bool
114+
*/
115+
public static function string_not_set( $string ) {
116+
return ! self::string_set( $string );
117+
}
118+
57119
/**
58120
* Replace a string.
59121
*

php/connect/class-api.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -256,16 +256,13 @@ public function cloudinary_url( $public_id = null, $args = array(), $size = arra
256256
'https:/',
257257
$this->url( $args['resource_type'], $asset_endpoint ),
258258
);
259-
260-
if ( ! empty( $args['transformation'] ) ) {
261-
$url_parts[] = self::generate_transformation_string( $args['transformation'], $args['resource_type'] );
262-
}
263-
$base = pathinfo( $public_id );
259+
$base = pathinfo( $public_id );
264260
// Only do dynamic naming and sizes if upload type.
265261
if ( 'image' === $args['resource_type'] && 'upload' === $args['delivery_type'] ) {
266262
$new_path = $base['filename'] . '/' . $base['basename'];
267263
$public_id = str_replace( $base['basename'], $new_path, $public_id );
268264
}
265+
269266
// Add size.
270267
if ( ! empty( $size ) && is_array( $size ) ) {
271268
$url_parts[] = self::generate_transformation_string( array( $size ), $args['resource_type'] );
@@ -274,6 +271,9 @@ public function cloudinary_url( $public_id = null, $args = array(), $size = arra
274271
$public_id = str_replace( $base['basename'], $size['file'], $public_id );
275272
}
276273
}
274+
if ( ! empty( $args['transformation'] ) ) {
275+
$url_parts[] = self::generate_transformation_string( $args['transformation'], $args['resource_type'] );
276+
}
277277

278278
$url_parts[] = $args['version'];
279279
$url_parts[] = $public_id;

0 commit comments

Comments
 (0)