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