PluginProbe
Buttonizer – Floating Menus, Sticky Buttons, & Popup Builder / trunk
Buttonizer – Floating Menus, Sticky Buttons, & Popup Builder vtrunk
3.5.0 trunk 1.0.10 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.6.1 1.0.7 1.0.8 1.0.9 1.1 1.1.1 1.2 1.3 1.4 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.5 1.5.1 1.5.2 All 109 releases
buttonizer-multifunctional-button / app / Core / buttonizer / wp-php-core / src / InitBootstrap.php

InitBootstrap.php in Buttonizer – Floating Menus, Sticky Buttons, & Popup Builder trunk, at app/Core/buttonizer/wp-php-core/src/InitBootstrap.php

242 lines 7.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Shared bootstrap logic for all Buttonizer plugins.
4 *
5 * Registers common WordPress hooks: language detection, page redirect,
6 * page data injection, embed script, widget shortcode, admin bar, and REST API.
7 *
8 * Each plugin's init.php calls InitBootstrap::boot() with its own Admin and Api
9 * class names, then adds any plugin-specific hooks afterwards.
10 *
11 * @package Core
12 *
13 * @license proprietary
14 * Modified by buttonizer on 04-August-2026 using {@see https://github.com/BrianHenryIE/strauss}.
15 */
16
17 namespace Buttonizer\Core;
18
19 use Buttonizer\Core\Utils\Settings;
20 use Buttonizer\Core\Utils\PermissionCheck;
21
22 class InitBootstrap
23 {
24 /**
25 * Get the current page language.
26 *
27 * Supports Polylang, Weglot, WPML, and falls back to WordPress site language.
28 *
29 * @return string Language code (e.g. "en", "nl").
30 */
31 public static function getCurrentLanguage(): string
32 {
33 // Polylang
34 if (function_exists("pll_current_language")) {
35 return pll_current_language("slug");
36 }
37
38 // Weglot
39 if (function_exists("weglot_get_current_language")) {
40 return weglot_get_current_language();
41 }
42
43 // WPML
44 $currentLanguage = apply_filters('wpml_current_language', NULL);
45
46 // Try to fall back on current language
47 if (!$currentLanguage) return substr(get_bloginfo('language'), 0, 2);
48
49 return $currentLanguage;
50 }
51
52 /**
53 * Redirect to the translated version of a page.
54 *
55 * Uses the plugin name from PluginConfig for the redirect query parameter
56 * (e.g. `is_buttonizer_redirect`, `is_bz_contact_button_redirect`).
57 */
58 public static function redirectToPage(): void
59 {
60 $name = PluginConfig::name();
61
62 // Validate params
63 if (!isset($_GET['page_id']) || !is_numeric($_GET['page_id']) || !isset($_GET['is_' . $name . '_redirect'])) {
64 return;
65 }
66
67 $id = $_GET['page_id'];
68 $page = null;
69
70 // Polylang
71 if (function_exists("pll_get_post")) {
72 $page = pll_get_post($id);
73 }
74
75 // Check WPML translated page
76 if (!$page && $wpmlObject = apply_filters('wpml_object_id', $id)) {
77 $page = $wpmlObject;
78 }
79
80 // Redirect if post or page was found
81 if ($pageUrl = get_the_permalink($page ?? $id)) {
82 // Check if the page was redirected
83 if (!wp_redirect($pageUrl, 302, 'Buttonizer')) {
84 // Make sure to receive a safe redirect URL
85 $redirectUrl = wp_validate_redirect(wp_sanitize_redirect($pageUrl), false);
86
87 // Only redirect if it's a safe and allowed host
88 if ($redirectUrl) {
89 header("Location: " . $redirectUrl, true, 302);
90 }
91
92 exit("A redirect was cancelled.");
93 }
94 exit;
95 }
96 }
97
98 /**
99 * Inject page data into wp_head for the Buttonizer embed script.
100 *
101 * Outputs language, and optionally page ID, categories, front page status,
102 * 404 status, and user roles when `include_page_data` setting is enabled.
103 */
104 public static function injectPageData(): void
105 {
106 if (!Settings::getSetting("site_id")) return;
107
108 // Get current page language
109 $pageData = [
110 "language" => self::getCurrentLanguage()
111 ];
112
113 // Add Buttonizer page data
114 if (Settings::getSetting("include_page_data", false)) {
115 // Get page categories
116 $pageCategories = array_map(function ($category) {
117 return $category->cat_ID;
118 }, get_the_category());
119
120 // Collect page data
121 $pageData = array_merge([
122 "page_id" => get_the_ID(),
123 "categories" => $pageCategories,
124 "is_frontpage" => is_front_page(),
125 "is_404" => is_404(),
126 "user_roles" => PermissionCheck::getUserRoles()
127 ], $pageData);
128 }
129
130 // Define page data
131 $buttonizerData = "if(!window._buttonizer) { window._buttonizer = {}; };var _buttonizer_page_data = " . wp_json_encode($pageData) . ";window._buttonizer.data = { ..._buttonizer_page_data, ...window._buttonizer.data };";
132
133 echo '<script type="text/javascript">' . $buttonizerData . '</script>';
134 }
135
136 /**
137 * Inject the Buttonizer CDN embed script into wp_footer.
138 *
139 * Respects the `wait_until_consent` GDPR setting.
140 */
141 public static function injectEmbedScript(): void
142 {
143 if (!Settings::getSetting("site_id")) return;
144
145 // Buttonizer integration script
146 $buttonizerSnippet = "(function(n,t,c,d){if(t.getElementById(d)){return}var o=t.createElement('script');o.id=d;(o.async=!0),(o.src='https://cdn.buttonizer.io/embed.js'),(o.onload=function(){window.Buttonizer?window.Buttonizer.init(c):window.addEventListener('buttonizer_script_loaded',()=>window.Buttonizer.init(c))}),t.head.appendChild(o)})(window,document,'" . Settings::getSetting("site_id") . "','buttonizer_script')";
147
148 // GDPR Compliance check
149 if (Settings::getSetting("wait_until_consent", false)) {
150 $buttonizerSnippet = "// Buttonizer snippet container
151 function enableButtonizer() {" . $buttonizerSnippet . "};
152
153 // Buttonizer consent given, load content
154 if(window.buttonizer_consent_given){ enableButtonizer(); }";
155 }
156
157 echo '<script type="text/javascript">' . $buttonizerSnippet . '</script>';
158 }
159
160 /**
161 * Validate a UUID v4 string.
162 *
163 * @param string $uuid The string to validate.
164 *
165 * @return bool True if valid UUID v4.
166 */
167 public static function isValidUUID(string $uuid): bool
168 {
169 $regex = '/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/';
170
171 return (bool) preg_match($regex, $uuid);
172 }
173
174 /**
175 * Buttonizer inline widget shortcode handler.
176 *
177 * Usage: [buttonizer id="uuid-here"]
178 *
179 * @param array $atts Shortcode attributes.
180 *
181 * @return string Widget HTML or empty string.
182 */
183 public static function widgetShortcode($atts): string
184 {
185 // Get attributes
186 $atts = shortcode_atts(
187 array(
188 'id' => '',
189 ),
190 $atts
191 );
192
193 // Make sure the ID exists and is a valid UUID
194 if (!isset($atts['id']) || !is_string($atts['id']) || !self::isValidUUID($atts['id'])) return "";
195
196 return '<div class="buttonizer-inline-widget" data-buttonizer-widget-id="' . esc_attr($atts['id']) . '"></div>';
197 }
198
199 /**
200 * Boot all shared WordPress hooks for the plugin.
201 *
202 * Call this from the plugin's init.php after the legacy check (if any).
203 *
204 * @param string $adminClass Fully qualified class name for the plugin's Admin class.
205 * @param string $apiClass Fully qualified class name for the plugin's Api class.
206 */
207 public static function boot(string $adminClass, string $apiClass): void
208 {
209 // Admin dashboard
210 if (is_admin()) {
211 new $adminClass();
212 }
213
214 // Redirect to page in correct language
215 add_action('template_redirect', [self::class, 'redirectToPage'], 0);
216
217 // Page data injection (wp_head)
218 add_action('wp_head', [self::class, 'injectPageData'], 10);
219
220 // Embed script injection (wp_footer)
221 add_action('wp_footer', [self::class, 'injectEmbedScript'], 11);
222
223 // Widget shortcode
224 add_action('init', function () {
225 if (!shortcode_exists("buttonizer")) {
226 add_shortcode('buttonizer', [self::class, 'widgetShortcode']);
227 }
228 });
229
230 // Admin bar
231 add_action('admin_bar_menu', function ($bar) use ($adminClass) {
232 $adminClass::wordpressAdminBar($bar);
233 }, 100);
234
235 // REST API endpoints
236 add_action('rest_api_init', function () use ($apiClass) {
237 new $apiClass();
238 });
239 }
240 }
241
242