PluginProbe
Booking Calendar / 11.2.1
Booking Calendar v11.2.1
11.8.2 11.8.1 11.8 11.7 11.6.1 11.6 11.5 11.4.3 11.4.2 11.4.1 11.4 11.3 11.2.1 11.2 11.1 11.0 10.15.7 10.15.6 10.1.3 10.10 10.10.1 10.10.2 10.11 10.11.2 10.11.3 All 202 releases
booking / includes / _front_end / class-fe-inline-css-js.php

class-fe-inline-css-js.php in Booking Calendar 11.2.1, at includes/_front_end/class-fe-inline-css-js.php

243 lines 7.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Minimal Inline Assets Printer (NO wp_head/wp_footer hooks)
4 *
5 * - Prints <style>/<script> immediately where you call it.
6 * - Optional de-dupe by $key (so the same payload is printed only once per request).
7 *
8 * IMPORTANT:
9 * This is NOT “Elementor-safe” by design. It outputs inline tags at the call site.
10 *
11 * @file: includes/_front_end/class-fe-inline-css-js.php
12 * @package Booking Calendar
13 * @since 11.0.x
14 */
15
16 if ( ! defined( 'ABSPATH' ) ) {
17 exit;
18 }
19
20 class WPBC_FE_Assets {
21
22 const CSS_TAG_ID_BASE = 'wpbc-inline-css';
23 const JS_TAG_ID_BASE = 'wpbc-inline-js';
24
25 /** @var array */
26 protected static $printed_css = array();
27
28 /** @var array */
29 protected static $printed_js = array();
30
31 // ------------------------------------------------------------------------------------------------
32 // == CSS ==
33 // ------------------------------------------------------------------------------------------------
34
35 /**
36 * Print inline CSS immediately (deduped by key).
37 *
38 * @param string $css
39 * @param string $key Unique key to prevent duplicate output. If empty, derived from content hash.
40 *
41 * @return void
42 */
43 public static function add_inline_css( $css, $key = '' ) {
44
45 $css = is_scalar( $css ) ? trim( (string) $css ) : '';
46 if ( '' === $css ) {
47 return;
48 }
49
50 $key = self::normalize_key( $key, $css, 'css' );
51 if ( isset( self::$printed_css[ $key ] ) ) {
52 return;
53 }
54 self::$printed_css[ $key ] = true;
55
56 $id = self::safe_dom_id( self::CSS_TAG_ID_BASE . '-' . $key );
57
58 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
59 return "\n" . '<style id="' . esc_attr( $id ) . '">' . "\n" . $css . "\n" . '</style>' . "\n";
60
61 // wp_add_inline_style( $id, $css ); ???
62 }
63
64 /**
65 * Add inline CSS via WP style handle (Elementor-safe).
66 * Avoids printing <style> tags inside content.
67 *
68 * @param string $handle Style handle (e.g. 'wpbc-ui-both').
69 * @param string $css CSS text.
70 * @param string $key Dedupe key (optional).
71 *
72 * @return bool True if added / already added, false if not possible.
73 */
74 public static function add_inline_css_to_wp_style( $handle, $css, $key = '' ) {
75 // FixIn: 10.14.14.1.
76 $handle = is_scalar( $handle ) ? trim( (string) $handle ) : '';
77 $css = is_scalar( $css ) ? trim( (string) $css ) : '';
78
79 if ( '' === $handle || '' === $css ) {
80 return false;
81 }
82
83 if ( ! function_exists( 'wp_add_inline_style' ) ) {
84 return false;
85 }
86
87 // Handle must exist in WP styles system.
88 if ( ! wp_style_is( $handle, 'enqueued' ) && ! wp_style_is( $handle, 'done' ) && ! wp_style_is( $handle, 'registered' ) ) {
89 return false;
90 }
91
92 $key = self::normalize_key( $key, $css, 'css' );
93 if ( isset( self::$printed_css[ $key ] ) ) {
94 return true;
95 }
96 self::$printed_css[ $key ] = true;
97
98 wp_add_inline_style( $handle, $css );
99
100 return true;
101 }
102
103 // ------------------------------------------------------------------------------------------------
104 // == JS ==
105 // ------------------------------------------------------------------------------------------------
106
107 /**
108 * Print inline JS immediately (deduped by key). -- Usually it is - Fallback to direct inline JS, if previosly not added script via: add_jq_ready_js_to_wp_script.
109 *
110 * @param string $js
111 * @param string $key Unique key to prevent duplicate output. If empty, derived from content hash.
112 *
113 * @return void
114 */
115 public static function add_inline_js( $js, $key = '' ) {
116
117 $js = is_scalar( $js ) ? trim( (string) $js ) : '';
118 if ( '' === $js ) {
119 return;
120 }
121
122 $key = self::normalize_key( $key, $js, 'js' );
123 if ( isset( self::$printed_js[ $key ] ) ) {
124 return;
125 }
126 self::$printed_js[ $key ] = true;
127
128 $id = self::safe_dom_id( self::JS_TAG_ID_BASE . '-' . $key );
129
130
131 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
132 return "\n" . '<script id="' . esc_attr( $id ) . '" type="text/javascript">' . "\n" . $js . "\n" . '</script>' . "\n";
133 }
134
135
136 // FixIn: 10.14.13.2. // FixIn: 10.14.17.2.
137 /**
138 * Add JS (wrapped in jQuery ready) as WP inline script after a registered/enqueued handle. (Elementor-safe)
139 * This avoids <script> tags in content (Elementor-safe).
140 *
141 * @param string $handle Script handle (e.g. 'wpbc-main-client' or 'wpbc_all').
142 * @param string $js_body JS without <script> and without ready wrapper.
143 * @param string $key Dedupe key (optional).
144 *
145 * @return bool True if added, false if not possible.
146 */
147 public static function add_jq_ready_js_to_wp_script( $handle, $js_body, $key = '' ) {
148
149 $handle = is_scalar( $handle ) ? trim( (string) $handle ) : '';
150 $js_body = is_scalar( $js_body ) ? trim( (string) $js_body ) : '';
151
152 if ( '' === $handle || '' === $js_body ) {
153 return false;
154 }
155
156 // One Exception to Ensure enqueue script - 'wpbc_all'! // FixIn: 10.14.17.2.
157 if ( 'wpbc_all' === $handle ) {
158 // 1) Ensure the handle exists in WP_Scripts *now* (register if needed).
159 if ( ! wp_script_is( 'wpbc_all', 'registered' ) && function_exists( 'wp_register_script' ) ) {
160 wp_enqueue_script( 'wpbc_all', wpbc_plugin_url( '/_dist/all/_out/wpbc_all.js' ), array( 'jquery' ), WP_BK_VERSION_NUM, array( 'in_footer' => WPBC_JS_IN_FOOTER ) );
161 }
162
163 // 2) Enqueue it (safe even if it will be enqueued later anyway).
164 if ( function_exists( 'wp_enqueue_script' ) ) {
165 wp_enqueue_script( 'wpbc_all' );
166 }
167 }
168
169
170 // Only if WP script API is available and the handle is in play.
171 if ( ! function_exists( 'wp_add_inline_script' ) ) {
172 return false;
173 }
174 if ( ! wp_script_is( $handle, 'enqueued' ) && ! wp_script_is( $handle, 'done' ) && ! wp_script_is( $handle, 'registered' ) ) {
175 return false;
176 }
177
178 if ( ';' !== substr( $js_body, - 1 ) ) {
179 $js_body .= ';';
180 }
181
182 $js = wpbc_jq_ready_start() . "\n" . $js_body . "\n" . wpbc_jq_ready_end();
183
184 $key = self::normalize_key( $key, $js, 'js' );
185 if ( isset( self::$printed_js[ $key ] ) ) {
186 return true;
187 }
188 self::$printed_js[ $key ] = true;
189
190 wp_add_inline_script( $handle, $js, 'after' );
191
192 return true;
193 }
194
195 // ------------------------------------------------------------------------------------------------
196 // Internals
197 // ------------------------------------------------------------------------------------------------
198
199 /**
200 * Normalize de-dupe key. If empty, use deterministic hash from content.
201 *
202 * @param string $key
203 * @param string $content
204 * @param string $type 'css'|'js'
205 *
206 * @return string
207 */
208 protected static function normalize_key( $key, $content, $type ) {
209
210 $key = is_scalar( $key ) ? trim( (string) $key ) : '';
211 if ( '' !== $key ) {
212 return $key;
213 }
214
215 return (string) $type . '-' . md5( (string) $content );
216 }
217
218 /**
219 * Make a safe DOM id (ASCII, simple).
220 *
221 * @param string $id
222 *
223 * @return string
224 */
225 protected static function safe_dom_id( $id ) {
226
227 $id = strtolower( (string) $id );
228 $id = preg_replace( '/[^a-z0-9\-\_]+/', '-', $id );
229 $id = trim( $id, '-' );
230
231 // Prevent extremely long ids.
232 if ( strlen( $id ) > 80 ) {
233 $id = substr( $id, 0, 80 );
234 }
235
236 if ( '' === $id ) {
237 $id = 'wpbc-inline';
238 }
239
240 return $id;
241 }
242 }
243