PluginProbe ʕ •ᴥ•ʔ
EmbedPress – PDF Embedder, 3D PDF FlipBook, Google Reviews, YouTube Videos, Upload & Embed PDF documents / 4.5.4
EmbedPress – PDF Embedder, 3D PDF FlipBook, Google Reviews, YouTube Videos, Upload & Embed PDF documents v4.5.4
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 1 month ago EmbedpressSettings.php 1 month ago
EmbedpressSettings.php
1001 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', '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 // Player & Engagement submenu — registered only when Pro is NOT active.
254 // When Pro IS active, Pro plugin's Admin_Page registers the real React
255 // page on the SAME slug (embedpress-player-engagement), so saved bookmarks
256 // and links keep working across the freemium boundary.
257 if ( ! apply_filters('embedpress/is_allow_rander', false) ) {
258 add_submenu_page(
259 $this->page_slug,
260 __('EmbedPress Player & Engagement', 'embedpress'),
261 __('Player & Engagement', 'embedpress'),
262 'manage_options',
263 'embedpress-player-engagement',
264 [ $this, 'render_player_engagement_page' ]
265 );
266 }
267
268 // Register Setup Wizard submenu page
269 add_submenu_page( $this->page_slug, __('EmbedPress Setup Wizard', 'embedpress'), __('Setup Wizard', 'embedpress'), 'manage_options', 'embedpress-onboarding',
270 [ $this, 'render_onboarding_page' ] );
271
272 // Add admin footer script to handle menu highlighting
273 add_action('admin_footer', [$this, 'admin_menu_highlight_script']);
274
275 // Pro badge styling for upsell submenu items
276 add_action('admin_head', function () {
277 echo '<style>
278 #adminmenu .ep-menu-pro-badge {
279 display: inline-block;
280 margin-left: 6px;
281 padding: 1px 6px;
282 font-size: 9px;
283 font-weight: 700;
284 line-height: 1.4;
285 letter-spacing: 0.4px;
286 color: #fff;
287 background: linear-gradient(90deg, #5b4e96 0%, #8a72d8 100%);
288 border-radius: 3px;
289 vertical-align: middle;
290 }
291 </style>';
292 });
293
294 // Add filter to reorder menu items - License should be last
295 add_filter('admin_menu', [$this, 'reorder_submenu_items'], 999);
296 }
297
298
299 public function admin_menu_highlight_script() {
300 // Only load on EmbedPress admin pages
301 $current_page = isset($_GET['page']) ? sanitize_text_field($_GET['page']) : '';
302 if ($current_page !== $this->page_slug) {
303 return;
304 }
305
306 $page_type = isset($_GET['page_type']) ? sanitize_text_field($_GET['page_type']) : '';
307 // Fixed: Evaluate PHP filter on server-side before passing to JavaScript
308 $is_pro_active = apply_filters('embedpress/is_allow_rander', false);
309
310 ?>
311 <script type="text/javascript">
312 /* EmbedPress Admin Menu Highlight Script - Fixed apply_filters issue */
313 jQuery(document).ready(function($) {
314 // Remove current highlighting
315 $('#adminmenu .wp-submenu li').removeClass('current');
316 $('#adminmenu .wp-submenu a').removeClass('current');
317
318 var pageType = '<?php echo esc_js($page_type); ?>';
319 var isProActive = <?php echo $is_pro_active ? 'true' : 'false'; ?>;
320 var menuSelector = '';
321
322 // Map page types to menu selectors
323 switch(pageType) {
324 case 'settings':
325 menuSelector = 'a[href*="page_type=settings"]';
326 break;
327 case 'shortcode':
328 menuSelector = 'a[href*="page_type=shortcode"]';
329 break;
330 case 'sources':
331 menuSelector = 'a[href*="page_type=sources"]';
332 break;
333 case 'elements':
334 menuSelector = 'a[href*="page_type=elements"]';
335 break;
336 case 'custom-logo':
337 menuSelector = 'a[href*="page_type=custom-logo"]';
338 break;
339 case 'ads':
340 menuSelector = 'a[href*="page_type=ads"]';
341 break;
342 case 'license':
343 menuSelector = 'a[href*="page_type=license"]';
344 break;
345 default:
346 // Default to Dashboard (no page_type or hub)
347 menuSelector = 'a[href="admin.php?page=<?php echo esc_js($this->page_slug); ?>"]';
348 break;
349 }
350
351 // Highlight the correct menu item
352 if (menuSelector) {
353 var $menuItem = $('#adminmenu .wp-submenu ' + menuSelector);
354 if ($menuItem.length) {
355 $menuItem.addClass('current').parent().addClass('current');
356 }
357 }
358 });
359 </script>
360 <?php
361 }
362
363
364 public function render_settings_page( ) {
365 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;
366
367 $page_slug = $this->page_slug; // make this available for included template
368 $template = !empty( $_GET['page_type'] ) ? sanitize_file_name( $_GET['page_type']) : 'hub';
369
370 $nonce_field = wp_nonce_field('ep_settings_nonce', 'ep_settings_nonce', true, false);
371 $ep_page = admin_url('admin.php?page='.$this->page_slug);
372 $gen_menu_template_names = apply_filters('ep_general_menu_tmpl_names', ['settings', 'shortcode',]);
373 $platform_menu_template_names = apply_filters('ep_platform_menu_tmpl_names', [ 'youtube', 'vimeo', 'wistia', 'twitch','dailymotion', 'soundcloud' ,'spotify','google-calendar','opensea']);
374 $brand_menu_template_names = apply_filters('ep_brand_menu_templates', ['custom-logo', 'branding',]);
375 $pro_active = apply_filters('embedpress/is_allow_rander', false);
376 $coming_soon = "<span class='ep-coming-soon'>". esc_html__( '(Coming soon)', 'embedpress'). "</span>";
377 $success_message = esc_html__( "Settings Updated", "embedpress" );
378 $error_message = esc_html__( "Ops! Something went wrong.", "embedpress" );
379 include_once EMBEDPRESS_SETTINGS_PATH . 'templates/main-template.php';
380 }
381
382 /**
383 * Render the free Player & Engagement landing page on the
384 * `embedpress-player-engagement` slug — same slug Pro's Admin_Page uses.
385 *
386 * The same `custom-player.build.js` React app mounts here. We localize
387 * `isProActive: false` so the app renders its UpgradePanel in the body
388 * instead of fetching engagement data from REST endpoints that don't
389 * exist on free.
390 */
391 public function render_player_engagement_page() {
392 if ( ! current_user_can( 'manage_options' ) ) {
393 return;
394 }
395
396 // AssetManager auto-enqueues custom-player.build.js + .css on this
397 // page slug. Just feed the React app its localize blob, matching
398 // the keys Pro's Admin_Page::render_page() uses.
399 wp_localize_script( 'embedpress-custom-player', 'embedpressCustomPlayerData', [
400 'restUrl' => esc_url_raw( rest_url( 'embedpress/v1/' ) ),
401 'nonce' => wp_create_nonce( 'wp_rest' ),
402 'adminUrl' => esc_url_raw( admin_url( 'admin.php' ) ),
403 'assetsUrl' => defined( 'EMBEDPRESS_URL_ASSETS' ) ? EMBEDPRESS_URL_ASSETS : '',
404 'isProActive' => false,
405 ] );
406
407 include_once EMBEDPRESS_SETTINGS_PATH . 'templates/player-engagement.php';
408 }
409
410 public function save_settings() {
411 // needs to check for ajax and return response accordingly.
412 if ( !empty( $_POST['ep_settings_nonce']) && wp_verify_nonce( $_POST['ep_settings_nonce'], 'ep_settings_nonce') ) {
413 $submit_type = !empty( $_POST['submit'] ) ? $_POST['submit'] : '';
414 $save_handler_method = "save_{$submit_type}_settings";
415 do_action( "before_{$save_handler_method}");
416 do_action( "before_embedpress_settings_save");
417 if ( method_exists( $this, $save_handler_method ) ) {
418 $this->$save_handler_method();
419 }
420 do_action( "after_embedpress_settings_save");
421 $return_url = isset( $_SERVER['HTTP_REFERER'] ) ? $_SERVER['HTTP_REFERER'] : admin_url();
422 $return_url = add_query_arg( 'success', 1, $return_url );
423 if ( wp_doing_ajax() ) {
424 wp_send_json_success();
425 }
426 wp_safe_redirect( $return_url);
427 exit();
428 }
429 }
430
431 public function save_settings_settings() {
432 $settings = (array) get_option( EMBEDPRESS_PLG_NAME, []);
433 $settings ['enableEmbedResizeWidth'] = isset( $_POST['enableEmbedResizeWidth']) ? intval( $_POST['enableEmbedResizeWidth']) : 600;
434 $settings ['enableEmbedResizeHeight'] = isset( $_POST['enableEmbedResizeHeight']) ? intval( $_POST['enableEmbedResizeHeight']) : 550;
435 $settings ['pdf_custom_color_settings'] = isset( $_POST['pdf_custom_color_settings']) ? intval( $_POST['pdf_custom_color_settings']) : 0;
436 $settings ['turn_off_rating_help'] = isset( $_POST['turn_off_rating_help']) ? intval( $_POST['turn_off_rating_help']) : 0;
437 $settings ['turn_off_milestone'] = isset( $_POST['turn_off_milestone']) ? intval( $_POST['turn_off_milestone']) : 0;
438
439 $settings ['custom_color'] = isset( $_POST['custom_color']) ? $_POST['custom_color'] : '#333333';
440
441 // Pro will handle g_loading_animation settings and other
442 // Keep backward compatibility with old filter names
443 $settings = apply_filters( 'ep_general_settings_before_save', $settings, $_POST);
444 $settings = apply_filters( 'ep_settings_settings_before_save', $settings, $_POST);
445
446 update_option( EMBEDPRESS_PLG_NAME, $settings);
447
448 // Keep backward compatibility with old action names
449 do_action( 'ep_general_settings_after_save', $settings, $_POST);
450 do_action( 'ep_settings_settings_after_save', $settings, $_POST);
451 }
452
453 // Keep backward compatibility method
454 public function save_general_settings() {
455 return $this->save_settings_settings();
456 }
457
458 public function save_youtube_settings() {
459 $option_name = EMBEDPRESS_PLG_NAME.':youtube';
460 $settings = get_option( $option_name, []);
461 $settings['api_key'] = isset( $_POST['api_key']) ? sanitize_text_field( $_POST['api_key']) : 0;
462 $settings['pagesize'] = isset( $_POST['pagesize']) ? sanitize_text_field( $_POST['pagesize']) : 0;
463 $settings['start_time'] = isset( $_POST['start_time']) ? sanitize_text_field( $_POST['start_time']) : 0;
464 $settings['end_time'] = isset( $_POST['end_time']) ? sanitize_text_field( $_POST['end_time']) : 0;
465 $settings['autoplay'] = isset( $_POST['autoplay']) ? sanitize_text_field( $_POST['autoplay']) : '';
466 $settings['controls'] = isset( $_POST['controls']) ? sanitize_text_field( $_POST['controls']) : '';
467 $settings['fs'] = isset( $_POST['fs']) ? sanitize_text_field( $_POST['fs']) : '';
468 $settings['iv_load_policy'] = isset( $_POST['iv_load_policy']) ? sanitize_text_field( $_POST['iv_load_policy']) : 1;
469 $settings['color'] = isset( $_POST['color']) ? sanitize_text_field( $_POST['color']) : 'red';
470 $settings['rel'] = isset( $_POST['rel']) ? sanitize_text_field( $_POST['rel']) : 1;
471 $settings['license_key'] = 1; // backward compatibility
472
473 // Pro will handle g_loading_animation settings and other
474 $settings = apply_filters( 'ep_youtube_settings_before_save', $settings);
475 update_option( $option_name, $settings);
476 do_action( 'ep_youtube_settings_after_save', $settings);
477
478 }
479
480 public function save_wistia_settings() {
481 $option_name = EMBEDPRESS_PLG_NAME.':wistia';
482 $settings = get_option( $option_name, []);
483 $settings['start_time'] = isset( $_POST['start_time']) ? sanitize_text_field( $_POST['start_time']) : 0;
484 $settings['autoplay'] = isset( $_POST['autoplay']) ? sanitize_text_field( $_POST['autoplay']) : '';
485 $settings['display_fullscreen_button'] = isset( $_POST['display_fullscreen_button']) ? sanitize_text_field( $_POST['display_fullscreen_button']) : '';
486 $settings['small_play_button'] = isset( $_POST['small_play_button']) ? sanitize_text_field( $_POST['small_play_button']) : '';
487 $settings['player_color'] = isset( $_POST['player_color']) ? sanitize_text_field( $_POST['player_color']) : '';
488 $settings['plugin_resumable'] = isset( $_POST['plugin_resumable']) ? sanitize_text_field( $_POST['plugin_resumable']) : '';
489 $settings['plugin_focus'] = isset( $_POST['plugin_focus']) ? sanitize_text_field( $_POST['plugin_focus']) : '';
490 $settings['plugin_rewind'] = isset( $_POST['plugin_rewind']) ? sanitize_text_field( $_POST['plugin_rewind']) : '';
491 $settings['display_playbar'] = isset( $_POST['display_playbar']) ? sanitize_text_field( $_POST['display_playbar']) : 1;
492 $settings['plugin_rewind_time'] = isset( $_POST['plugin_rewind_time']) ? sanitize_text_field( $_POST['plugin_rewind_time']) : 10;
493 $settings['always_show_controls'] = isset( $_POST['always_show_controls']) ? sanitize_text_field( $_POST['always_show_controls']) : '';
494 $settings['license_key'] = 1; // backward compatibility
495 // Pro will handle g_loading_animation settings and other
496 $settings = apply_filters( 'ep_wistia_settings_before_save', $settings);
497 update_option( $option_name, $settings);
498 do_action( 'ep_wistia_settings_after_save', $settings);
499 }
500
501 public function save_vimeo_settings() {
502 $option_name = EMBEDPRESS_PLG_NAME.':vimeo';
503 $settings = get_option( $option_name, []);
504 $settings['start_time'] = isset( $_POST['start_time']) ? sanitize_text_field( $_POST['start_time']) : 0;
505 $settings['autoplay'] = isset( $_POST['autoplay']) ? sanitize_text_field( $_POST['autoplay']) : '';
506 $settings['color'] = isset( $_POST['color']) ? sanitize_text_field( $_POST['color']) : '#00adef';
507 $settings['display_title'] = isset( $_POST['display_title']) ? sanitize_text_field( $_POST['display_title']) : 1;
508 $settings['display_author'] = isset( $_POST['display_author']) ? sanitize_text_field( $_POST['display_author']) : 1;
509 $settings['display_avatar'] = isset( $_POST['display_avatar']) ? sanitize_text_field( $_POST['display_avatar']) : 1;
510 $settings['license_key'] = 1; // backward compatibility
511 // Pro will handle g_loading_animation settings and other
512 $settings = apply_filters( 'ep_vimeo_settings_before_save', $settings);
513 update_option( $option_name, $settings);
514 do_action( 'ep_vimeo_settings_after_save', $settings);
515 }
516
517 public function save_twitch_settings() {
518 $option_name = EMBEDPRESS_PLG_NAME.':twitch';
519 $settings = get_option( $option_name, []);
520 $settings['embedpress_pro_twitch_autoplay'] = isset( $_POST['autoplay']) ? sanitize_text_field( $_POST['autoplay']) : 'no';
521 $settings['embedpress_pro_fs'] = isset( $_POST['fs']) ? sanitize_text_field( $_POST['fs']) : 'yes';
522 $settings['start_time'] = isset( $_POST['start_time']) ? sanitize_text_field( $_POST['start_time']) : 0;
523 $settings['embedpress_pro_twitch_theme'] = isset( $_POST['theme']) ? sanitize_text_field( $_POST['theme']) : 'dark';
524 $settings['embedpress_pro_twitch_mute'] = isset( $_POST['mute']) ? sanitize_text_field( $_POST['mute']) : 'yes';
525 $settings['license_key'] = 1; // backward compatibility
526 // Pro will handle g_loading_animation settings and other
527 $settings = apply_filters( 'ep_twitch_settings_before_save', $settings);
528 update_option( $option_name, $settings);
529 do_action( 'ep_twitch_settings_after_save', $settings);
530 }
531
532 public function save_spotify_settings() {
533 $option_name = EMBEDPRESS_PLG_NAME.':spotify';
534 $settings = get_option( $option_name, []);
535 $settings['theme'] = isset( $_POST['spotify_theme']) ? sanitize_text_field( $_POST['spotify_theme']) : '1';
536 $settings['license_key'] = 1; // backward compatibility
537
538 $settings = apply_filters( 'ep_spotify_settings_before_save', $settings);
539 update_option( $option_name, $settings);
540 do_action( 'ep_spotify_settings_after_save', $settings);
541 return $settings;
542 }
543
544 public function save_custom_logo_settings() {
545 do_action( 'before_embedpress_branding_save');
546 $settings = (array) get_option( EMBEDPRESS_PLG_NAME, []);
547
548 // If checkbox is checked, it will be in POST data with value 'yes'
549 // If unchecked, it won't be in POST data, so we set it to 'no'
550 $settings['embedpress_document_powered_by'] = isset( $_POST['embedpress_document_powered_by'] ) ? sanitize_text_field( $_POST['embedpress_document_powered_by'] ) : 'no';
551
552 update_option( EMBEDPRESS_PLG_NAME, $settings);
553 do_action( 'after_embedpress_branding_save');
554
555 }
556
557 public function save_dailymotion_settings() {
558 $option_name = EMBEDPRESS_PLG_NAME.':dailymotion';
559 $settings = get_option( $option_name, []);
560 $settings['start_time'] = isset( $_POST['start_time']) ? sanitize_text_field( $_POST['start_time']) : 0;
561 $settings['visual'] = isset( $_POST['visual']) ? sanitize_text_field( $_POST['visual']) : '';
562 $settings['autoplay'] = isset( $_POST['autoplay']) ? sanitize_text_field( $_POST['autoplay']) : '';
563 $settings['play_on_mobile'] = isset( $_POST['play_on_mobile']) ? sanitize_text_field( $_POST['play_on_mobile']) : '';
564 $settings['color'] = isset( $_POST['color']) ? sanitize_text_field( $_POST['color']) : '#dd3333';
565 $settings['controls'] = isset( $_POST['controls']) ? sanitize_text_field( $_POST['controls']) : '';
566 $settings['video_info'] = isset( $_POST['video_info']) ? sanitize_text_field( $_POST['video_info']) : '';
567 $settings['mute'] = isset( $_POST['mute']) ? sanitize_text_field( $_POST['mute']) : '';
568 // Pro will handle g_loading_animation settings and other
569 $settings = apply_filters( 'ep_dailymotion_settings_before_save', $settings);
570 update_option( $option_name, $settings);
571 do_action( 'ep_dailymotion_settings_after_save', $settings);
572 }
573
574 public function save_soundcloud_settings() {
575 $option_name = EMBEDPRESS_PLG_NAME.':soundcloud';
576 $settings = get_option( $option_name, []);
577 $settings['visual'] = isset( $_POST['visual']) ? sanitize_text_field( $_POST['visual']) : '';
578 $settings['autoplay'] = isset( $_POST['autoplay']) ? sanitize_text_field( $_POST['autoplay']) : '';
579 $settings['play_on_mobile'] = isset( $_POST['play_on_mobile']) ? sanitize_text_field( $_POST['play_on_mobile']) : '';
580 $settings['share_button'] = isset( $_POST['share_button']) ? sanitize_text_field( $_POST['share_button']) : '';
581 $settings['comments'] = isset( $_POST['comments']) ? sanitize_text_field( $_POST['comments']) : '';
582 $settings['color'] = isset( $_POST['color']) ? sanitize_text_field( $_POST['color']) : '';
583 $settings['artwork'] = isset( $_POST['artwork']) ? sanitize_text_field( $_POST['artwork']) : '';
584 $settings['play_count'] = isset( $_POST['play_count']) ? sanitize_text_field( $_POST['play_count']) : '';
585 $settings['username'] = isset( $_POST['username']) ? sanitize_text_field( $_POST['username']) : '';
586
587 $settings['license_key'] = 1; // backward compatibility
588 // Pro will handle g_loading_animation settings and other
589 $settings = apply_filters( 'ep_soundcloud_settings_before_save', $settings);
590 update_option( $option_name, $settings);
591 do_action( 'ep_soundcloud_settings_after_save', $settings);
592 }
593
594 public function save_gcalendar_settings() {
595 $epgc_cache_time = !empty( $_POST['epgc_cache_time'] ) ? absint( $_POST['epgc_cache_time']) : 0;
596 $epgc_selected_calendar_ids = !empty( $_POST['epgc_selected_calendar_ids'] ) ? array_map( 'sanitize_text_field', $_POST['epgc_selected_calendar_ids']) : [];
597
598 // New two-field form: Client ID + Client Secret. Legacy: full JSON pasted
599 // into epgc_client_secret. Accept both so sites upgrading mid-stream still save.
600 $posted_client_id = isset( $_POST['epgc_client_id'] ) ? sanitize_text_field( wp_unslash( $_POST['epgc_client_id'] ) ) : '';
601 $posted_client_secret = isset( $_POST['epgc_client_secret_value'] ) ? trim( wp_unslash( $_POST['epgc_client_secret_value'] ) ) : '';
602 $posted_legacy_json = isset( $_POST['epgc_client_secret'] ) ? trim( wp_unslash( $_POST['epgc_client_secret'] ) ) : '';
603
604 $pretty_client_secret = '';
605
606 if ( $posted_client_id !== '' || $posted_client_secret !== '' ) {
607 // Two-field form path. Preserve the existing secret if the field was
608 // left blank (the UI surfaces "Stored — leave blank to keep").
609 $existing = json_decode( get_option( 'epgc_client_secret', '' ), true );
610 $effective_secret = $posted_client_secret !== ''
611 ? $posted_client_secret
612 : ( isset( $existing['web']['client_secret'] ) ? $existing['web']['client_secret'] : '' );
613
614 if ( $posted_client_id !== '' && $effective_secret !== '' ) {
615 $pretty_client_secret = $this->get_pretty_json_string( [
616 'web' => [
617 'client_id' => $posted_client_id,
618 'client_secret' => $effective_secret,
619 'redirect_uris' => [ admin_url( 'admin.php?page=embedpress&page_type=google-calendar' ) ],
620 ],
621 ] );
622 }
623 } elseif ( $posted_legacy_json !== '' ) {
624 // Legacy full-JSON path (kept for backward compatibility).
625 $decoded = json_decode( $posted_legacy_json, true );
626 if ( !empty( $decoded ) ) {
627 $pretty_client_secret = $this->get_pretty_json_string( $decoded );
628 }
629 }
630
631 update_option( 'epgc_client_secret', $pretty_client_secret);
632 update_option( 'epgc_cache_time', $epgc_cache_time);
633 update_option( 'epgc_selected_calendar_ids', $epgc_selected_calendar_ids);
634
635 }
636
637 public function save_opensea_settings() {
638 $option_name = EMBEDPRESS_PLG_NAME.':opensea';
639 $settings = get_option( $option_name, []);
640 $settings['api_key'] = isset( $_POST['api_key']) ? sanitize_text_field( $_POST['api_key']) : 0;
641 $settings['limit'] = isset( $_POST['limit']) ? sanitize_text_field( $_POST['limit']) : 0;
642 $settings['orderby'] = isset( $_POST['orderby']) ? sanitize_text_field( $_POST['orderby']) : 0;
643
644 $settings['license_key'] = 1; // backward compatibility
645
646 // Pro will handle g_loading_animation settings and other
647 $settings = apply_filters( 'ep_opensea_settings_before_save', $settings);
648 update_option( $option_name, $settings);
649 do_action( 'ep_opensea_settings_after_save', $settings);
650 }
651
652
653 function get_pretty_json_string($array) {
654 return str_replace(" ", " ", json_encode($array, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
655 }
656
657 /**
658 * AJAX handler for saving global brand image
659 */
660 public function save_global_brand_image() {
661 // Verify nonce for security
662 if (!wp_verify_nonce($_POST['nonce'], 'embedpress_ajax_nonce')) {
663 wp_die('Security check failed');
664 }
665
666 // Check user capabilities
667 if (!current_user_can('manage_options')) {
668 wp_die('Insufficient permissions');
669 }
670
671 $logo_url = isset($_POST['logo_url']) ? esc_url_raw($_POST['logo_url']) : '';
672 $logo_id = isset($_POST['logo_id']) ? intval($_POST['logo_id']) : '';
673
674 // Save global brand settings
675 $global_brand_settings = [
676 'logo_url' => $logo_url,
677 'logo_id' => $logo_id,
678 ];
679
680 $updated = update_option(EMBEDPRESS_PLG_NAME . ':global_brand', $global_brand_settings);
681
682 // If global brand image is being set, auto-enable branding for providers without custom logos
683 if (!empty($logo_url)) {
684 $this->auto_enable_global_branding($logo_url, $logo_id);
685 }
686
687 if ($updated !== false) {
688 wp_send_json_success([
689 'message' => 'Global brand image saved successfully',
690 'logo_url' => $logo_url,
691 'logo_id' => $logo_id
692 ]);
693 } else {
694 wp_send_json_error('Failed to save global brand image');
695 }
696 }
697
698 /**
699 * AJAX handler for dismissing UI elements (banners, popups, etc.)
700 */
701 public function dismiss_element() {
702 // Verify nonce for security
703 if (!wp_verify_nonce($_POST['nonce'], 'embedpress_ajax_nonce')) {
704 wp_die('Security check failed');
705 }
706
707 // Check user capabilities
708 if (!current_user_can('manage_options')) {
709 wp_die('Insufficient permissions');
710 }
711
712 $element_type = isset($_POST['element_type']) ? sanitize_text_field($_POST['element_type']) : '';
713
714 // Define valid dismiss types and their corresponding option names
715 $valid_dismiss_types = [
716 'main_banner' => 'embedpress_main_banner_dismissed',
717 'hub_popup' => 'embedpress_hub_popup_dismissed',
718 'popup_banner' => 'embedpress_popup_dismissed', // Legacy support
719 ];
720
721 if (array_key_exists($element_type, $valid_dismiss_types)) {
722 $option_name = $valid_dismiss_types[$element_type];
723 update_option($option_name, true);
724
725 // Store current plugin version when hub_popup is dismissed
726 // This ensures popup shows again on next version update
727 if ($element_type === 'hub_popup') {
728 update_option('embedpress_last_popup_version', EMBEDPRESS_VERSION);
729 }
730
731 wp_send_json_success([
732 'message' => ucfirst(str_replace('_', ' ', $element_type)) . ' dismissed successfully',
733 'element_type' => $element_type,
734 'option_name' => $option_name
735 ]);
736 }
737
738 wp_send_json_error([
739 'message' => 'Invalid element type: ' . $element_type,
740 'valid_types' => array_keys($valid_dismiss_types)
741 ]);
742 }
743
744 /**
745 * AJAX handler for dismissing feature notices
746 */
747 public function dismiss_feature_notice() {
748 // Verify nonce for security
749 if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'embedpress_feature_notice_nonce')) {
750 wp_send_json_error(['message' => 'Security check failed']);
751 }
752
753 // Check user capabilities
754 if (!current_user_can('manage_options')) {
755 wp_send_json_error(['message' => 'Insufficient permissions']);
756 }
757
758 $notice_id = isset($_POST['notice_id']) ? sanitize_text_field($_POST['notice_id']) : '';
759
760 if (empty($notice_id)) {
761 wp_send_json_error(['message' => 'Notice ID is required']);
762 }
763
764 // Define valid notice types and their corresponding option names
765 $valid_notices = [
766 'analytics' => 'embedpress_feature_notice_analytics_dismissed',
767 ];
768
769 if (array_key_exists($notice_id, $valid_notices)) {
770 $option_name = $valid_notices[$notice_id];
771 update_option($option_name, true);
772
773 wp_send_json_success([
774 'message' => 'Feature notice dismissed successfully',
775 'notice_id' => $notice_id,
776 'option_name' => $option_name
777 ]);
778 }
779
780 wp_send_json_error([
781 'message' => 'Invalid notice ID: ' . $notice_id,
782 'valid_notices' => array_keys($valid_notices)
783 ]);
784 }
785
786 /**
787 * Auto-enable branding for all providers that don't have custom logos
788 */
789 private function auto_enable_global_branding($logo_url, $logo_id) {
790 $providers = ['youtube', 'vimeo', 'wistia', 'twitch', 'dailymotion', 'document'];
791
792 foreach ($providers as $provider) {
793 $option_name = EMBEDPRESS_PLG_NAME . ':' . $provider;
794 $settings = get_option($option_name, []);
795
796 // Only auto-enable if provider doesn't have a custom logo set
797 $has_custom_logo = isset($settings['logo_url']) && !empty($settings['logo_url']);
798
799 if (!$has_custom_logo) {
800 // Enable branding but don't set logo_url/logo_id - let the template logic handle global fallback
801 $settings['branding'] = 'yes';
802 update_option($option_name, $settings);
803 }
804 }
805 }
806
807 /**
808 * Render the onboarding wizard page
809 */
810 public function render_onboarding_page() {
811 $settings = (array) get_option( EMBEDPRESS_PLG_NAME, [] );
812 $elements = (array) get_option( EMBEDPRESS_PLG_NAME . ':elements', [] );
813 $pro_active = apply_filters( 'embedpress/is_allow_rander', false );
814
815 $onboarding_data = [
816 'ajaxUrl' => admin_url( 'admin-ajax.php' ),
817 'nonce' => wp_create_nonce( 'embedpress_onboarding_nonce' ),
818 'settingsUrl' => admin_url( 'admin.php?page=' . $this->page_slug . '&page_type=settings' ),
819 'dashboardUrl' => admin_url( 'admin.php?page=' . $this->page_slug ),
820 'proActive' => $pro_active,
821 'upgradeUrl' => 'https://wpdeveloper.com/in/upgrade-embedpress',
822 'settings' => $settings,
823 'elements' => $elements,
824 'assetsUrl' => EMBEDPRESS_URL_ASSETS,
825 'analyticsTracking' => get_option( 'embedpress_analytics_tracking_enabled', true ),
826 ];
827
828 // Enqueue onboarding assets explicitly
829 wp_enqueue_script( 'embedpress-onboarding' );
830 wp_enqueue_style( 'embedpress-onboarding-css' );
831 wp_localize_script( 'embedpress-onboarding', 'embedpressOnboardingData', $onboarding_data );
832
833 echo '<div class="embedpress-onboarding-wrapper">';
834 echo '<div id="embedpress-onboarding-root"></div>';
835 echo '</div>';
836 }
837
838 /**
839 * AJAX handler for saving onboarding wizard settings
840 */
841 public function save_onboarding_settings() {
842 if ( ! current_user_can( 'manage_options' ) ) {
843 wp_send_json_error( [ 'message' => 'Insufficient permissions.' ] );
844 }
845
846 if ( empty( $_POST['nonce'] ) || ! wp_verify_nonce( $_POST['nonce'], 'embedpress_onboarding_nonce' ) ) {
847 wp_send_json_error( [ 'message' => 'Security check failed.' ] );
848 }
849
850 $settings = (array) get_option( EMBEDPRESS_PLG_NAME, [] );
851 $elements = (array) get_option( EMBEDPRESS_PLG_NAME . ':elements', [] );
852
853 // Element toggles — enable/disable all blocks/widgets at once
854 $all_gutenberg_blocks = [
855 'embedpress', 'document', 'embedpress-pdf', 'embedpress-calendar',
856 'youtube-block', 'google-docs-block', 'google-slides-block',
857 'google-sheets-block', 'google-forms-block', 'google-drawings-block',
858 'google-maps-block', 'twitch-block', 'wistia-block', 'vimeo-block',
859 ];
860 $all_elementor_widgets = [
861 'embedpress', 'embedpress-document', 'embedpress-pdf', 'embedpress-calendar',
862 ];
863
864 if ( isset( $_POST['gutenberg_block'] ) ) {
865 if ( sanitize_text_field( $_POST['gutenberg_block'] ) === '1' ) {
866 foreach ( $all_gutenberg_blocks as $block ) {
867 $elements['gutenberg'][ $block ] = $block;
868 }
869 } else {
870 $elements['gutenberg'] = [];
871 }
872 }
873 if ( isset( $_POST['elementor_widget'] ) ) {
874 if ( sanitize_text_field( $_POST['elementor_widget'] ) === '1' ) {
875 foreach ( $all_elementor_widgets as $widget ) {
876 $elements['elementor'][ $widget ] = $widget;
877 }
878 } else {
879 $elements['elementor'] = [];
880 }
881 }
882
883 // Global settings toggles
884 if ( isset( $_POST['analytics_tracking'] ) ) {
885 update_option( 'embedpress_analytics_tracking_enabled', intval( $_POST['analytics_tracking'] ) ? true : false );
886 }
887 if ( isset( $_POST['g_lazyload'] ) ) {
888 $settings['g_lazyload'] = intval( $_POST['g_lazyload'] );
889 }
890 if ( isset( $_POST['embedpress_document_powered_by'] ) ) {
891 $settings['embedpress_document_powered_by'] = intval( $_POST['embedpress_document_powered_by'] ) ? 'yes' : 'no';
892 }
893 // Pro feature toggles
894 if ( isset( $_POST['social_share'] ) ) {
895 $settings['social_share'] = intval( $_POST['social_share'] );
896 }
897 if ( isset( $_POST['custom_branding'] ) ) {
898 $settings['custom_branding'] = intval( $_POST['custom_branding'] );
899 }
900 if ( isset( $_POST['custom_ads'] ) ) {
901 $settings['custom_ads'] = intval( $_POST['custom_ads'] );
902 }
903 if ( isset( $_POST['content_protection'] ) ) {
904 $settings['content_protection'] = intval( $_POST['content_protection'] );
905 }
906 // Mark onboarding as complete
907 if ( ! empty( $_POST['complete'] ) ) {
908 update_option( 'embedpress_onboarding_complete', true );
909 }
910
911 // Data consent — enable usage tracking via WPInsights
912 if ( ! empty( $_POST['data_consent'] ) && ! get_option( 'embedpress_data_consent', false ) ) {
913 update_option( 'embedpress_data_consent', true );
914
915 $allow_tracking = get_option( 'wpins_allow_tracking', [] );
916 if ( ! is_array( $allow_tracking ) ) {
917 $allow_tracking = [];
918 }
919 $allow_tracking['embedpress'] = 'embedpress';
920 update_option( 'wpins_allow_tracking', $allow_tracking );
921
922 // Suppress the legacy opt-in notice now that consent was captured via the wizard
923 $block_notice = get_option( 'wpins_block_notice', [] );
924 if ( ! is_array( $block_notice ) ) {
925 $block_notice = [];
926 }
927 $block_notice['embedpress'] = 'embedpress';
928 update_option( 'wpins_block_notice', $block_notice );
929
930 // Register the daily cron and fire an initial payload so data
931 // reaches wpinsight.com without waiting for the first cron tick.
932 $tracker = EmbedPress_Plugin_Usage_Tracker::get_instance( EMBEDPRESS_FILE, [
933 'opt_in' => true,
934 'goodbye_form' => true,
935 'item_id' => '98ba0ac16a4f7b3b940d',
936 ] );
937 $tracker->schedule_tracking();
938 $tracker->do_tracking( true );
939 }
940
941 update_option( EMBEDPRESS_PLG_NAME, $settings );
942 update_option( EMBEDPRESS_PLG_NAME . ':elements', $elements );
943
944 wp_send_json_success( [ 'message' => 'Onboarding settings saved.' ] );
945 }
946
947 /**
948 * Reorder submenu items into the canonical order:
949 * 1. Dashboard, 2. Analytics, 3. Player & Engagement, 4. Branding,
950 * 5. Custom Ads, 6. Shortcode, 7. Settings, 8. Setup Wizard, 9. License.
951 *
952 * The label match strips out the trailing PRO badge span (if any) so
953 * upsell items keep their position regardless of badge markup.
954 */
955 public function reorder_submenu_items() {
956 global $submenu;
957
958 if (!isset($submenu[$this->page_slug])) {
959 return;
960 }
961
962 // Canonical priority by label (lower = earlier).
963 $priority = [
964 __('Dashboard', 'embedpress') => 10,
965 __('Analytics', 'embedpress') => 20,
966 __('Player & Engagement', 'embedpress') => 30,
967 __('Branding', 'embedpress') => 40,
968 __('Custom Ads', 'embedpress') => 50,
969 __('Shortcode', 'embedpress') => 60,
970 __('Settings', 'embedpress') => 70,
971 __('Setup Wizard', 'embedpress') => 80,
972 __('License', 'embedpress') => 90,
973 ];
974
975 $items = $submenu[$this->page_slug];
976
977 // Stable sort: pair each item with its original index so unknown
978 // labels keep their relative order while known ones snap to priority.
979 $indexed = [];
980 foreach ($items as $i => $item) {
981 $label_raw = isset($item[0]) ? $item[0] : '';
982 // Strip the trailing PRO/badge span and tags so labels with
983 // inline markup still match the priority map.
984 $label = trim(wp_strip_all_tags($label_raw));
985 $rank = isset($priority[$label]) ? $priority[$label] : 1000 + $i;
986 $indexed[] = [$rank, $i, $item];
987 }
988
989 usort($indexed, function ($a, $b) {
990 if ($a[0] === $b[0]) {
991 return $a[1] - $b[1];
992 }
993 return $a[0] - $b[0];
994 });
995
996 $submenu[$this->page_slug] = array_map(function ($row) {
997 return $row[2];
998 }, $indexed);
999 }
1000 }
1001