PluginProbe ʕ •ᴥ•ʔ
EmbedPress – PDF Embedder, 3D PDF FlipBook, Google Reviews, YouTube Videos, Upload & Embed PDF documents / 4.5.1
EmbedPress – PDF Embedder, 3D PDF FlipBook, Google Reviews, YouTube Videos, Upload & Embed PDF documents v4.5.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 / EmbedPress / Ends / Back / Settings / EmbedpressSettings.php
embedpress / EmbedPress / Ends / Back / Settings Last commit date
templates 2 months ago EmbedpressSettings.php 2 months ago
EmbedpressSettings.php
915 lines
1 <?php
2 namespace EmbedPress\Ends\Back\Settings;
3
4 use EmbedPress\Includes\Classes\Helper;
5 use EmbedPress\Includes\Classes\EmbedPress_Plugin_Usage_Tracker;
6
7 class EmbedpressSettings {
8 var $page_slug = '';
9 /**
10 * @var int|string
11 */
12 protected $file_version;
13
14 public function __construct($page_slug = 'embedpress') {
15 $this->page_slug = $page_slug;
16 $this->file_version = defined( 'WP_DEBUG') && WP_DEBUG ? time() : EMBEDPRESS_VERSION;
17
18 // One-time install-type detection. Must run before any default settings are
19 // written below, otherwise every site looks "non-empty" by the time the
20 // activation hook fires. Existing users keep the 'existing' marker; only
21 // truly fresh sites get marked 'fresh' and will be eligible for the wizard.
22 if ( ! get_option( 'embedpress_install_type', false ) ) {
23 $had_prior_data = (bool) get_option( 'embedpress_elements_updated', false )
24 || ! empty( get_option( EMBEDPRESS_PLG_NAME, [] ) )
25 || ! empty( get_option( EMBEDPRESS_PLG_NAME . ':elements', [] ) );
26 update_option( 'embedpress_install_type', $had_prior_data ? 'existing' : 'fresh' );
27
28 // Existing users may carry a stuck need_first_time_redirect flag set by
29 // an earlier buggy migration. Clear it so they aren't dropped into the
30 // wizard after updating to this version.
31 if ( $had_prior_data ) {
32 $prior_settings = get_option( EMBEDPRESS_PLG_NAME, [] );
33 if ( isset( $prior_settings['need_first_time_redirect'] ) ) {
34 unset( $prior_settings['need_first_time_redirect'] );
35 update_option( EMBEDPRESS_PLG_NAME, $prior_settings );
36 }
37 }
38 }
39
40 add_action('admin_menu', [$this, 'register_menu']);
41 add_action( 'init', [$this, 'save_settings']);
42
43 // Add activation redirect hook
44 add_action( 'admin_init', [$this, 'embedpress_maybe_redirect_to_settings']);
45
46 // ajax
47 add_action( 'wp_ajax_embedpress_elements_action', [$this, 'update_elements_list']);
48 add_action( 'wp_ajax_embedpress_settings_action', [$this, 'save_settings']);
49 add_action( 'wp_ajax_save_global_brand_image', [$this, 'save_global_brand_image']);
50 add_action( 'wp_ajax_embedpress_dismiss_element', [$this, 'dismiss_element']);
51 add_action( 'wp_ajax_embedpress_dismiss_feature_notice', [$this, 'dismiss_feature_notice']);
52 add_action( 'wp_ajax_embedpress_save_onboarding', [$this, 'save_onboarding_settings']);
53
54 // Hide all admin notices on onboarding page
55 add_action( 'in_admin_header', function() {
56 if ( isset( $_GET['page'] ) && $_GET['page'] === 'embedpress-onboarding' ) {
57 remove_all_actions( 'admin_notices' );
58 remove_all_actions( 'all_admin_notices' );
59 }
60 }, 999 );
61
62 $g_settings = get_option( EMBEDPRESS_PLG_NAME, [] );
63
64 if(!isset($g_settings['turn_off_rating_help'])){
65 $g_settings['turn_off_rating_help'] = true;
66 update_option(EMBEDPRESS_PLG_NAME, $g_settings);
67 }
68 if(!isset($g_settings['turn_off_milestone'])){
69 $g_settings['turn_off_milestone'] = true;
70 update_option(EMBEDPRESS_PLG_NAME, $g_settings);
71 }
72
73 // Set default value for embedpress_document_powered_by to 'yes' on fresh installations
74 if(!isset($g_settings['embedpress_document_powered_by'])){
75 $g_settings['embedpress_document_powered_by'] = 'yes';
76 update_option(EMBEDPRESS_PLG_NAME, $g_settings);
77 }
78
79
80 // Migration
81 $option = 'embedpress_elements_updated'; // to update initially for backward compatibility
82 if ( !get_option( $option, false) ) {
83 $elements_initial_states = [
84 'gutenberg' => [
85 'google-docs-block' => 'google-docs-block',
86 'document' => 'document',
87 'embedpress' => 'embedpress',
88 'embedpress-pdf' => 'embedpress-pdf',
89 'google-sheets-block' => 'google-sheets-block',
90 'google-slides-block' => 'google-slides-block',
91 'youtube-block' => 'youtube-block',
92 'google-forms-block' => 'google-forms-block',
93 'google-drawings-block' => 'google-drawings-block',
94 'google-maps-block' => 'google-maps-block',
95 'twitch-block' => 'twitch-block',
96 'wistia-block' => 'wistia-block',
97 'vimeo-block' => 'vimeo-block',
98 ],
99 'elementor' => [
100 'embedpress-document' => 'embedpress-document',
101 'embedpress' => 'embedpress',
102 'embedpress-pdf' => 'embedpress-pdf',
103 ]
104 ];
105
106
107 $settings = get_option( EMBEDPRESS_PLG_NAME, [] );
108 $yt = get_option( EMBEDPRESS_PLG_NAME.':youtube' );
109 if ( empty( $settings) && empty( $yt) ) {
110 $settings['need_first_time_redirect'] = true;
111 }
112 if ( !isset( $settings['enablePluginInAdmin']) ) {
113 $settings['enablePluginInAdmin'] = 1;
114 }
115 if ( !isset( $settings['enablePluginInFront']) ) {
116 $settings['enablePluginInFront'] = 1;
117 }
118
119 update_option( EMBEDPRESS_PLG_NAME.":elements", $elements_initial_states);
120 update_option( EMBEDPRESS_PLG_NAME, $settings);
121 update_option( $option, true);
122 }
123 $migration_v_320 = 'embedpress_v_320_migration';
124 if ( !get_option( $migration_v_320, false) ) {
125 $elements = (array) get_option( EMBEDPRESS_PLG_NAME.":elements", []);
126 $elements['gutenberg']['embedpress-pdf'] = 'embedpress-pdf';
127 $elements['elementor']['embedpress-pdf'] = 'embedpress-pdf';
128 update_option( EMBEDPRESS_PLG_NAME.":elements", $elements);
129 update_option( $migration_v_320, true);
130 }
131
132 $migration_v_330 = 'embedpress_v_330_migration';
133 if ( !get_option( $migration_v_330, false) ) {
134 $elements = (array) get_option( EMBEDPRESS_PLG_NAME.":elements", []);
135 $elements['gutenberg']['embedpress-calendar'] = 'embedpress-calendar';
136 $elements['elementor']['embedpress-calendar'] = 'embedpress-calendar';
137 update_option( EMBEDPRESS_PLG_NAME.":elements", $elements);
138 update_option( $migration_v_330, true);
139 }
140
141 }
142 function embedpress_maybe_redirect_to_settings() {
143 $settings = get_option( EMBEDPRESS_PLG_NAME, [] );
144 if ( isset( $settings['need_first_time_redirect']) && $settings['need_first_time_redirect'] ) {
145 // Skip redirect if already done, doing AJAX, or in certain admin contexts
146 if ( get_option( 'embedpress_activation_redirect_done' ) || wp_doing_ajax() || wp_doing_cron() ) {
147 return;
148 }
149
150 // Skip redirect for bulk activations, network admin, or CLI
151 if ( is_network_admin() || isset( $_GET['activate-multi'] ) || defined( 'WP_CLI' ) ) {
152 return;
153 }
154
155 // Skip redirect if not in admin area or if user doesn't have proper capabilities
156 if ( ! is_admin() || ! current_user_can( 'manage_options' ) ) {
157 return;
158 }
159
160 // Skip redirect if we're already on the EmbedPress settings or onboarding page
161 if ( isset( $_GET['page'] ) && in_array( $_GET['page'], [ $this->page_slug, 'embedpress-onboarding' ], true ) ) {
162 return;
163 }
164
165 // If onboarding is not complete and pro is not active, redirect to onboarding wizard
166 $pro_active = apply_filters( 'embedpress/is_allow_rander', false );
167 if ( ! $pro_active && ! get_option( 'embedpress_onboarding_complete', false ) ) {
168 update_option( 'embedpress_activation_redirect_done', true );
169 $settings['need_first_time_redirect'] = false;
170 update_option( EMBEDPRESS_PLG_NAME, $settings );
171
172 wp_safe_redirect( admin_url( 'admin.php?page=embedpress-onboarding' ) );
173 exit;
174 }
175
176 // Set redirect done flag and clear the redirect trigger
177 update_option( 'embedpress_activation_redirect_done', true );
178 $settings['need_first_time_redirect'] = false;
179 update_option( EMBEDPRESS_PLG_NAME, $settings);
180
181 // Perform the redirect
182 wp_safe_redirect( admin_url('admin.php?page='.$this->page_slug) );
183 exit;
184 }
185 }
186 public function update_elements_list() {
187
188 if (!current_user_can('manage_options')) {
189 wp_send_json_error(array('message' => 'You do not have sufficient permissions to access this functionality.'));
190 return;
191 }
192
193 if ( !empty($_POST['_wpnonce'] && wp_verify_nonce( $_POST['_wpnonce'], 'embedpress_elements_action')) ) {
194 $option = EMBEDPRESS_PLG_NAME.":elements";
195 $elements = (array) get_option( $option, []);
196 $settings = (array) get_option( EMBEDPRESS_PLG_NAME, []);
197
198 $type = !empty( $_POST['element_type']) ? sanitize_text_field( $_POST['element_type']) : '';
199 $name = !empty( $_POST['element_name']) ? sanitize_text_field( $_POST['element_name']) : '';
200 $checked = !empty( $_POST['checked']) ? $_POST['checked'] : false;
201 if ( 'false' != $checked ) {
202 $elements[$type][$name] = $name;
203 if ( $type === 'classic' ) {
204 $settings[$name] = 1;
205 }
206 }else{
207 if( isset( $elements[$type]) && isset( $elements[$type][$name])){
208 unset( $elements[$type][$name]);
209 }
210 if ( $type === 'classic' ) {
211 $settings[$name] = 0;
212 }
213 }
214 update_option( EMBEDPRESS_PLG_NAME, $settings);
215 update_option( $option, $elements);
216 wp_send_json_success();
217 }
218 wp_send_json_error();
219 }
220
221 public function register_menu() {
222 add_menu_page( __('EmbedPress Settings', 'embedpress'), 'EmbedPress', 'manage_options', $this->page_slug,
223 [ $this, 'render_settings_page' ], EMBEDPRESS_URL_ASSETS.'images/menu-icon.svg', 64 );
224
225 // Add Dashboard submenu (replaces the default first submenu item)
226 add_submenu_page( $this->page_slug, __('EmbedPress Dashboard', 'embedpress'), __('Dashboard', 'embedpress'), 'manage_options', $this->page_slug,
227 [ $this, 'render_settings_page' ] );
228
229 // Add Branding submenu
230 add_submenu_page( $this->page_slug, __('EmbedPress Branding', 'embedpress'), __('Branding', 'embedpress'), 'manage_options', $this->page_slug . '&page_type=custom-logo',
231 [ $this, 'render_settings_page' ] );
232
233 // Add Custom Ads submenu
234 add_submenu_page( $this->page_slug, __('EmbedPress Custom Ads', 'embedpress'), __('Custom Ads', 'embedpress'), 'manage_options', $this->page_slug . '&page_type=ads',
235 [ $this, 'render_settings_page' ] );
236
237
238 // Add Shortcode submenu
239 add_submenu_page( $this->page_slug, __('EmbedPress Shortcode', 'embedpress'), __('Shortcode', 'embedpress'), 'manage_options', $this->page_slug . '&page_type=shortcode',
240 [ $this, 'render_settings_page' ] );
241
242 // Add Settings submenu
243 add_submenu_page( $this->page_slug, __('EmbedPress Settings', 'embedpress'), __('Settings', 'embedpress'), 'manage_options', $this->page_slug . '&page_type=settings',
244 [ $this, 'render_settings_page' ] );
245
246
247 // Add License submenu (only if pro is active)
248 if ( apply_filters('embedpress/is_allow_rander', false) ) {
249 add_submenu_page( $this->page_slug, __('EmbedPress License', 'embedpress'), __('License', 'embedpress'), 'manage_options', $this->page_slug . '&page_type=license',
250 [ $this, 'render_settings_page' ] );
251 }
252
253 // Register Setup Wizard submenu page
254 add_submenu_page( $this->page_slug, __('EmbedPress Setup Wizard', 'embedpress'), __('Setup Wizard', 'embedpress'), 'manage_options', 'embedpress-onboarding',
255 [ $this, 'render_onboarding_page' ] );
256
257 // Add admin footer script to handle menu highlighting
258 add_action('admin_footer', [$this, 'admin_menu_highlight_script']);
259
260 // Add filter to reorder menu items - License should be last
261 add_filter('admin_menu', [$this, 'reorder_submenu_items'], 999);
262 }
263
264
265 public function admin_menu_highlight_script() {
266 // Only load on EmbedPress admin pages
267 $current_page = isset($_GET['page']) ? sanitize_text_field($_GET['page']) : '';
268 if ($current_page !== $this->page_slug) {
269 return;
270 }
271
272 $page_type = isset($_GET['page_type']) ? sanitize_text_field($_GET['page_type']) : '';
273 // Fixed: Evaluate PHP filter on server-side before passing to JavaScript
274 $is_pro_active = apply_filters('embedpress/is_allow_rander', false);
275
276 ?>
277 <script type="text/javascript">
278 /* EmbedPress Admin Menu Highlight Script - Fixed apply_filters issue */
279 jQuery(document).ready(function($) {
280 // Remove current highlighting
281 $('#adminmenu .wp-submenu li').removeClass('current');
282 $('#adminmenu .wp-submenu a').removeClass('current');
283
284 var pageType = '<?php echo esc_js($page_type); ?>';
285 var isProActive = <?php echo $is_pro_active ? 'true' : 'false'; ?>;
286 var menuSelector = '';
287
288 // Map page types to menu selectors
289 switch(pageType) {
290 case 'settings':
291 menuSelector = 'a[href*="page_type=settings"]';
292 break;
293 case 'shortcode':
294 menuSelector = 'a[href*="page_type=shortcode"]';
295 break;
296 case 'sources':
297 menuSelector = 'a[href*="page_type=sources"]';
298 break;
299 case 'elements':
300 menuSelector = 'a[href*="page_type=elements"]';
301 break;
302 case 'custom-logo':
303 menuSelector = 'a[href*="page_type=custom-logo"]';
304 break;
305 case 'ads':
306 menuSelector = 'a[href*="page_type=ads"]';
307 break;
308 case 'license':
309 menuSelector = 'a[href*="page_type=license"]';
310 break;
311 default:
312 // Default to Dashboard (no page_type or hub)
313 menuSelector = 'a[href="admin.php?page=<?php echo esc_js($this->page_slug); ?>"]';
314 break;
315 }
316
317 // Highlight the correct menu item
318 if (menuSelector) {
319 var $menuItem = $('#adminmenu .wp-submenu ' + menuSelector);
320 if ($menuItem.length) {
321 $menuItem.addClass('current').parent().addClass('current');
322 }
323 }
324 });
325 </script>
326 <?php
327 }
328
329
330 public function render_settings_page( ) {
331 global $template, $page_slug, $nonce_field, $ep_page, $gen_menu_template_names, $brand_menu_template_names, $pro_active, $coming_soon, $success_message, $error_message, $platform_menu_template_names;
332
333 $page_slug = $this->page_slug; // make this available for included template
334 $template = !empty( $_GET['page_type'] ) ? sanitize_file_name( $_GET['page_type']) : 'hub';
335
336 $nonce_field = wp_nonce_field('ep_settings_nonce', 'ep_settings_nonce', true, false);
337 $ep_page = admin_url('admin.php?page='.$this->page_slug);
338 $gen_menu_template_names = apply_filters('ep_general_menu_tmpl_names', ['settings', 'shortcode',]);
339 $platform_menu_template_names = apply_filters('ep_platform_menu_tmpl_names', [ 'youtube', 'vimeo', 'wistia', 'twitch','dailymotion', 'soundcloud' ,'spotify','google-calendar','opensea']);
340 $brand_menu_template_names = apply_filters('ep_brand_menu_templates', ['custom-logo', 'branding',]);
341 $pro_active = apply_filters('embedpress/is_allow_rander', false);
342 $coming_soon = "<span class='ep-coming-soon'>". esc_html__( '(Coming soon)', 'embedpress'). "</span>";
343 $success_message = esc_html__( "Settings Updated", "embedpress" );
344 $error_message = esc_html__( "Ops! Something went wrong.", "embedpress" );
345 include_once EMBEDPRESS_SETTINGS_PATH . 'templates/main-template.php';
346 }
347
348 public function save_settings() {
349 // needs to check for ajax and return response accordingly.
350 if ( !empty( $_POST['ep_settings_nonce']) && wp_verify_nonce( $_POST['ep_settings_nonce'], 'ep_settings_nonce') ) {
351 $submit_type = !empty( $_POST['submit'] ) ? $_POST['submit'] : '';
352 $save_handler_method = "save_{$submit_type}_settings";
353 do_action( "before_{$save_handler_method}");
354 do_action( "before_embedpress_settings_save");
355 if ( method_exists( $this, $save_handler_method ) ) {
356 $this->$save_handler_method();
357 }
358 do_action( "after_embedpress_settings_save");
359 $return_url = isset( $_SERVER['HTTP_REFERER'] ) ? $_SERVER['HTTP_REFERER'] : admin_url();
360 $return_url = add_query_arg( 'success', 1, $return_url );
361 if ( wp_doing_ajax() ) {
362 wp_send_json_success();
363 }
364 wp_safe_redirect( $return_url);
365 exit();
366 }
367 }
368
369 public function save_settings_settings() {
370 $settings = (array) get_option( EMBEDPRESS_PLG_NAME, []);
371 $settings ['enableEmbedResizeWidth'] = isset( $_POST['enableEmbedResizeWidth']) ? intval( $_POST['enableEmbedResizeWidth']) : 600;
372 $settings ['enableEmbedResizeHeight'] = isset( $_POST['enableEmbedResizeHeight']) ? intval( $_POST['enableEmbedResizeHeight']) : 550;
373 $settings ['pdf_custom_color_settings'] = isset( $_POST['pdf_custom_color_settings']) ? intval( $_POST['pdf_custom_color_settings']) : 0;
374 $settings ['turn_off_rating_help'] = isset( $_POST['turn_off_rating_help']) ? intval( $_POST['turn_off_rating_help']) : 0;
375 $settings ['turn_off_milestone'] = isset( $_POST['turn_off_milestone']) ? intval( $_POST['turn_off_milestone']) : 0;
376
377 $settings ['custom_color'] = isset( $_POST['custom_color']) ? $_POST['custom_color'] : '#333333';
378
379 // Pro will handle g_loading_animation settings and other
380 // Keep backward compatibility with old filter names
381 $settings = apply_filters( 'ep_general_settings_before_save', $settings, $_POST);
382 $settings = apply_filters( 'ep_settings_settings_before_save', $settings, $_POST);
383
384 update_option( EMBEDPRESS_PLG_NAME, $settings);
385
386 // Keep backward compatibility with old action names
387 do_action( 'ep_general_settings_after_save', $settings, $_POST);
388 do_action( 'ep_settings_settings_after_save', $settings, $_POST);
389 }
390
391 // Keep backward compatibility method
392 public function save_general_settings() {
393 return $this->save_settings_settings();
394 }
395
396 public function save_youtube_settings() {
397 $option_name = EMBEDPRESS_PLG_NAME.':youtube';
398 $settings = get_option( $option_name, []);
399 $settings['api_key'] = isset( $_POST['api_key']) ? sanitize_text_field( $_POST['api_key']) : 0;
400 $settings['pagesize'] = isset( $_POST['pagesize']) ? sanitize_text_field( $_POST['pagesize']) : 0;
401 $settings['start_time'] = isset( $_POST['start_time']) ? sanitize_text_field( $_POST['start_time']) : 0;
402 $settings['end_time'] = isset( $_POST['end_time']) ? sanitize_text_field( $_POST['end_time']) : 0;
403 $settings['autoplay'] = isset( $_POST['autoplay']) ? sanitize_text_field( $_POST['autoplay']) : '';
404 $settings['controls'] = isset( $_POST['controls']) ? sanitize_text_field( $_POST['controls']) : '';
405 $settings['fs'] = isset( $_POST['fs']) ? sanitize_text_field( $_POST['fs']) : '';
406 $settings['iv_load_policy'] = isset( $_POST['iv_load_policy']) ? sanitize_text_field( $_POST['iv_load_policy']) : 1;
407 $settings['color'] = isset( $_POST['color']) ? sanitize_text_field( $_POST['color']) : 'red';
408 $settings['rel'] = isset( $_POST['rel']) ? sanitize_text_field( $_POST['rel']) : 1;
409 $settings['license_key'] = 1; // backward compatibility
410
411 // Pro will handle g_loading_animation settings and other
412 $settings = apply_filters( 'ep_youtube_settings_before_save', $settings);
413 update_option( $option_name, $settings);
414 do_action( 'ep_youtube_settings_after_save', $settings);
415
416 }
417
418 public function save_wistia_settings() {
419 $option_name = EMBEDPRESS_PLG_NAME.':wistia';
420 $settings = get_option( $option_name, []);
421 $settings['start_time'] = isset( $_POST['start_time']) ? sanitize_text_field( $_POST['start_time']) : 0;
422 $settings['autoplay'] = isset( $_POST['autoplay']) ? sanitize_text_field( $_POST['autoplay']) : '';
423 $settings['display_fullscreen_button'] = isset( $_POST['display_fullscreen_button']) ? sanitize_text_field( $_POST['display_fullscreen_button']) : '';
424 $settings['small_play_button'] = isset( $_POST['small_play_button']) ? sanitize_text_field( $_POST['small_play_button']) : '';
425 $settings['player_color'] = isset( $_POST['player_color']) ? sanitize_text_field( $_POST['player_color']) : '';
426 $settings['plugin_resumable'] = isset( $_POST['plugin_resumable']) ? sanitize_text_field( $_POST['plugin_resumable']) : '';
427 $settings['plugin_focus'] = isset( $_POST['plugin_focus']) ? sanitize_text_field( $_POST['plugin_focus']) : '';
428 $settings['plugin_rewind'] = isset( $_POST['plugin_rewind']) ? sanitize_text_field( $_POST['plugin_rewind']) : '';
429 $settings['display_playbar'] = isset( $_POST['display_playbar']) ? sanitize_text_field( $_POST['display_playbar']) : 1;
430 $settings['plugin_rewind_time'] = isset( $_POST['plugin_rewind_time']) ? sanitize_text_field( $_POST['plugin_rewind_time']) : 10;
431 $settings['always_show_controls'] = isset( $_POST['always_show_controls']) ? sanitize_text_field( $_POST['always_show_controls']) : '';
432 $settings['license_key'] = 1; // backward compatibility
433 // Pro will handle g_loading_animation settings and other
434 $settings = apply_filters( 'ep_wistia_settings_before_save', $settings);
435 update_option( $option_name, $settings);
436 do_action( 'ep_wistia_settings_after_save', $settings);
437 }
438
439 public function save_vimeo_settings() {
440 $option_name = EMBEDPRESS_PLG_NAME.':vimeo';
441 $settings = get_option( $option_name, []);
442 $settings['start_time'] = isset( $_POST['start_time']) ? sanitize_text_field( $_POST['start_time']) : 0;
443 $settings['autoplay'] = isset( $_POST['autoplay']) ? sanitize_text_field( $_POST['autoplay']) : '';
444 $settings['color'] = isset( $_POST['color']) ? sanitize_text_field( $_POST['color']) : '#00adef';
445 $settings['display_title'] = isset( $_POST['display_title']) ? sanitize_text_field( $_POST['display_title']) : 1;
446 $settings['display_author'] = isset( $_POST['display_author']) ? sanitize_text_field( $_POST['display_author']) : 1;
447 $settings['display_avatar'] = isset( $_POST['display_avatar']) ? sanitize_text_field( $_POST['display_avatar']) : 1;
448 $settings['license_key'] = 1; // backward compatibility
449 // Pro will handle g_loading_animation settings and other
450 $settings = apply_filters( 'ep_vimeo_settings_before_save', $settings);
451 update_option( $option_name, $settings);
452 do_action( 'ep_vimeo_settings_after_save', $settings);
453 }
454
455 public function save_twitch_settings() {
456 $option_name = EMBEDPRESS_PLG_NAME.':twitch';
457 $settings = get_option( $option_name, []);
458 $settings['embedpress_pro_twitch_autoplay'] = isset( $_POST['autoplay']) ? sanitize_text_field( $_POST['autoplay']) : 'no';
459 $settings['embedpress_pro_fs'] = isset( $_POST['fs']) ? sanitize_text_field( $_POST['fs']) : 'yes';
460 $settings['start_time'] = isset( $_POST['start_time']) ? sanitize_text_field( $_POST['start_time']) : 0;
461 $settings['embedpress_pro_twitch_theme'] = isset( $_POST['theme']) ? sanitize_text_field( $_POST['theme']) : 'dark';
462 $settings['embedpress_pro_twitch_mute'] = isset( $_POST['mute']) ? sanitize_text_field( $_POST['mute']) : 'yes';
463 $settings['license_key'] = 1; // backward compatibility
464 // Pro will handle g_loading_animation settings and other
465 $settings = apply_filters( 'ep_twitch_settings_before_save', $settings);
466 update_option( $option_name, $settings);
467 do_action( 'ep_twitch_settings_after_save', $settings);
468 }
469
470 public function save_spotify_settings() {
471 $option_name = EMBEDPRESS_PLG_NAME.':spotify';
472 $settings = get_option( $option_name, []);
473 $settings['theme'] = isset( $_POST['spotify_theme']) ? sanitize_text_field( $_POST['spotify_theme']) : '1';
474 $settings['license_key'] = 1; // backward compatibility
475
476 $settings = apply_filters( 'ep_spotify_settings_before_save', $settings);
477 update_option( $option_name, $settings);
478 do_action( 'ep_spotify_settings_after_save', $settings);
479 return $settings;
480 }
481
482 public function save_custom_logo_settings() {
483 do_action( 'before_embedpress_branding_save');
484 $settings = (array) get_option( EMBEDPRESS_PLG_NAME, []);
485
486 // If checkbox is checked, it will be in POST data with value 'yes'
487 // If unchecked, it won't be in POST data, so we set it to 'no'
488 $settings['embedpress_document_powered_by'] = isset( $_POST['embedpress_document_powered_by'] ) ? sanitize_text_field( $_POST['embedpress_document_powered_by'] ) : 'no';
489
490 update_option( EMBEDPRESS_PLG_NAME, $settings);
491 do_action( 'after_embedpress_branding_save');
492
493 }
494
495 public function save_dailymotion_settings() {
496 $option_name = EMBEDPRESS_PLG_NAME.':dailymotion';
497 $settings = get_option( $option_name, []);
498 $settings['start_time'] = isset( $_POST['start_time']) ? sanitize_text_field( $_POST['start_time']) : 0;
499 $settings['visual'] = isset( $_POST['visual']) ? sanitize_text_field( $_POST['visual']) : '';
500 $settings['autoplay'] = isset( $_POST['autoplay']) ? sanitize_text_field( $_POST['autoplay']) : '';
501 $settings['play_on_mobile'] = isset( $_POST['play_on_mobile']) ? sanitize_text_field( $_POST['play_on_mobile']) : '';
502 $settings['color'] = isset( $_POST['color']) ? sanitize_text_field( $_POST['color']) : '#dd3333';
503 $settings['controls'] = isset( $_POST['controls']) ? sanitize_text_field( $_POST['controls']) : '';
504 $settings['video_info'] = isset( $_POST['video_info']) ? sanitize_text_field( $_POST['video_info']) : '';
505 $settings['mute'] = isset( $_POST['mute']) ? sanitize_text_field( $_POST['mute']) : '';
506 // Pro will handle g_loading_animation settings and other
507 $settings = apply_filters( 'ep_dailymotion_settings_before_save', $settings);
508 update_option( $option_name, $settings);
509 do_action( 'ep_dailymotion_settings_after_save', $settings);
510 }
511
512 public function save_soundcloud_settings() {
513 $option_name = EMBEDPRESS_PLG_NAME.':soundcloud';
514 $settings = get_option( $option_name, []);
515 $settings['visual'] = isset( $_POST['visual']) ? sanitize_text_field( $_POST['visual']) : '';
516 $settings['autoplay'] = isset( $_POST['autoplay']) ? sanitize_text_field( $_POST['autoplay']) : '';
517 $settings['play_on_mobile'] = isset( $_POST['play_on_mobile']) ? sanitize_text_field( $_POST['play_on_mobile']) : '';
518 $settings['share_button'] = isset( $_POST['share_button']) ? sanitize_text_field( $_POST['share_button']) : '';
519 $settings['comments'] = isset( $_POST['comments']) ? sanitize_text_field( $_POST['comments']) : '';
520 $settings['color'] = isset( $_POST['color']) ? sanitize_text_field( $_POST['color']) : '';
521 $settings['artwork'] = isset( $_POST['artwork']) ? sanitize_text_field( $_POST['artwork']) : '';
522 $settings['play_count'] = isset( $_POST['play_count']) ? sanitize_text_field( $_POST['play_count']) : '';
523 $settings['username'] = isset( $_POST['username']) ? sanitize_text_field( $_POST['username']) : '';
524
525 $settings['license_key'] = 1; // backward compatibility
526 // Pro will handle g_loading_animation settings and other
527 $settings = apply_filters( 'ep_soundcloud_settings_before_save', $settings);
528 update_option( $option_name, $settings);
529 do_action( 'ep_soundcloud_settings_after_save', $settings);
530 }
531
532 public function save_gcalendar_settings() {
533 $client_secret = !empty( $_POST['epgc_client_secret']) ? json_decode( wp_unslash( trim( $_POST['epgc_client_secret'])), true) : [];
534 $epgc_cache_time = !empty( $_POST['epgc_cache_time'] ) ? absint( $_POST['epgc_cache_time']) : 0;
535 $epgc_selected_calendar_ids = !empty( $_POST['epgc_selected_calendar_ids'] ) ? array_map( 'sanitize_text_field', $_POST['epgc_selected_calendar_ids']) : [];
536
537
538 $pretty_client_secret = '';
539 if ( !empty( $client_secret) ) {
540 $pretty_client_secret = $this->get_pretty_json_string( $client_secret);
541 }
542
543 update_option( 'epgc_client_secret', $pretty_client_secret);
544 update_option( 'epgc_cache_time', $epgc_cache_time);
545 update_option( 'epgc_selected_calendar_ids', $epgc_selected_calendar_ids);
546
547 }
548
549 public function save_opensea_settings() {
550 $option_name = EMBEDPRESS_PLG_NAME.':opensea';
551 $settings = get_option( $option_name, []);
552 $settings['api_key'] = isset( $_POST['api_key']) ? sanitize_text_field( $_POST['api_key']) : 0;
553 $settings['limit'] = isset( $_POST['limit']) ? sanitize_text_field( $_POST['limit']) : 0;
554 $settings['orderby'] = isset( $_POST['orderby']) ? sanitize_text_field( $_POST['orderby']) : 0;
555
556 $settings['license_key'] = 1; // backward compatibility
557
558 // Pro will handle g_loading_animation settings and other
559 $settings = apply_filters( 'ep_opensea_settings_before_save', $settings);
560 update_option( $option_name, $settings);
561 do_action( 'ep_opensea_settings_after_save', $settings);
562 }
563
564
565 function get_pretty_json_string($array) {
566 return str_replace(" ", " ", json_encode($array, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
567 }
568
569 /**
570 * AJAX handler for saving global brand image
571 */
572 public function save_global_brand_image() {
573 // Verify nonce for security
574 if (!wp_verify_nonce($_POST['nonce'], 'embedpress_ajax_nonce')) {
575 wp_die('Security check failed');
576 }
577
578 // Check user capabilities
579 if (!current_user_can('manage_options')) {
580 wp_die('Insufficient permissions');
581 }
582
583 $logo_url = isset($_POST['logo_url']) ? esc_url_raw($_POST['logo_url']) : '';
584 $logo_id = isset($_POST['logo_id']) ? intval($_POST['logo_id']) : '';
585
586 // Save global brand settings
587 $global_brand_settings = [
588 'logo_url' => $logo_url,
589 'logo_id' => $logo_id,
590 ];
591
592 $updated = update_option(EMBEDPRESS_PLG_NAME . ':global_brand', $global_brand_settings);
593
594 // If global brand image is being set, auto-enable branding for providers without custom logos
595 if (!empty($logo_url)) {
596 $this->auto_enable_global_branding($logo_url, $logo_id);
597 }
598
599 if ($updated !== false) {
600 wp_send_json_success([
601 'message' => 'Global brand image saved successfully',
602 'logo_url' => $logo_url,
603 'logo_id' => $logo_id
604 ]);
605 } else {
606 wp_send_json_error('Failed to save global brand image');
607 }
608 }
609
610 /**
611 * AJAX handler for dismissing UI elements (banners, popups, etc.)
612 */
613 public function dismiss_element() {
614 // Verify nonce for security
615 if (!wp_verify_nonce($_POST['nonce'], 'embedpress_ajax_nonce')) {
616 wp_die('Security check failed');
617 }
618
619 // Check user capabilities
620 if (!current_user_can('manage_options')) {
621 wp_die('Insufficient permissions');
622 }
623
624 $element_type = isset($_POST['element_type']) ? sanitize_text_field($_POST['element_type']) : '';
625
626 // Define valid dismiss types and their corresponding option names
627 $valid_dismiss_types = [
628 'main_banner' => 'embedpress_main_banner_dismissed',
629 'hub_popup' => 'embedpress_hub_popup_dismissed',
630 'popup_banner' => 'embedpress_popup_dismissed', // Legacy support
631 ];
632
633 if (array_key_exists($element_type, $valid_dismiss_types)) {
634 $option_name = $valid_dismiss_types[$element_type];
635 update_option($option_name, true);
636
637 // Store current plugin version when hub_popup is dismissed
638 // This ensures popup shows again on next version update
639 if ($element_type === 'hub_popup') {
640 update_option('embedpress_last_popup_version', EMBEDPRESS_VERSION);
641 }
642
643 wp_send_json_success([
644 'message' => ucfirst(str_replace('_', ' ', $element_type)) . ' dismissed successfully',
645 'element_type' => $element_type,
646 'option_name' => $option_name
647 ]);
648 }
649
650 wp_send_json_error([
651 'message' => 'Invalid element type: ' . $element_type,
652 'valid_types' => array_keys($valid_dismiss_types)
653 ]);
654 }
655
656 /**
657 * AJAX handler for dismissing feature notices
658 */
659 public function dismiss_feature_notice() {
660 // Verify nonce for security
661 if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'embedpress_feature_notice_nonce')) {
662 wp_send_json_error(['message' => 'Security check failed']);
663 }
664
665 // Check user capabilities
666 if (!current_user_can('manage_options')) {
667 wp_send_json_error(['message' => 'Insufficient permissions']);
668 }
669
670 $notice_id = isset($_POST['notice_id']) ? sanitize_text_field($_POST['notice_id']) : '';
671
672 if (empty($notice_id)) {
673 wp_send_json_error(['message' => 'Notice ID is required']);
674 }
675
676 // Define valid notice types and their corresponding option names
677 $valid_notices = [
678 'analytics' => 'embedpress_feature_notice_analytics_dismissed',
679 ];
680
681 if (array_key_exists($notice_id, $valid_notices)) {
682 $option_name = $valid_notices[$notice_id];
683 update_option($option_name, true);
684
685 wp_send_json_success([
686 'message' => 'Feature notice dismissed successfully',
687 'notice_id' => $notice_id,
688 'option_name' => $option_name
689 ]);
690 }
691
692 wp_send_json_error([
693 'message' => 'Invalid notice ID: ' . $notice_id,
694 'valid_notices' => array_keys($valid_notices)
695 ]);
696 }
697
698 /**
699 * Auto-enable branding for all providers that don't have custom logos
700 */
701 private function auto_enable_global_branding($logo_url, $logo_id) {
702 $providers = ['youtube', 'vimeo', 'wistia', 'twitch', 'dailymotion', 'document'];
703
704 foreach ($providers as $provider) {
705 $option_name = EMBEDPRESS_PLG_NAME . ':' . $provider;
706 $settings = get_option($option_name, []);
707
708 // Only auto-enable if provider doesn't have a custom logo set
709 $has_custom_logo = isset($settings['logo_url']) && !empty($settings['logo_url']);
710
711 if (!$has_custom_logo) {
712 // Enable branding but don't set logo_url/logo_id - let the template logic handle global fallback
713 $settings['branding'] = 'yes';
714 update_option($option_name, $settings);
715 }
716 }
717 }
718
719 /**
720 * Render the onboarding wizard page
721 */
722 public function render_onboarding_page() {
723 $settings = (array) get_option( EMBEDPRESS_PLG_NAME, [] );
724 $elements = (array) get_option( EMBEDPRESS_PLG_NAME . ':elements', [] );
725 $pro_active = apply_filters( 'embedpress/is_allow_rander', false );
726
727 $onboarding_data = [
728 'ajaxUrl' => admin_url( 'admin-ajax.php' ),
729 'nonce' => wp_create_nonce( 'embedpress_onboarding_nonce' ),
730 'settingsUrl' => admin_url( 'admin.php?page=' . $this->page_slug . '&page_type=settings' ),
731 'dashboardUrl' => admin_url( 'admin.php?page=' . $this->page_slug ),
732 'proActive' => $pro_active,
733 'upgradeUrl' => 'https://wpdeveloper.com/in/upgrade-embedpress',
734 'settings' => $settings,
735 'elements' => $elements,
736 'assetsUrl' => EMBEDPRESS_URL_ASSETS,
737 'analyticsTracking' => get_option( 'embedpress_analytics_tracking_enabled', true ),
738 ];
739
740 // Enqueue onboarding assets explicitly
741 wp_enqueue_script( 'embedpress-onboarding' );
742 wp_enqueue_style( 'embedpress-onboarding-css' );
743 wp_localize_script( 'embedpress-onboarding', 'embedpressOnboardingData', $onboarding_data );
744
745 echo '<div class="embedpress-onboarding-wrapper">';
746 echo '<div id="embedpress-onboarding-root"></div>';
747 echo '</div>';
748 }
749
750 /**
751 * AJAX handler for saving onboarding wizard settings
752 */
753 public function save_onboarding_settings() {
754 if ( ! current_user_can( 'manage_options' ) ) {
755 wp_send_json_error( [ 'message' => 'Insufficient permissions.' ] );
756 }
757
758 if ( empty( $_POST['nonce'] ) || ! wp_verify_nonce( $_POST['nonce'], 'embedpress_onboarding_nonce' ) ) {
759 wp_send_json_error( [ 'message' => 'Security check failed.' ] );
760 }
761
762 $settings = (array) get_option( EMBEDPRESS_PLG_NAME, [] );
763 $elements = (array) get_option( EMBEDPRESS_PLG_NAME . ':elements', [] );
764
765 // Element toggles — enable/disable all blocks/widgets at once
766 $all_gutenberg_blocks = [
767 'embedpress', 'document', 'embedpress-pdf', 'embedpress-calendar',
768 'youtube-block', 'google-docs-block', 'google-slides-block',
769 'google-sheets-block', 'google-forms-block', 'google-drawings-block',
770 'google-maps-block', 'twitch-block', 'wistia-block', 'vimeo-block',
771 ];
772 $all_elementor_widgets = [
773 'embedpress', 'embedpress-document', 'embedpress-pdf', 'embedpress-calendar',
774 ];
775
776 if ( isset( $_POST['gutenberg_block'] ) ) {
777 if ( sanitize_text_field( $_POST['gutenberg_block'] ) === '1' ) {
778 foreach ( $all_gutenberg_blocks as $block ) {
779 $elements['gutenberg'][ $block ] = $block;
780 }
781 } else {
782 $elements['gutenberg'] = [];
783 }
784 }
785 if ( isset( $_POST['elementor_widget'] ) ) {
786 if ( sanitize_text_field( $_POST['elementor_widget'] ) === '1' ) {
787 foreach ( $all_elementor_widgets as $widget ) {
788 $elements['elementor'][ $widget ] = $widget;
789 }
790 } else {
791 $elements['elementor'] = [];
792 }
793 }
794
795 // Global settings toggles
796 if ( isset( $_POST['analytics_tracking'] ) ) {
797 update_option( 'embedpress_analytics_tracking_enabled', intval( $_POST['analytics_tracking'] ) ? true : false );
798 }
799 if ( isset( $_POST['g_lazyload'] ) ) {
800 $settings['g_lazyload'] = intval( $_POST['g_lazyload'] );
801 }
802 if ( isset( $_POST['embedpress_document_powered_by'] ) ) {
803 $settings['embedpress_document_powered_by'] = intval( $_POST['embedpress_document_powered_by'] ) ? 'yes' : 'no';
804 }
805 // Pro feature toggles
806 if ( isset( $_POST['social_share'] ) ) {
807 $settings['social_share'] = intval( $_POST['social_share'] );
808 }
809 if ( isset( $_POST['custom_branding'] ) ) {
810 $settings['custom_branding'] = intval( $_POST['custom_branding'] );
811 }
812 if ( isset( $_POST['custom_ads'] ) ) {
813 $settings['custom_ads'] = intval( $_POST['custom_ads'] );
814 }
815 if ( isset( $_POST['content_protection'] ) ) {
816 $settings['content_protection'] = intval( $_POST['content_protection'] );
817 }
818 // Mark onboarding as complete
819 if ( ! empty( $_POST['complete'] ) ) {
820 update_option( 'embedpress_onboarding_complete', true );
821 }
822
823 // Data consent — enable usage tracking via WPInsights
824 if ( ! empty( $_POST['data_consent'] ) && ! get_option( 'embedpress_data_consent', false ) ) {
825 update_option( 'embedpress_data_consent', true );
826
827 $allow_tracking = get_option( 'wpins_allow_tracking', [] );
828 if ( ! is_array( $allow_tracking ) ) {
829 $allow_tracking = [];
830 }
831 $allow_tracking['embedpress'] = 'embedpress';
832 update_option( 'wpins_allow_tracking', $allow_tracking );
833
834 // Suppress the legacy opt-in notice now that consent was captured via the wizard
835 $block_notice = get_option( 'wpins_block_notice', [] );
836 if ( ! is_array( $block_notice ) ) {
837 $block_notice = [];
838 }
839 $block_notice['embedpress'] = 'embedpress';
840 update_option( 'wpins_block_notice', $block_notice );
841
842 // Register the daily cron and fire an initial payload so data
843 // reaches wpinsight.com without waiting for the first cron tick.
844 $tracker = EmbedPress_Plugin_Usage_Tracker::get_instance( EMBEDPRESS_FILE, [
845 'opt_in' => true,
846 'goodbye_form' => true,
847 'item_id' => '98ba0ac16a4f7b3b940d',
848 ] );
849 $tracker->schedule_tracking();
850 $tracker->do_tracking( true );
851 }
852
853 update_option( EMBEDPRESS_PLG_NAME, $settings );
854 update_option( EMBEDPRESS_PLG_NAME . ':elements', $elements );
855
856 wp_send_json_success( [ 'message' => 'Onboarding settings saved.' ] );
857 }
858
859 /**
860 * Reorder submenu items to put Analytics 2nd and License last
861 */
862 public function reorder_submenu_items() {
863 global $submenu;
864
865 // Check if our menu exists
866 if (!isset($submenu[$this->page_slug])) {
867 return;
868 }
869
870 $license_item = null;
871 $analytics_item = null;
872 $reordered_menu = [];
873
874 // Find and extract License and Analytics items
875 foreach ($submenu[$this->page_slug] as $item) {
876 if (isset($item[0])) {
877 if ($item[0] === __('License', 'embedpress')) {
878 $license_item = $item;
879 continue; // Skip adding to reordered menu
880 } elseif ($item[0] === __('Analytics', 'embedpress')) {
881 $analytics_item = $item;
882 continue; // Skip adding to reordered menu
883 }
884 }
885 $reordered_menu[] = $item;
886 }
887
888 // Rebuild the menu with proper order
889 $final_menu = [];
890
891 // Add first item (Dashboard)
892 if (!empty($reordered_menu[0])) {
893 $final_menu[] = $reordered_menu[0];
894 }
895
896 // Add Analytics as 2nd item if it exists
897 if ($analytics_item !== null) {
898 $final_menu[] = $analytics_item;
899 }
900
901 // Add remaining items (except first which we already added)
902 for ($i = 1; $i < count($reordered_menu); $i++) {
903 $final_menu[] = $reordered_menu[$i];
904 }
905
906 // Add License at the end if it exists
907 if ($license_item !== null) {
908 $final_menu[] = $license_item;
909 }
910
911 // Replace the submenu with reordered items
912 $submenu[$this->page_slug] = $final_menu;
913 }
914 }
915