PluginProbe ʕ •ᴥ•ʔ
EmbedPress – PDF Embedder, 3D PDF FlipBook, Google Reviews, YouTube Videos, Upload & Embed PDF documents / 4.6.4
EmbedPress – PDF Embedder, 3D PDF FlipBook, Google Reviews, YouTube Videos, Upload & Embed PDF documents v4.6.4
4.6.5 4.6.4 4.6.3 4.6.2 4.6.1 4.6.0 4.5.6 4.5.5 4.5.4 4.5.3 4.5.2 trunk 1.0.0 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.3.0 1.3.1 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.5.0 1.6.0 1.6.1 1.6.2 1.6.3 1.7.0 1.7.1 1.7.2 1.7.3 1.7.4 1.7.5 2.0.0 2.0.1 2.0.2 2.0.3 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.2.0 2.2.1 2.2.2 2.3.0 2.3.1 2.3.2 2.3.3 2.4.0 2.4.1 2.5.0 2.5.1 2.5.2 2.5.3 2.5.4 2.5.5 2.6.0 2.6.1 2.6.2 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.1.0 3.1.1 3.1.2 3.1.3 3.2.0 3.2.1 3.3.0 3.3.1 3.3.2 3.3.3 3.3.4 3.3.5 3.3.6 3.3.7 3.4.0 3.4.1 3.4.2 3.4.3 3.5.0 3.5.1 3.5.2 3.5.3 3.6.0 3.6.1 3.6.2 3.6.3 3.6.4 3.6.5 3.6.6 3.6.7 3.6.8 3.7.0 3.7.1 3.7.2 3.7.3 3.8.0 3.8.1 3.8.2 3.8.3 3.8.4 3.8.5 3.9.0 3.9.1 3.9.10 3.9.11 3.9.12 3.9.13 3.9.14 3.9.15 3.9.16 3.9.17 3.9.2 3.9.3 3.9.4 3.9.5 3.9.6 3.9.7 3.9.8 3.9.9 4.0.0 4.0.1 4.0.10 4.0.11 4.0.12 4.0.13 4.0.14 4.0.2 4.0.3 4.0.4 4.0.5 4.0.6 4.0.7 4.0.8 4.0.9 4.1.0 4.1.1 4.1.10 4.1.2 4.1.3 4.1.4 4.1.5 4.1.6 4.1.7 4.1.8 4.1.9 4.2.0 4.2.1 4.2.2 4.2.3 4.2.4 4.2.5 4.2.6 4.2.7 4.2.8 4.2.9 4.3.0 4.3.1 4.4.0 4.4.1 4.4.10 4.4.11 4.4.2 4.4.3 4.4.4 4.4.5 4.4.6 4.4.7 4.4.8 4.4.9 4.5.0 4.5.1
embedpress / Core / LocalizationManager.php
embedpress / Core Last commit date
AssetManager.php 2 weeks ago LocalizationManager.php 2 weeks ago init.php 3 weeks ago
LocalizationManager.php
732 lines
1 <?php
2
3 namespace EmbedPress\Core;
4
5 use EmbedPress\Includes\Classes\Helper;
6
7 /**
8 * EmbedPress Localization Manager
9 *
10 * Handles all JavaScript localization for EmbedPress blocks, admin, and frontend
11 * Provides clean separation of concerns from AssetManager
12 */
13 class LocalizationManager
14 {
15 /**
16 * Setup admin localization scripts
17 *
18 * @param string $hook Current admin page hook
19 */
20 public static function setup_admin_localization($hook)
21 {
22 global $pagenow;
23
24 self::setup_license_localization();
25 self::setup_feature_notices_localization();
26
27 // Setup settings page localization if on EmbedPress settings page
28 if (strpos($hook, 'embedpress') !== false) {
29 self::setup_settings_localization();
30 self::setup_preview_localization();
31 self::setup_onboarding_localization($hook);
32 }
33
34 // Only setup localization on post edit pages
35 if (!in_array($pagenow, ['post.php', 'post-new.php'])) {
36 return;
37 }
38 }
39
40 /**
41 * Setup editor localization scripts
42 */
43 public static function setup_editor_localization()
44 {
45 self::setup_frontend_script_localization();
46 self::setup_gutenberg_localization();
47 self::setup_new_blocks_localization();
48 self::setup_preview_localization();
49 // Needed for the Calendar block's editor ServerSideRender preview
50 // to authenticate AJAX requests via the epgc_nonce.
51 self::setup_calendar_widget_localization();
52 }
53
54 /**
55 * Setup frontend localization scripts
56 */
57 public static function setup_frontend_localization()
58 {
59 self::setup_frontend_script_localization();
60 self::setup_gutenberg_localization();
61 self::setup_preview_localization();
62 self::setup_analytics_localization();
63 self::setup_pdf_gallery_localization();
64 self::setup_pdf_lightbox_localization();
65 }
66
67 /**
68 * Setup Elementor widget localization
69 */
70 public static function setup_elementor_localization()
71 {
72 self::setup_frontend_script_localization();
73 self::setup_calendar_widget_localization();
74 self::setup_analytics_localization();
75 self::setup_pdf_gallery_localization();
76 self::setup_pdf_lightbox_localization();
77 }
78
79 /**
80 * Setup preview localization (attached to preview script)
81 */
82 private static function setup_preview_localization()
83 {
84 // Try both admin and preview script handles
85 $script_handles = ['embedpress-admin', 'embedpress-preview'];
86
87 $url_schemes = apply_filters('embedpress:getAdditionalURLSchemes', self::get_url_schemes());
88
89 // Ensure required constants are defined with fallbacks
90 $version = defined('EMBEDPRESS_VERSION') ? EMBEDPRESS_VERSION : '1.0.0';
91 $shortcode = defined('EMBEDPRESS_SHORTCODE') ? EMBEDPRESS_SHORTCODE : 'embedpress';
92 $assets_url = defined('EMBEDPRESS_URL_ASSETS') ? EMBEDPRESS_URL_ASSETS : '';
93
94 $localization_data = [
95 'previewSettings' => [
96 'baseUrl' => get_site_url() . '/',
97 'versionUID' => $version,
98 'debug' => defined('WP_DEBUG') && WP_DEBUG,
99 'nonce' => wp_create_nonce('embedpress_do_ajax_request'),
100 ],
101 'shortcode' => $shortcode,
102 'assetsUrl' => $assets_url,
103 'urlSchemes' => $url_schemes,
104 ];
105
106 foreach ($script_handles as $script_handle) {
107 if (wp_script_is($script_handle, 'enqueued') || wp_script_is($script_handle, 'registered')) {
108 wp_localize_script($script_handle, 'embedpressPreviewData', $localization_data);
109 }
110 }
111
112 wp_localize_script($script_handle, 'embedpressAdminParams', [
113 'ajaxUrl' => admin_url('admin-ajax.php'),
114 'nonce' => wp_create_nonce('embedpress')
115 ]);
116 }
117
118 /**
119 * Setup license script localization
120 */
121 private static function setup_license_localization()
122 {
123 $script_handle = 'embedpress-admin';
124
125 if (!wp_script_is($script_handle, 'enqueued') && !wp_script_is($script_handle, 'registered')) {
126 return;
127 }
128
129 $item_id = defined('EMBEDPRESS_SL_ITEM_ID') ? EMBEDPRESS_SL_ITEM_ID : 'embedpress';
130
131 wp_localize_script($script_handle, 'embedpressLicenseData', [
132 'nonce' => wp_create_nonce('wpdeveloper_sl_' . $item_id . '_nonce')
133 ]);
134 }
135
136 /**
137 * Setup feature notices script localization
138 */
139 private static function setup_feature_notices_localization()
140 {
141 $script_handle = 'embedpress-feature-notices';
142
143 if (!wp_script_is($script_handle, 'enqueued') && !wp_script_is($script_handle, 'registered')) {
144 return;
145 }
146
147 wp_localize_script($script_handle, 'embedpressFeatureNotices', [
148 'ajaxurl' => admin_url('admin-ajax.php'),
149 'nonce' => wp_create_nonce('embedpress_feature_notice'),
150 ]);
151 }
152
153 /**
154 * Setup Gutenberg blocks localization (embedpressObj variable)
155 */
156 private static function setup_gutenberg_localization()
157 {
158 $script_handle = 'embedpress-blocks-editor';
159
160 if (!wp_script_is($script_handle, 'enqueued') && !wp_script_is($script_handle, 'registered')) {
161 return;
162 }
163
164 // Ensure required constants are defined
165 if (!defined('EMBEDPRESS_PLG_NAME')) {
166 return;
167 }
168
169 $elements = (array) get_option(EMBEDPRESS_PLG_NAME . ":elements", []);
170 $active_blocks = isset($elements['gutenberg']) ? (array) $elements['gutenberg'] : [];
171
172 $wistia_labels = self::get_wistia_labels();
173 $wistia_options = self::get_wistia_options();
174 $pars_url = wp_parse_url(get_site_url());
175 $documents_cta_options = (array) get_option(EMBEDPRESS_PLG_NAME . ':document');
176 $current_user = wp_get_current_user();
177 $assets_url = defined('EMBEDPRESS_URL_ASSETS') ? EMBEDPRESS_URL_ASSETS : '';
178 $static_url = defined('EMBEDPRESS_URL_STATIC') ? EMBEDPRESS_URL_STATIC : '';
179
180 // Get global powered_by setting
181 $g_settings = get_option(EMBEDPRESS_PLG_NAME, []);
182 $powered_by_default = isset($g_settings['embedpress_document_powered_by']) && $g_settings['embedpress_document_powered_by'] === 'yes';
183 $lazy_load_default = isset($g_settings['g_lazyload']) && $g_settings['g_lazyload'] == 1;
184
185 wp_localize_script($script_handle, 'embedpressGutenbergData', [
186
187
188 // Keep only the variables that are actually used in JavaScript
189 'wistiaLabels' => json_encode($wistia_labels),
190 'wistiaOptions' => $wistia_options,
191 'poweredBy' => apply_filters('embedpress_document_block_powered_by', $powered_by_default),
192 'isProVersion' => defined('EMBEDPRESS_PRO_PLUGIN_FILE'),
193 'twitchHost' => !empty($pars_url['host']) ? $pars_url['host'] : '',
194 'twitchSettings' => self::get_twitch_settings(),
195 'siteUrl' => site_url(),
196 // Permalink-aware REST base. Plain permalinks serve REST under
197 // ?rest_route=/ instead of /wp-json/, so always derive from
198 // rest_url() rather than concatenating site_url() + '/wp-json/'.
199 'restUrl' => esc_url_raw(rest_url('embedpress/v1/')),
200 'activeBlocks' => $active_blocks,
201 'documentCta' => $documents_cta_options,
202 'pdfRenderer' => Helper::get_pdf_renderer(),
203 'flipbookRenderer' => Helper::get_flipbook_renderer(),
204 'isProPluginActive' => defined('EMBEDPRESS_SL_ITEM_SLUG'),
205 // Google Reviews: when the hosted EmbedPress API (managed proxy) is
206 // connected, a place can hold far more than Google's 5-review API
207 // cap, so the "Reviews per page" ceiling lifts to 50. (Drives the
208 // block + settings count controls; must match the renderer's
209 // max_reviews gate in GoogleReviewsRenderer.)
210 'googleReviewsApifyConnected' => \EmbedPress\Includes\Classes\GoogleReviewsManaged::is_connected(),
211 'ajaxUrl' => admin_url('admin-ajax.php'),
212 'adminUrl' => admin_url(),
213 'sourceNonce' => wp_create_nonce('source_nonce_embedpress'),
214 'canUploadMedia' => current_user_can('upload_files'),
215 // Google Reviews: the saved-places library is a SINGLE SITE-WIDE
216 // store, so both verbs of /google-reviews/places are gated on
217 // manage_options (see GoogleReviewsRestController's authz notes).
218 // The picker needs to know that BEFORE it offers to add a place —
219 // without this flag a non-admin gets a working search, a dead
220 // "+ Select", and a 403 with nothing on screen to explain it.
221 'canManageGoogleReviewPlaces' => current_user_can('manage_options'),
222 'pdfGalleryNonce' => wp_create_nonce('ep_pdf_gallery_nonce'),
223 'assetsUrl' => $assets_url,
224 'staticUrl' => $static_url,
225 // Use underscore naming for consistency with block attributes
226 'iframe_width' => Helper::get_options_value('enableEmbedResizeWidth', '600'),
227 'iframe_height' => Helper::get_options_value('enableEmbedResizeHeight', '400'),
228 'iframeWidth' => Helper::get_options_value('enableEmbedResizeWidth', '600'), // Keep camelCase for backward compatibility
229 'iframeHeight' => Helper::get_options_value('enableEmbedResizeHeight', '400'), // Keep camelCase for backward compatibility
230 'pdfCustomColor' => Helper::get_options_value('custom_color', '#403A81'),
231 'lazyLoad' => $lazy_load_default,
232 'brandingLogos' => [
233 'youtube' => Helper::get_branding_value('logo_url', 'youtube'),
234 'vimeo' => Helper::get_branding_value('logo_url', 'vimeo'),
235 'wistia' => Helper::get_branding_value('logo_url', 'wistia'),
236 'twitch' => Helper::get_branding_value('logo_url', 'twitch'),
237 'dailymotion' => Helper::get_branding_value('logo_url', 'dailymotion'),
238 'document' => Helper::get_branding_value('logo_url', 'document'),
239 ],
240 'viewCount' => [
241 'restUrl' => esc_url_raw(get_rest_url(null, 'embedpress/v1/analytics/view-count')),
242 'downloadUrl' => esc_url_raw(get_rest_url(null, 'embedpress/v1/analytics/download-count')),
243 'labels' => [
244 /* translators: %s: formatted number of views */
245 'singular' => __('%s view', 'embedpress'),
246 /* translators: %s: formatted number of views */
247 'plural' => __('%s views', 'embedpress'),
248 /* translators: %s: formatted number of downloads */
249 'downloadSingular' => __('%s download', 'embedpress'),
250 /* translators: %s: formatted number of downloads */
251 'downloadPlural' => __('%s downloads', 'embedpress'),
252 ],
253 ],
254 'userRoles' => Helper::get_user_roles(),
255 'currentUser' => $current_user->data,
256 'feedbackSubmitted' => get_option('embedpress_feedback_submited'),
257 'ratingHelpDisabled' => Helper::get_options_value('turn_off_rating_help', false),
258 'milestoneDisabled' => Helper::get_options_value('turn_off_milestone', false),
259
260 // Legacy support
261 'wistia_labels' => json_encode($wistia_labels),
262 'wisita_options' => $wistia_options,
263 'embedpress_powered_by' => apply_filters('embedpress_document_block_powered_by', $powered_by_default),
264 'embedpress_pro' => defined('EMBEDPRESS_PRO_PLUGIN_FILE'),
265 'twitch_host' => !empty($pars_url['host']) ? $pars_url['host'] : '',
266 'site_url' => site_url(),
267 'rest_url' => get_rest_url(),
268 'embedpress_rest_url' => get_rest_url(null, 'embedpress/v1/oembed/embedpress'),
269 'active_blocks' => $active_blocks,
270 'document_cta' => $documents_cta_options,
271 'pdf_renderer' => Helper::get_pdf_renderer(),
272 'flipbook_renderer' => Helper::get_flipbook_renderer(),
273 'is_pro_plugin_active' => defined('EMBEDPRESS_SL_ITEM_SLUG'),
274 'ajaxurl' => admin_url('admin-ajax.php'),
275 'source_nonce' => wp_create_nonce('source_nonce_embedpress'),
276 'can_upload_media' => current_user_can('upload_files'),
277 'permalink_structure' => get_option('permalink_structure'),
278 'EMBEDPRESS_URL_ASSETS' => EMBEDPRESS_URL_ASSETS,
279 'iframe_width' => Helper::get_options_value('enableEmbedResizeWidth'),
280 'iframe_height' => Helper::get_options_value('enableEmbedResizeHeight'),
281 'pdf_custom_color' => Helper::get_options_value('custom_color'),
282 'pdf_custom_color' => Helper::get_options_value('custom_color'),
283 'youtube_brand_logo_url' => Helper::get_branding_value('logo_url', 'youtube'),
284 'vimeo_brand_logo_url' => Helper::get_branding_value('logo_url', 'vimeo'),
285 'wistia_brand_logo_url' => Helper::get_branding_value('logo_url', 'wistia'),
286 'twitch_brand_logo_url' => Helper::get_branding_value('logo_url', 'twitch'),
287 'dailymotion_brand_logo_url' => Helper::get_branding_value('logo_url', 'dailymotion'),
288 'user_roles' => Helper::get_user_roles(),
289 'current_user' => $current_user->data,
290 'is_embedpress_feedback_submited' => get_option('embedpress_feedback_submited'),
291 'turn_off_rating_help' => Helper::get_options_value('turn_off_rating_help'),
292 'turn_off_milestone' => Helper::get_options_value('turn_off_milestone'),
293 ]);
294 }
295
296 /**
297 * Setup frontend script localization (embedpressFrontendData variable)
298 */
299 private static function setup_frontend_script_localization()
300 {
301 // The embedpressFrontendData variable should be attached to multiple frontend scripts
302 $script_handles = ['embedpress-front', 'embedpress-ads', 'embedpress-yt-queue'];
303
304 $localization_data = [
305 'ajaxurl' => admin_url('admin-ajax.php'),
306 'isProPluginActive' => defined('EMBEDPRESS_SL_ITEM_SLUG'),
307 'nonce' => wp_create_nonce('ep_nonce'),
308 'rest_url' => esc_url_raw(rest_url()),
309 'rest_nonce' => wp_create_nonce('wp_rest'),
310 ];
311
312 foreach ($script_handles as $script_handle) {
313 if (wp_script_is($script_handle, 'enqueued') || wp_script_is($script_handle, 'registered')) {
314 wp_localize_script($script_handle, 'embedpressFrontendData', $localization_data);
315 }
316 }
317 }
318
319 /**
320 * Setup settings page localization (attached to admin script)
321 */
322 private static function setup_settings_localization()
323 {
324 $script_handle = 'embedpress-admin';
325
326 if (!wp_script_is($script_handle, 'enqueued') && !wp_script_is($script_handle, 'registered')) {
327 return;
328 }
329
330 wp_localize_script($script_handle, 'embedpressSettingsData', [
331 'nonce' => wp_create_nonce('embedpress_elements_action'),
332 'ajaxNonce' => wp_create_nonce('embedpress_ajax_nonce'),
333 ]);
334 }
335
336 /**
337 * Setup onboarding wizard localization
338 *
339 * @param string $hook Current admin page hook
340 */
341 private static function setup_onboarding_localization($hook)
342 {
343 if (strpos($hook, 'embedpress-onboarding') === false) {
344 return;
345 }
346
347 $script_handle = 'embedpress-onboarding';
348
349 if (!wp_script_is($script_handle, 'enqueued') && !wp_script_is($script_handle, 'registered')) {
350 return;
351 }
352
353 $settings = (array) get_option(EMBEDPRESS_PLG_NAME, []);
354 $elements = (array) get_option(EMBEDPRESS_PLG_NAME . ':elements', []);
355 $pro_active = apply_filters('embedpress/is_allow_rander', false);
356
357 wp_localize_script($script_handle, 'embedpressOnboardingData', [
358 'ajaxUrl' => admin_url('admin-ajax.php'),
359 'nonce' => wp_create_nonce('embedpress_onboarding_nonce'),
360 'settingsUrl' => admin_url('admin.php?page=embedpress&page_type=settings'),
361 'dashboardUrl' => admin_url('admin.php?page=embedpress'),
362 'proActive' => $pro_active,
363 'upgradeUrl' => 'https://wpdeveloper.com/in/upgrade-embedpress',
364 'settings' => $settings,
365 'elements' => $elements,
366 'assetsUrl' => EMBEDPRESS_URL_ASSETS,
367 ]);
368 }
369
370 /**
371 * Setup new blocks localization (for new block system)
372 */
373 private static function setup_new_blocks_localization()
374 {
375 // Try multiple possible handles for new blocks
376 $possible_handles = [
377 'embedpress-blocks-editor', // Current handle from AssetManager
378 'embedpress-blocks', // Old handle
379 'embedpress_blocks-cgb-block-js', // Legacy handle
380 'embedpress-blocks-js', // Alternative handle
381 ];
382
383 $script_handle = null;
384 foreach ($possible_handles as $handle) {
385 if (wp_script_is($handle, 'enqueued') || wp_script_is($handle, 'registered')) {
386 $script_handle = $handle;
387 break;
388 }
389 }
390
391 if (!$script_handle) {
392 return;
393 }
394
395 // Ensure required constants are defined
396 if (!defined('EMBEDPRESS_PLG_NAME')) {
397 return;
398 }
399
400 $elements = (array) get_option(EMBEDPRESS_PLG_NAME . ":elements", []);
401 $active_blocks = isset($elements['gutenberg']) ? (array) $elements['gutenberg'] : [];
402
403 wp_localize_script($script_handle, 'embedpressNewBlocksData', [
404 'pluginDirPath' => defined('EMBEDPRESS_PATH_BASE') ? EMBEDPRESS_PATH_BASE : '',
405 'pluginDirUrl' => defined('EMBEDPRESS_URL_STATIC') ? EMBEDPRESS_URL_STATIC . '../' : '',
406 'activeBlocks' => $active_blocks,
407 'canUploadMedia' => current_user_can('upload_files'),
408 'ajaxUrl' => admin_url('admin-ajax.php'),
409 'nonce' => wp_create_nonce('embedpress_nonce'),
410 'restUrl' => rest_url('embedpress/v1/'),
411 'siteUrl' => site_url(),
412 ]);
413 }
414
415
416
417
418
419 /**
420 * Setup analytics tracker localization
421 */
422 private static function setup_analytics_localization()
423 {
424 $script_handle = 'embedpress-analytics-tracker';
425
426 if (!wp_script_is($script_handle, 'enqueued') && !wp_script_is($script_handle, 'registered')) {
427 return;
428 }
429
430 // Get analytics manager instance to check for embedded content
431 $has_embedded_content = false;
432 if (class_exists('EmbedPress\Includes\Classes\Analytics\Analytics_Manager')) {
433 $analytics_manager = \EmbedPress\Includes\Classes\Analytics\Analytics_Manager::get_instance();
434 $has_embedded_content = $analytics_manager->has_embedded_content();
435 }
436
437 // Get tracking enabled setting
438 $tracking_enabled = get_option('embedpress_analytics_tracking_enabled', true);
439
440 // Get original referrer if available
441 $original_referrer = '';
442 if (defined('EMBEDPRESS_ORIGINAL_REFERRER') && !empty(EMBEDPRESS_ORIGINAL_REFERRER)) {
443 $original_referrer = EMBEDPRESS_ORIGINAL_REFERRER;
444 }
445
446 // Get session ID safely — only when tracking is enabled, otherwise we'd
447 // set ep_session_id even though no events will ever be recorded.
448 $session_id = $tracking_enabled ? self::get_analytics_session_id() : '';
449
450 wp_localize_script($script_handle, 'embedpress_analytics', [
451 'ajax_url' => admin_url('admin-ajax.php'),
452 'rest_url' => rest_url('embedpress/v1/analytics/'),
453 'nonce' => wp_create_nonce('wp_rest'),
454 'session_id' => $session_id,
455 'page_url' => get_permalink(),
456 'post_id' => get_the_ID(),
457 'tracking_enabled' => (bool) $tracking_enabled,
458 'original_referrer' => $original_referrer,
459 'has_embedded_content' => $has_embedded_content
460 ]);
461 }
462
463 /**
464 * Setup Google Calendar widget localization
465 */
466 private static function setup_calendar_widget_localization()
467 {
468 $script_handle = 'epgc';
469
470 if (!wp_script_is($script_handle, 'enqueued') && !wp_script_is($script_handle, 'registered')) {
471 return;
472 }
473
474 $nonce = wp_create_nonce('epgc_nonce');
475 wp_localize_script($script_handle, 'embedpressCalendarData', [
476 'ajaxUrl' => admin_url('admin-ajax.php'),
477 'nonce' => $nonce,
478 'translations' => [
479 'allDay' => __('All day', 'embedpress'),
480 'createdBy' => __('Created by', 'embedpress'),
481 'goToEvent' => __('Go to event', 'embedpress'),
482 'unknownError' => __('Unknown error', 'embedpress'),
483 'requestError' => __('Request error', 'embedpress'),
484 'loading' => __('Loading', 'embedpress')
485 ]
486 ]);
487 }
488
489 /**
490 * Load plugin text domain for translations
491 */
492 public static function load_text_domain()
493 {
494 $locale = determine_locale();
495 $locale = apply_filters('plugin_locale', $locale, 'embedpress');
496
497 // Load from WordPress languages directory first
498 if (file_exists(WP_LANG_DIR . "/embedpress-" . $locale . '.mo')) {
499 unload_textdomain('embedpress');
500 load_textdomain('embedpress', WP_LANG_DIR . "/embedpress-" . $locale . '.mo');
501 }
502
503 // Load from plugin languages directory
504 load_plugin_textdomain('embedpress', false, plugin_basename(dirname(EMBEDPRESS_FILE)) . '/languages');
505 }
506
507 /**
508 * Get Wistia labels for localization
509 *
510 * @return array
511 */
512 private static function get_wistia_labels()
513 {
514 return [
515 'watch_from_beginning' => __('Watch from the beginning', 'embedpress'),
516 'skip_to_where_you_left_off' => __('Skip to where you left off', 'embedpress'),
517 'you_have_watched_it_before' => __('It looks like you\'ve watched<br />part of this video before!', 'embedpress'),
518 ];
519 }
520
521 /**
522 * Get Wistia options safely
523 *
524 * @return mixed|null
525 */
526 private static function get_wistia_options()
527 {
528 if (!function_exists('embedpress_wisita_pro_get_options')) {
529 return null;
530 }
531
532 try {
533 // return embedpress_wisita_pro_get_options();
534 } catch (\Exception $e) {
535 // Silently fail if function throws an error
536 return null;
537 }
538 }
539
540 /**
541 * Get branding value safely
542 *
543 * @param string $type
544 * @param string $provider
545 * @return string
546 */
547 private static function get_branding_value($type, $provider)
548 {
549 if (!function_exists('get_branding_value')) {
550 return '';
551 }
552
553 try {
554 return self::get_branding_value($type, $provider);
555 } catch (\Exception $e) {
556 return '';
557 }
558 }
559
560 /**
561 * Get analytics session ID safely
562 *
563 * @return string
564 */
565 private static function get_analytics_session_id()
566 {
567 // Prefer cookie-based session IDs to avoid server PHP session configuration issues
568 if (isset($_COOKIE['ep_session_id'])) {
569 $cookie = $_COOKIE['ep_session_id'];
570 // Allow only safe characters and a minimum length
571 if (is_string($cookie) && preg_match('/^[A-Za-z0-9._:-]{8,}$/', $cookie)) {
572 return sanitize_text_field($cookie);
573 }
574 }
575
576 // Generate a new ephemeral session ID
577 $id = 'ep-sess-' . time() . '-' . wp_generate_password(8, false);
578
579 // Set a session cookie (expires when the browser closes).
580 // Build the Set-Cookie header manually so we can add SameSite=Lax while
581 // staying compatible with PHP 5.6+ (the options-array form of setcookie()
582 // requires PHP 7.3). HttpOnly is intentionally omitted: the analytics
583 // tracker reads ep_session_id via document.cookie to deduplicate views
584 // within a session, so the cookie must be JS-readable.
585 if (!headers_sent()) {
586 $path = defined('COOKIEPATH') ? COOKIEPATH : '/';
587 $domain = (defined('COOKIE_DOMAIN') && COOKIE_DOMAIN) ? COOKIE_DOMAIN : '';
588 $secure = is_ssl();
589
590 $cookie = 'ep_session_id=' . rawurlencode($id)
591 . '; path=' . ($path ? $path : '/')
592 . '; SameSite=Lax';
593 if ($domain) {
594 $cookie .= '; domain=' . $domain;
595 }
596 if ($secure) {
597 $cookie .= '; Secure';
598 }
599
600 header('Set-Cookie: ' . $cookie, false);
601 }
602
603 return $id;
604 }
605
606 /**
607 * Get URL schemes for preview script
608 *
609 * @return array
610 */
611 private static function get_url_schemes()
612 {
613 return [
614 // Apple podcasts
615 'podcasts.apple.com/*',
616 // YouTube
617 'youtube.com/watch\\?*',
618 'youtube.com/playlist\\?*',
619 'youtube.com/channel/*',
620 'youtube.com/c/*',
621 'youtube.com/user/*',
622 'youtube.com/(\w+)[^?\/]*$',
623 // Vimeo
624 'vimeo.com/*',
625 'vimeo.com/groups/*/videos/*',
626 // Twitter
627 'twitter.com/*/status/*',
628 'twitter.com/i/moments/*',
629 'twitter.com/*/timelines/*',
630 // Facebook
631 'facebook.com/*',
632 'fb.watch/*',
633 // Instagram
634 'instagram.com/p/*',
635 'instagr.am/p/*',
636 // SoundCloud
637 'soundcloud.com/*',
638 // Twitch
639 '*.twitch.tv/*',
640 'twitch.tv/*',
641 // Wistia
642 '*.wistia.com/medias/*',
643 'fast.wistia.com/embed/medias/*.jsonp',
644 // Google services
645 'google.com/*',
646 'google.com.*/*',
647 'google.co.*/*',
648 'maps.google.com/*',
649 'docs.google.com/presentation/*',
650 'docs.google.com/document/*',
651 'docs.google.com/spreadsheets/*',
652 'docs.google.com/forms/*',
653 'docs.google.com/drawings/*',
654 ];
655 }
656
657 /**
658 * Setup PDF gallery frontend localization
659 */
660 private static function setup_pdf_gallery_localization()
661 {
662 $script_handle = 'embedpress-pdf-gallery';
663
664 if (!wp_script_is($script_handle, 'enqueued') && !wp_script_is($script_handle, 'registered')) {
665 return;
666 }
667
668 $plugin_url = defined('EMBEDPRESS_URL_ASSETS') ? str_replace('assets/', '', EMBEDPRESS_URL_ASSETS) : '';
669
670 wp_localize_script($script_handle, 'embedpressObj', [
671 'pdfRenderer' => Helper::get_pdf_renderer(),
672 'flipbookRenderer' => Helper::get_flipbook_renderer(),
673 'pluginUrl' => $plugin_url,
674 ]);
675 }
676
677 /**
678 * Setup PDF lightbox frontend localization
679 */
680 private static function setup_pdf_lightbox_localization()
681 {
682 $script_handle = 'embedpress-pdf-lightbox';
683
684 if (!wp_script_is($script_handle, 'enqueued') && !wp_script_is($script_handle, 'registered')) {
685 return;
686 }
687
688 // Only localize if not already done by gallery
689 if (wp_script_is('embedpress-pdf-gallery', 'enqueued')) {
690 return;
691 }
692
693 $plugin_url = defined('EMBEDPRESS_URL_ASSETS') ? str_replace('assets/', '', EMBEDPRESS_URL_ASSETS) : '';
694
695 wp_localize_script($script_handle, 'embedpressObj', [
696 'pdfRenderer' => Helper::get_pdf_renderer(),
697 'flipbookRenderer' => Helper::get_flipbook_renderer(),
698 'pluginUrl' => $plugin_url,
699 ]);
700 }
701
702 /**
703 * Initialize localization manager hooks
704 */
705 /**
706 * Get Twitch settings for Gutenberg localization
707 */
708 private static function get_twitch_settings()
709 {
710 $twitch_settings = get_option(EMBEDPRESS_PLG_NAME . ':twitch', []);
711
712 return [
713 'autoplay' => isset($twitch_settings['embedpress_pro_twitch_autoplay']) ? $twitch_settings['embedpress_pro_twitch_autoplay'] : 'no',
714 'mute' => isset($twitch_settings['embedpress_pro_twitch_mute']) ? $twitch_settings['embedpress_pro_twitch_mute'] : 'yes',
715 'theme' => isset($twitch_settings['embedpress_pro_twitch_theme']) ? $twitch_settings['embedpress_pro_twitch_theme'] : 'dark',
716 'fullscreen' => isset($twitch_settings['embedpress_pro_fs']) ? $twitch_settings['embedpress_pro_fs'] : 'yes',
717 'chat' => isset($twitch_settings['embedpress_pro_twitch_chat']) ? $twitch_settings['embedpress_pro_twitch_chat'] : 'no',
718 'startTime' => isset($twitch_settings['start_time']) ? intval($twitch_settings['start_time']) : 0,
719 ];
720 }
721
722 public static function init()
723 {
724 // Load directly: init() is called from an `init` priority-5 callback in
725 // Core/init.php, so `plugins_loaded` has already fired and registering a
726 // hook on it here is a no-op. Since WP 4.6 `init` is the recommended
727 // hook for load_plugin_textdomain anyway, and WPML's `gettext` filter
728 // is registered well before this point.
729 self::load_text_domain();
730 }
731 }
732