PluginProbe ʕ •ᴥ•ʔ
Superb Addons: Blocks, Patterns, Pre-built Pages, Sliders, Popups, Free Forms, Animations & More / 4.0.7
Superb Addons: Blocks, Patterns, Pre-built Pages, Sliders, Popups, Free Forms, Animations & More v4.0.7
4.0.7 4.0.6 4.0.5 4.0.4 4.0.3 4.0.2 4.0.1 4.0.0 trunk 1.0.0 2.0.0 2.0.1 2.0.2 2.0.3 3.0 3.0.1 3.0.2 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.2 3.1.3 3.2.0 3.2.1 3.2.2 3.2.4 3.2.5 3.2.7 3.2.8 3.2.9 3.3.0 3.3.1 3.3.2 3.4.0 3.4.1 3.4.2 3.4.5 3.4.6 3.5.0 3.5.1 3.5.2 3.5.3 3.5.4 3.5.6 3.5.7 3.5.8 3.5.9 3.6.0 3.6.1 3.6.2 3.7.0 3.7.1
superb-blocks / src / data / utils / class-third-party-compatibility-util.php
superb-blocks / src / data / utils Last commit date
wizard 6 days ago class-addons-template-util.php 6 days ago class-allowed-template-html-util.php 6 days ago class-base-exception.php 6 days ago class-cache-constants.php 6 days ago class-cache-exception.php 6 days ago class-engagement.php 6 days ago class-key-exception.php 6 days ago class-keytypes.php 6 days ago class-option-exception.php 6 days ago class-quiet-skin.php 6 days ago class-request-exception.php 6 days ago class-script-translations.php 6 days ago class-settings-exception.php 6 days ago class-theme-installer-exception.php 6 days ago class-theme-installer.php 6 days ago class-third-party-compatibility-util.php 6 days ago
class-third-party-compatibility-util.php
109 lines
1 <?php
2
3 namespace SuperbAddons\Data\Utils;
4
5 use SuperbAddons\Data\Controllers\LogController;
6
7 defined('ABSPATH') || exit();
8
9 /**
10 * Compatibility helpers for coexisting with third-party plugins inside our own
11 * synthetic rendering contexts (e.g. the wizard template preview canvas), where
12 * the usual front-end page-load state is not fully set up.
13 *
14 * Two layers:
15 * - guard_preview_render(): registers shims for specific, known conflicts that
16 * we can fully fix so the preview renders completely.
17 * - run_guarded(): a generic safety net so that an uncaught error from ANY
18 * third-party hook degrades gracefully instead of white-screening the
19 * preview.
20 *
21 * Everything here only affects the short-lived, admin-only preview request, so
22 * normal site pages are never touched.
23 */
24 class ThirdPartyCompatibilityUtil
25 {
26 /**
27 * Register shims for known, fully-fixable third-party conflicts.
28 *
29 * Call this immediately before wp_head() in a synthetic render context.
30 */
31 public static function guard_preview_render()
32 {
33 self::guard_gutenverse_conditional_handles();
34 }
35
36 /**
37 * Run a synthetic-render callback (e.g. wp_head / wp_body_open / wp_footer)
38 * with a safety net around any uncaught error a third-party hook may throw.
39 *
40 * In our preview we call wp_head()/wp_footer() ourselves, so a TypeError or
41 * other Error thrown by some plugin's enqueue/print callback propagates back
42 * up to our call site. Without this it would abort the whole preview (a
43 * "critical error" white screen). Catching it lets the rest of the canvas
44 * render and records the offender so a targeted shim can be added later.
45 *
46 * Errors originating from our own plugin are re-thrown: this is strictly a
47 * third-party safety net, not a blanket error suppressor for our own bugs.
48 *
49 * @param callable $callback Output-producing callback to execute.
50 */
51 public static function run_guarded($callback)
52 {
53 try {
54 call_user_func($callback);
55 } catch (\Throwable $e) {
56 // PHP 7+. On PHP 5.6 this class of failure is a warning, not a
57 // throwable, so there is nothing to catch and \Throwable never matches.
58 self::handle_render_throwable($e);
59 }
60 }
61
62 /**
63 * Decide what to do with an error caught during a synthetic render.
64 *
65 * @param \Throwable $e
66 */
67 private static function handle_render_throwable($e)
68 {
69 // Never hide our own bugs: if the failure originates inside our plugin, re-throw.
70 if (defined('SUPERBADDONS_PLUGIN_DIR')) {
71 $file = wp_normalize_path($e->getFile());
72 $plugin_dir = wp_normalize_path(SUPERBADDONS_PLUGIN_DIR);
73 if ($plugin_dir !== '' && strpos($file, $plugin_dir) === 0) {
74 throw $e;
75 }
76 }
77
78 // Third-party fatal during our preview: record it and let the render continue.
79 LogController::HandleException($e);
80 }
81
82 /**
83 * Gutenverse compatibility.
84 *
85 * Frontend_Generator::load_conditional_scripts() and ::load_conditional_styles()
86 * run array_unique() on the result of the gutenverse_conditional_script_handles /
87 * gutenverse_conditional_style_handles filters. Gutenverse's own Frontend_Cache
88 * hooks those filters (at priority 0) and, in its default 'file' render mechanism,
89 * returns json_decode() of cached content, which is null when there is no cache for
90 * our synthetic preview. array_unique(null) throws a TypeError on PHP 8 and aborts
91 * the whole preview.
92 *
93 * We hook the same filters at PHP_INT_MAX (the highest priority, so our callback
94 * runs LAST, after Gutenverse's own cache callback) and coerce any non-array value
95 * to an empty array. On a healthy render the value is already an array and passes
96 * through unchanged, so this only ever intervenes in the broken case.
97 */
98 private static function guard_gutenverse_conditional_handles()
99 {
100 add_filter('gutenverse_conditional_script_handles', array(__CLASS__, '_ensure_array'), PHP_INT_MAX);
101 add_filter('gutenverse_conditional_style_handles', array(__CLASS__, '_ensure_array'), PHP_INT_MAX);
102 }
103
104 public static function _ensure_array($value)
105 {
106 return is_array($value) ? $value : array();
107 }
108 }
109