PluginProbe
aBlocks – Gutenberg Blocks, User Dashboard Builder, Popup Builder, Form Builder & Animation Builder / 2.13.1
aBlocks – Gutenberg Blocks, User Dashboard Builder, Popup Builder, Form Builder & Animation Builder v2.13.1
2.13.0 2.13.1 2.12.0 2.11.1 2.11.0 2.10.0 2.9.0 2.7.4 2.7.5 2.7.6 2.7.7 2.8.0 2.8.1 2.9.1 trunk 1.0 1.0-beta1 1.0-beta2 1.0-beta3 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.1.2 All 80 releases
← All changes | includes/helper.php +463 -16 2.9.12.13.1 View file →
@@ -4,10 +4,8 @@
4 4 if ( ! defined( 'ABSPATH' ) ) {
5 5 exit; // Exit if accessed directly.
6 6 }
7 7
8 -use ABlocks\Classes\FileUpload;
9 -use ABlocks\Classes\BlockGlobal;
10 8 use ABlocks\traits\Importer;
11 9
12 10 class Helper {
13 11
@@ -12,8 +10,11 @@
12 10 class Helper {
13 11
14 12 use Importer;
15 13
14 + /** Memoized responsive device list (see get_responsive_devices). */
15 + private static $responsive_devices_cache = null;
16 +
16 17 public static function get_time() {
17 18 return time() + ( get_option( 'gmt_offset' ) * HOUR_IN_SECONDS );
18 19 }
19 20
@@ -26,8 +27,253 @@
26 27
27 28 return $default;
28 29 }
29 30
31 + /**
32 + * Responsive breakpoint widths (px) for the whole plugin. User-configurable
33 + * via Settings; defaults preserve the historical 800/480 values. Every CSS
34 + * generator and the block editor reads these so breakpoints stay in sync.
35 + */
36 + /**
37 + * Make one CSS property or declaration value safe to write into a stylesheet.
38 + *
39 + * Block attributes reach the compiled CSS verbatim and that CSS is echoed
40 + * inside a `<style>` element, so a value carrying `</style>` closes the
41 + * element and everything after it is parsed as HTML — a stored XSS
42 + * available to anyone who can set a block attribute, which includes a
43 + * Contributor editing their own draft. `{` and `}` are the same problem one
44 + * level down: they close the rule and let the value choose its own
45 + * selector.
46 + *
47 + * Only those four characters are removed. A declaration value never needs
48 + * them, and everything a real one does need survives: data URIs (which
49 + * carry `;`), gradients, `calc()` and `var()` (parentheses and commas),
50 + * font stacks (quotes), `content` escapes (backslashes), and shorthand
51 + * slashes such as `font: 12px/1.5`.
52 + *
53 + * `;` is deliberately kept. With the braces gone, an injected `;` can only
54 + * add declarations to the same rule — which targets the block's own
55 + * element, exactly what its style controls already allow — so removing it
56 + * would break data URIs to buy nothing.
57 + *
58 + * @param mixed $value A CSS property name or declaration value.
59 + * @return string The value with the escape characters removed.
60 + */
61 + public static function esc_css_value( $value ) {
62 + if ( ! is_scalar( $value ) ) {
63 + return '';
64 + }
65 + return str_replace( [ '<', '>', '{', '}' ], '', (string) $value );
66 + }
67 +
68 + public static function get_breakpoints() {
69 + $tablet = (int) self::get_settings( 'breakpoint_tablet', 800 );
70 + $mobile = (int) self::get_settings( 'breakpoint_mobile', 480 );
71 +
72 + // Guard against nonsensical config (mobile must be below tablet).
73 + if ( $tablet < 1 ) {
74 + $tablet = 800;
75 + }
76 + if ( $mobile < 1 || $mobile >= $tablet ) {
77 + $mobile = min( 480, $tablet - 1 );
78 + }
79 +
80 + return array(
81 + 'tablet' => $tablet,
82 + 'mobile' => $mobile,
83 + );
84 + }
85 +
86 + /**
87 + * The full ordered list of responsive devices the atomic style system emits
88 + * for: the base (Desktop, width 0 = no media query), the two built-in
89 + * breakpoints, then any user-registered custom breakpoints. Each entry:
90 + * id - stable identifier (also the WP device name for the built-ins)
91 + * label - shown in the editor device switcher
92 + * suffix - appended to responsive attribute keys (e.g. fontSize + suffix)
93 + * width - max-width px for the @media rule (0 = base, no media query)
94 + *
95 + * Ordering is load-bearing, not cosmetic: the base comes first and every
96 + * other device follows widest-first, so narrower breakpoints emit later and
97 + * win in `cascade` mode. Precedence therefore follows the breakpoint's own
98 + * bounds rather than the order a custom breakpoint happened to be
99 + * registered in.
100 + */
101 + public static function get_responsive_devices() {
102 + if ( null !== self::$responsive_devices_cache ) {
103 + return self::$responsive_devices_cache;
104 + }
105 +
106 + $bp = self::get_breakpoints();
107 + // Built-ins are max-width only (min 0). `width` is the sort key
108 + // (max-width, or a large value for min-only so it sorts widest).
109 + $devices = array(
110 + array( 'id' => 'Desktop', 'label' => 'Desktop', 'suffix' => '', 'width' => 0, 'min' => 0, 'max' => 0 ),
111 + array( 'id' => 'Tablet', 'label' => 'Tablet', 'suffix' => 'Tablet', 'width' => $bp['tablet'], 'min' => 0, 'max' => $bp['tablet'] ),
112 + array( 'id' => 'Mobile', 'label' => 'Mobile', 'suffix' => 'Mobile', 'width' => $bp['mobile'], 'min' => 0, 'max' => $bp['mobile'] ),
113 + );
114 +
115 + $custom = self::get_settings( 'breakpoint_custom', array() );
116 + if ( is_array( $custom ) ) {
117 + foreach ( $custom as $c ) {
118 + $c = (array) $c;
119 + // Advanced breakpoints support a min and/or max width. `width` is
120 + // kept as a legacy alias for max-width.
121 + $max = isset( $c['maxWidth'] ) ? (int) $c['maxWidth'] : ( isset( $c['width'] ) ? (int) $c['width'] : 0 );
122 + $min = isset( $c['minWidth'] ) ? (int) $c['minWidth'] : 0;
123 + if ( $max < 1 && $min < 1 ) {
124 + continue; // needs at least one bound
125 + }
126 + // Stable, alphanumeric suffix so stored values survive label edits.
127 + $key = ! empty( $c['key'] ) ? preg_replace( '/[^a-zA-Z0-9]/', '', $c['key'] ) : (string) ( $max ? $max : $min );
128 + $suffix = 'Bp' . ucfirst( $key );
129 + $label = ! empty( $c['label'] ) ? $c['label'] : self::breakpoint_auto_label( $min, $max );
130 + $devices[] = array(
131 + 'id' => $suffix,
132 + 'label' => $label,
133 + 'suffix' => $suffix,
134 + 'width' => $max > 0 ? $max : 999999, // sort key (min-only = widest)
135 + 'min' => $min,
136 + 'max' => $max,
137 + );
138 + }
139 + }
140 +
141 + self::$responsive_devices_cache = self::sort_responsive_devices( $devices );
142 + return self::$responsive_devices_cache;
143 + }
144 +
145 + /**
146 + * Base first, then widest-first. Ties break on id so the order is stable
147 + * regardless of the PHP version's sort stability.
148 + */
149 + private static function sort_responsive_devices( $devices ) {
150 + $base = array();
151 + $rest = array();
152 + foreach ( $devices as $d ) {
153 + if ( empty( $d['min'] ) && empty( $d['max'] ) ) {
154 + $base[] = $d;
155 + } else {
156 + $rest[] = $d;
157 + }
158 + }
159 +
160 + usort(
161 + $rest,
162 + function ( $a, $b ) {
163 + $cmp = (int) $b['width'] - (int) $a['width'];
164 + return 0 !== $cmp ? $cmp : strcmp( (string) $a['id'], (string) $b['id'] );
165 + }
166 + );
167 +
168 + return array_merge( $base, $rest );
169 + }
170 +
171 + /** Drop the memoized device list (settings changed mid-request). */
172 + public static function flush_responsive_devices_cache() {
173 + self::$responsive_devices_cache = null;
174 + }
175 +
176 + /** A readable fallback label for a min/max breakpoint. */
177 + public static function breakpoint_auto_label( $min, $max ) {
178 + if ( $min > 0 && $max > 0 ) {
179 + return $min . '–' . $max . 'px';
180 + }
181 + if ( $max > 0 ) {
182 + return '≤ ' . $max . 'px';
183 + }
184 + return '≥ ' . $min . 'px';
185 + }
186 +
187 + /** Compose a CSS media condition (no `@media` keyword) from min/max px. */
188 + public static function breakpoint_media_condition( $min, $max ) {
189 + $parts = array();
190 + if ( $min > 0 ) {
191 + $parts[] = '(min-width:' . (int) $min . 'px)';
192 + }
193 + if ( $max > 0 ) {
194 + $parts[] = '(max-width:' . (int) $max . 'px)';
195 + }
196 + return implode( ' and ', $parts );
197 + }
198 +
199 + /**
200 + * How breakpoint queries relate to each other, site-wide.
201 + *
202 + * cascade (default) - max-width envelopes. A Tablet value still applies at
203 + * Mobile widths unless Mobile overrides it. This is how
204 + * aBlocks v1/v2 blocks behave, so a page mixing block
205 + * versions stays consistent.
206 + * strict - exclusive bands. A Tablet value applies only between
207 + * the Mobile bound and the Tablet bound, matching
208 + * WordPress core and block themes.
209 + */
210 + public static function get_breakpoint_mode() {
211 + return 'strict' === self::get_settings( 'breakpoint_mode', 'cascade' ) ? 'strict' : 'cascade';
212 + }
213 +
214 + /**
215 + * The single place an atomic media query is built. Returns the complete
216 + * `@media …` prelude for a device entry, or '' for the base device (which
217 + * needs no query at all).
218 + *
219 + * Both bounds are honoured, so a custom breakpoint declared with only a
220 + * `minWidth` produces a real min-width query instead of being skipped —
221 + * animations already behaved this way, style rules did not.
222 + */
223 + public static function breakpoint_media_query( $device ) {
224 + $device = (array) $device;
225 + $min = isset( $device['min'] ) ? (int) $device['min'] : 0;
226 + $max = isset( $device['max'] ) ? (int) $device['max'] : 0;
227 +
228 + if ( $min < 1 && $max < 1 ) {
229 + return '';
230 + }
231 +
232 + /*
233 + * Strict mode bounds a max-width breakpoint from below with the next
234 + * narrower breakpoint, turning overlapping envelopes into exclusive
235 + * bands. A breakpoint that already declares its own min is left alone —
236 + * the author has stated the band explicitly.
237 + */
238 + if ( 'strict' === self::get_breakpoint_mode() && $max > 0 && $min < 1 ) {
239 + $narrower = self::next_narrower_max( $max );
240 + if ( $narrower > 0 ) {
241 + $min = $narrower + 1;
242 + }
243 + }
244 +
245 + $condition = self::breakpoint_media_condition( $min, $max );
246 + return '' === $condition ? '' : '@media screen and ' . $condition;
247 + }
248 +
249 + /** The largest max-width bound narrower than $max, or 0 if none. */
250 + private static function next_narrower_max( $max ) {
251 + $best = 0;
252 + foreach ( self::get_responsive_devices() as $d ) {
253 + $dmax = isset( $d['max'] ) ? (int) $d['max'] : 0;
254 + if ( $dmax > 0 && $dmax < $max && $dmax > $best ) {
255 + $best = $dmax;
256 + }
257 + }
258 + return $best;
259 + }
260 +
261 + public static function get_page_permalink( $page, $fallback = null ) {
262 + $page_id = self::get_settings( $page );
263 + $permalink = 0 < $page_id ? get_permalink( $page_id ) : '';
264 + if ( ! $permalink ) {
265 + $permalink = is_null( $fallback ) ? get_home_url() : $fallback;
266 + }
267 +
268 + return apply_filters( 'ablocks/get_' . $page . '_permalink', $permalink );
269 + }
270 +
271 + public static function get_logout_url( $redirect = '' ) {
272 + $redirect = $redirect ? $redirect : apply_filters( 'ablocks/logout_default_redirect_url', self::get_page_permalink( 'dashboard_page' ) );
273 +
274 + return wp_logout_url( $redirect );
275 + }
30 276 public static function is_enabled_block( $block_name, $parent_block_name = '' ) {
31 277 global $ablocks_blocks;
32 278 $block_name = ! empty( $parent_block_name ) ? $parent_block_name : $block_name;
33 279 if ( isset( $ablocks_blocks->{$block_name} ) ) {
@@ -60,14 +306,31 @@
60 306 public static function is_active_wp_map_block() {
61 307 $wp_map_block = 'wp-map-block/wp-map-block.php';
62 308 return self::is_plugin_active( $wp_map_block );
63 309 }
310 + public static function is_active_quizpress() {
311 + return class_exists( 'QuizPress' );
312 + }
313 + public static function is_active_zencommunity() {
314 + $zencommunity = 'zencommunity/zencommunity.php';
315 + return self::is_plugin_active( $zencommunity );
316 + }
317 + public static function is_active_gemboards() {
318 + $gemboards = 'gemboards/gemboards.php';
319 + return self::is_plugin_active( $gemboards );
320 + }
321 + public static function is_active_easy_content_manager() {
322 + return class_exists( 'EasyContentManager' );
323 + }
64 324
65 325 public static function is_enabled_assets_generation() {
66 - $flag = false;
67 - if ( (bool) self::get_settings( 'enabled_assets_file_generation' ) ) {
68 - $flag = function_exists( 'wp_is_block_theme' ) ? ! wp_is_block_theme() : true;
69 - }
326 + // Default OFF — combining/generating per-page asset files churns while a
327 + // site is still being built, so it's recommended (via the Performance tab
328 + // notice) once the site is complete rather than forced on. When enabled it
329 + // merges every block's CSS/JS into one per-page file, inlined when small
330 + // (see Assets::enqueue_frontend_assets), removing the per-block
331 + // render-blocking stylesheets.
332 + $flag = (bool) self::get_settings( 'enabled_assets_file_generation', false );
70 333 return apply_filters( 'ablocks/is_enabled_assets_generation', $flag );
71 334 }
72 335
73 336 public static function is_plugin_active( $basename ) {
@@ -83,20 +346,28 @@
83 346 return true;
84 347 }
85 348 }
86 349
350 + /**
351 + * The aBlocks submenu.
352 + *
353 + * Each item declares the aBlocks capability that owns it rather than
354 + * manage_options, so a site can hand somebody the Theme Builder without
355 + * handing them the whole of WordPress. Administrators hold every one of
356 + * these, so nothing changes for them. See Permissions.
357 + */
87 358 public static function get_admin_menu_list() {
88 359 $menu = [];
89 360 $menu[ ABLOCKS_PLUGIN_SLUG ] = [
90 361 'parent_slug' => ABLOCKS_PLUGIN_SLUG,
91 362 'title' => __( 'Dashboard', 'ablocks' ),
92 - 'capability' => 'manage_options',
363 + 'capability' => Permissions::ACCESS,
93 364 ];
94 365 if ( self::is_enabled_block( 'form-builder' ) ) {
95 366 $menu[ ABLOCKS_PLUGIN_SLUG . '-submissions' ] = [
96 367 'parent_slug' => ABLOCKS_PLUGIN_SLUG,
97 368 'title' => __( 'Submissions', 'ablocks' ),
98 - 'capability' => 'manage_options',
369 + 'capability' => 'ablocks_view_submissions',
99 370 ];
100 371 }
101 372 if ( self::get_addon_active_status( 'theme-builder' ) ) {
102 373 $menu[ ABLOCKS_PLUGIN_SLUG . '-theme-builder' ] = [
@@ -101,26 +372,31 @@
101 372 if ( self::get_addon_active_status( 'theme-builder' ) ) {
102 373 $menu[ ABLOCKS_PLUGIN_SLUG . '-theme-builder' ] = [
103 374 'parent_slug' => ABLOCKS_PLUGIN_SLUG,
104 375 'title' => __( 'Theme Builder', 'ablocks' ),
105 - 'capability' => 'manage_options',
376 + 'capability' => 'ablocks_manage_theme_builder',
106 377 ];
107 378 }
108 379 $menu[ ABLOCKS_PLUGIN_SLUG . '-addons' ] = [
109 380 'parent_slug' => ABLOCKS_PLUGIN_SLUG,
110 381 'title' => __( 'Add-ons', 'ablocks' ),
111 - 'capability' => 'manage_options',
382 + 'capability' => 'ablocks_manage_addons',
112 383 ];
384 + $menu[ ABLOCKS_PLUGIN_SLUG . '-scanner' ] = [
385 + 'parent_slug' => ABLOCKS_PLUGIN_SLUG,
386 + 'title' => __( 'Site Scanner', 'ablocks' ),
387 + 'capability' => 'ablocks_run_scanner',
388 + ];
113 389 $menu[ ABLOCKS_PLUGIN_SLUG . '-settings' ] = [
114 390 'parent_slug' => ABLOCKS_PLUGIN_SLUG,
115 391 'title' => __( 'Settings', 'ablocks' ),
116 - 'capability' => 'manage_options',
392 + 'capability' => Permissions::SAVE_SETTINGS,
117 393 ];
118 394 if ( ! defined( 'ABLOCKS_PRO_VERSION' ) ) {
119 395 $menu[ ABLOCKS_PLUGIN_SLUG . '-get-pro' ] = [
120 396 'parent_slug' => ABLOCKS_PLUGIN_SLUG,
121 397 'title' => '<span class="dashicons dashicons-awards academy-blue-color"></span> ' . __( 'Get Pro', 'ablocks' ),
122 - 'capability' => 'manage_options',
398 + 'capability' => Permissions::ACCESS,
123 399 ];
124 400 }
125 401 return apply_filters( 'ablocks/admin_menu_list', $menu );
126 402 }
@@ -134,8 +410,50 @@
134 410 }
135 411 public static function has_value( $value ) {
136 412 return isset( $value ) && ! empty( $value );
137 413 }
414 +
415 + public static function get_array_value( $array, $key, $default ) {
416 + return ( isset( $array[ $key ] ) && ! empty( $array[ $key ] ) ) ? $array[ $key ] : $default;
417 + }
418 +
419 + public static function get_responsive_value( $attribute, $attribute_object_key, $device, $attribute_default_value = [] ) {
420 + // Closure to "clean" a value (similar to your JS clean() helper)
421 + $clean = function( $value ) {
422 + return self::has_value( $value ) ? $value : null;
423 + };
424 +
425 + // Desktop value (fallback to default, or false if nothing found)
426 + $desktop_value =
427 + $clean( $attribute[ $attribute_object_key ] ?? null ) ??
428 + $clean( $attribute_default_value[ $attribute_object_key ] ?? null ) ??
429 + false;
430 +
431 + // Tablet value (fallback to desktop if nothing found)
432 + $tablet_key = $attribute_object_key . 'Tablet';
433 + $tablet_value =
434 + $clean( $attribute[ $tablet_key ] ?? null ) ??
435 + $clean( $attribute_default_value[ $tablet_key ] ?? null ) ??
436 + $desktop_value;
437 +
438 + // Mobile value (fallback to tablet if nothing found)
439 + $mobile_key = $attribute_object_key . 'Mobile';
440 + $mobile_value =
441 + $clean( $attribute[ $mobile_key ] ?? null ) ??
442 + $clean( $attribute_default_value[ $mobile_key ] ?? null ) ??
443 + $tablet_value;
444 +
445 + // Return based on device
446 + switch ( $device ) {
447 + case 'Mobile':
448 + return $mobile_value;
449 + case 'Tablet':
450 + return $tablet_value;
451 + default:
452 + return $desktop_value;
453 + }
454 + }
455 +
138 456 public static function is_gutenberg_editor() {
139 457 global $pagenow;
140 458 if ( $pagenow === 'post.php' || $pagenow === 'post-new.php' ) {
141 459 return true;
@@ -332,8 +650,14 @@
332 650 }
333 651
334 652 public static function get_content_by_object_id( string $id_or_fse_slug ) : ?string {
335 653 if ( is_numeric( $id_or_fse_slug ) ) {
654 + if (
655 + ! current_user_can( 'edit_post', $id_or_fse_slug ) &&
656 + get_post_status( $id_or_fse_slug ) !== 'publish'
657 + ) {
658 + return null;
659 + }
336 660 return get_post_field( 'post_content', intval( $id_or_fse_slug ) );
337 661 } elseif (
338 662 ! empty( $template = get_block_template( $id_or_fse_slug, 'wp_template_part' ) ) ||
339 663 ! empty( $template = get_block_template( $id_or_fse_slug ) )
@@ -343,13 +667,21 @@
343 667 return null;
344 668 }
345 669
346 670 public static function get_block_attributes( string $post_id, string $block_id, string $block_name ) : array {
347 - if ( ! is_null( $post_content = self::get_content_by_object_id( $post_id ) ) ) {
348 - if ( is_array( $blocks = parse_blocks( $post_content ) ) ) {
349 - return self::get_block_attributes_recursive( $block_id, $block_name, $blocks );
350 - }
671 + // Cache parsed blocks per object id for the request — this is called once
672 + // per loop/REST lookup and would otherwise re-fetch + re-parse the whole
673 + // post content every time.
674 + static $parsed_cache = [];
675 + if ( ! array_key_exists( $post_id, $parsed_cache ) ) {
676 + $post_content = self::get_content_by_object_id( $post_id );
677 + $parsed_cache[ $post_id ] = ( ! is_null( $post_content ) && is_array( $blocks = parse_blocks( $post_content ) ) )
678 + ? $blocks
679 + : null;
351 680 }
681 + if ( is_array( $parsed_cache[ $post_id ] ) ) {
682 + return self::get_block_attributes_recursive( $block_id, $block_name, $parsed_cache[ $post_id ] );
683 + }
352 684 return [];
353 685 }
354 686
355 687 public static function get_block_attributes_recursive( string $block_id, string $block_name, array $blocks ) : array {
@@ -378,8 +710,20 @@
378 710 if ( ! empty( $data ) ) {
379 711 return $data;
380 712 }
381 713 }
714 +
715 + if (
716 + isset( $block['blockName'] ) &&
717 + $block['blockName'] === 'core/template-part' &&
718 + ! empty( $block['attrs']['slug'] )
719 + ) {
720 + $part_slug = $block['attrs']['theme'] . '//' . $block['attrs']['slug'];
721 + $data = self::get_block_attributes( $part_slug, $block_id, $block_name );
722 + if ( ! empty( $data ) ) {
723 + return $data;
724 + }
725 + }
382 726 }//end foreach
383 727 return [];
384 728 }
385 729
@@ -584,5 +928,108 @@
584 928 public static function is_valid_site_url( string $url ): bool {
585 929 return str_starts_with( $url, get_option( 'siteurl' ) );
586 930 }
587 931
932 + public static function get_script_loading_strategy() {
933 + return 'defer';
934 + }
935 +
936 + public static function is_static_front_page( $post_id ) {
937 + $show_on_front = get_option( 'show_on_front' );
938 + $page_on_front = (int) get_option( 'page_on_front' );
939 + return ( $show_on_front === 'page' && $page_on_front === (int) $post_id );
940 + }
941 +
942 + public static function get_public_post_type_options() {
943 + $args = [
944 + 'public' => true,
945 + '_builtin' => true,
946 + ];
947 + $post_types = get_post_types( $args, 'objects' );
948 + unset( $post_types['attachment'] ); // Remove 'attachment' if present
949 +
950 + // Get custom post types
951 + $args['_builtin'] = false;
952 + $custom_post_types = get_post_types( $args, 'objects' );
953 +
954 + // Allow filters to modify the combined post types
955 + $all_post_types = apply_filters(
956 + 'ablocks_theme_builder/location_rule_post_types',
957 + array_merge( $post_types, $custom_post_types )
958 + );
959 +
960 + // Format result
961 + $result = [];
962 + foreach ( $all_post_types as $post_type => $post_type_obj ) {
963 + $result[] = [
964 + 'label' => $post_type_obj->label,
965 + 'value' => $post_type,
966 + ];
967 + }
968 +
969 + return $result;
970 + }
971 +
972 + public static function clear_third_party_plugin_cache() {
973 +
974 + // Breeze
975 + try {
976 + if ( class_exists( 'Breeze_Purge' ) ) {
977 + \Breeze_Purge::breeze_cache_flush();
978 + }
979 + } catch ( \Throwable $e ) {
980 + // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
981 + error_log( 'Breeze Cache Clear Failed: ' . $e->getMessage() );
982 + }
983 +
984 + // W3 Total Cache
985 + try {
986 + if ( function_exists( 'w3tc_flush_all' ) ) {
987 + \w3tc_flush_all();
988 + }
989 + } catch ( \Throwable $e ) {
990 + // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
991 + error_log( 'W3 Total Cache Clear Failed: ' . $e->getMessage() );
992 + }
993 +
994 + // WP Super Cache
995 + try {
996 + if ( function_exists( 'wp_cache_clear_cache' ) ) {
997 + \wp_cache_clear_cache();
998 + }
999 + } catch ( \Throwable $e ) {
1000 + // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
1001 + error_log( 'WP Super Cache Clear Failed: ' . $e->getMessage() );
1002 + }
1003 +
1004 + // LiteSpeed Cache
1005 + try {
1006 + if ( class_exists( 'LiteSpeed_Cache_API' ) ) {
1007 + \LiteSpeed_Cache_API::purge_all();
1008 + }
1009 + } catch ( \Throwable $e ) {
1010 + // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
1011 + error_log( 'LiteSpeed Cache Clear Failed: ' . $e->getMessage() );
1012 + }
1013 +
1014 + // WP Fastest Cache
1015 + try {
1016 + if ( class_exists( 'WpFastestCache' ) ) {
1017 + $wpfc = new \WpFastestCache();
1018 + $wpfc->deleteCache();
1019 + }
1020 + } catch ( \Throwable $e ) {
1021 + // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
1022 + error_log( 'WP Fastest Cache Clear Failed: ' . $e->getMessage() );
1023 + }
1024 +
1025 + // Autoptimize
1026 + try {
1027 + if ( function_exists( 'autoptimize_clearall' ) ) {
1028 + \autoptimize_clearall();
1029 + }
1030 + } catch ( \Throwable $e ) {
1031 + // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
1032 + error_log( 'Autoptimize Clear Failed: ' . $e->getMessage() );
1033 + }
1034 + }
588 1035 }