PluginProbe ʕ •ᴥ•ʔ
Presto Player / 4.3.1
Presto Player v4.3.1
4.3.1 4.3.0 4.2.4 4.2.3 4.2.2 4.2.0 4.2.1 trunk 1.10.0 1.10.1 1.10.2 1.11.0 1.12.0 1.13.0 1.14.0 1.14.1 1.5.10 1.5.11 1.5.12 1.5.13 1.5.14 1.5.15 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.10 1.6.11 1.6.12 1.6.13 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 1.8.0 1.8.1 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.9.0 1.9.1 1.9.10 1.9.11 1.9.12 1.9.13 1.9.14 1.9.2 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.1 2.0.10 2.0.11 2.0.12 2.0.13 2.0.14 2.0.15 2.0.16 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 2.1.0 2.2.0 2.2.1 2.2.2 2.2.3 2.2.3-beta1 2.3.0 2.3.1 2.3.2 2.3.3 3.0.0 3.0.0-beta1 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.0.8 3.1.0 3.1.1 3.1.2 3.1.3 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.0.5 4.0.6 4.0.7 4.0.8 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4
presto-player / inc / Services / Menu.php
presto-player / inc / Services Last commit date
API 1 month ago Blocks 10 months ago License 1 month ago AdminNotice.php 3 weeks ago AdminNotices.php 3 weeks ago AjaxActions.php 3 weeks ago Blocks.php 1 year ago Compatibility.php 10 months ago Learn.php 1 month ago Menu.php 1 month ago Migrations.php 1 year ago NpsSurvey.php 5 months ago Onboarding.php 3 weeks ago Player.php 5 days ago PluginInstaller.php 1 month ago PreloadService.php 1 year ago ProCompatibility.php 1 month ago ReusableVideos.php 2 weeks ago RewriteRulesManager.php 1 year ago Scripts.php 2 weeks ago Settings.php 1 month ago Shortcodes.php 1 month ago Streamer.php 3 weeks ago Translation.php 3 weeks ago Usage.php 3 weeks ago VideoPostType.php 2 weeks ago
Menu.php
343 lines
1 <?php
2 /**
3 * Admin menu registration for the Presto Player dashboard.
4 *
5 * @package PrestoPlayer
6 * @subpackage Services
7 */
8
9 namespace PrestoPlayer\Services;
10
11 use PrestoPlayer\Plugin;
12 use PrestoPlayer\Services\License\License;
13
14 /**
15 * Registers the top-level "Presto Player" admin menu and submenu structure.
16 */
17 class Menu {
18
19 /**
20 * Whether enqueueing has run for the dashboard page.
21 *
22 * @var bool
23 */
24 protected $enqueue;
25
26 /**
27 * Register WordPress hooks for the menu service.
28 *
29 * @return void
30 */
31 public function register() {
32 add_action( 'admin_menu', array( $this, 'addMenu' ) );
33 }
34
35 /**
36 * Register the top-level menu and its submenu pages.
37 *
38 * @return void
39 */
40 public function addMenu() {
41 // Custom-slug menu following the SureDash submenu pattern. See #996.
42 $dashboard_page = add_menu_page(
43 __( 'Presto Player', 'presto-player' ),
44 __( 'Presto Player', 'presto-player' ),
45 'publish_posts',
46 'presto-dashboard',
47 function () {
48 ob_start();
49 ?>
50 <div id="presto-admin-dashboard">
51 <div id="presto-admin-dashboard-content"></div>
52 </div>
53 <?php wp_auth_check_html(); ?>
54 <?php
55 $page = ob_get_clean();
56 echo $page; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Pre-rendered admin HTML from trusted markup above.
57 },
58 'data:image/svg+xml;base64,' . base64_encode( file_get_contents( PRESTO_PLAYER_PLUGIN_DIR . 'img/menu-icon.svg' ) ),
59 58
60 );
61
62 // First submenu — same slug as parent, replaces "Presto Player" label with "Dashboard".
63 add_submenu_page(
64 'presto-dashboard',
65 __( 'Dashboard', 'presto-player' ),
66 __( 'Dashboard', 'presto-player' ),
67 'publish_posts',
68 'presto-dashboard'
69 );
70
71 // Remaining tabs — each uses admin.php?page=presto-dashboard&tab=X as slug.
72 // WordPress renders these as links to the dashboard page with the tab param.
73 add_submenu_page(
74 'presto-dashboard',
75 __( 'Media Hub', 'presto-player' ),
76 __( 'Media Hub', 'presto-player' ),
77 'publish_posts',
78 'admin.php?page=presto-dashboard&tab=MediaHub'
79 );
80
81 add_submenu_page(
82 'presto-dashboard',
83 __( 'Analytics', 'presto-player' ),
84 __( 'Analytics', 'presto-player' ),
85 'publish_posts',
86 'admin.php?page=presto-dashboard&tab=Analytics'
87 );
88
89 add_submenu_page(
90 'presto-dashboard',
91 __( 'Emails', 'presto-player' ),
92 __( 'Emails', 'presto-player' ),
93 'manage_options',
94 'admin.php?page=presto-dashboard&tab=Emails'
95 );
96
97 add_submenu_page(
98 'presto-dashboard',
99 __( 'Settings', 'presto-player' ),
100 __( 'Settings', 'presto-player' ),
101 'publish_posts',
102 'admin.php?page=presto-dashboard&tab=Settings'
103 );
104
105 add_submenu_page(
106 'presto-dashboard',
107 __( 'Learn', 'presto-player' ),
108 __( 'Learn', 'presto-player' ),
109 'publish_posts',
110 'admin.php?page=presto-dashboard&tab=Learn'
111 );
112
113 // Pro-active-but-unlicensed users see the License tab CTA inside the dashboard,
114 // so the external "Upgrade to Pro" submenu entry is shown only when Pro isn't installed.
115 if ( ! class_exists( '\PrestoPlayer\Pro\Plugin' ) ) {
116 global $submenu;
117 $submenu['presto-dashboard'][] = array( // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- Appending to the admin submenu global is the standard WordPress pattern.
118 __( 'Upgrade to Pro', 'presto-player' ),
119 'publish_posts',
120 'https://prestoplayer.com/pricing/',
121 );
122 add_action( 'admin_head', array( $this, 'upgradeToProLinkStyles' ) );
123 add_action( 'admin_footer', array( $this, 'upgradeToProLinkScript' ) );
124 }
125
126 add_action( 'admin_head', array( $this, 'submenuDividerStyles' ) );
127 add_action( "admin_print_scripts-{$dashboard_page}", array( $this, 'dashboardAssets' ) );
128 }
129
130 /**
131 * Add visual dividers between submenu groups.
132 *
133 * Groups:
134 * 1. Dashboard (overview)
135 * 2. Media Hub, Analytics, Emails (features)
136 * 3. Settings, Learn (config & help)
137 * 4. Upgrade to Pro (upsell, non-Pro only)
138 *
139 * nth-child mapping (1st child is the hidden parent duplicate):
140 * 2 = Dashboard, 3 = Media Hub, 4 = Analytics,
141 * 5 = Emails, 6 = Settings, 7 = Learn, 8 = Upgrade to Pro
142 */
143 public function submenuDividerStyles() {
144 $menu = '#toplevel_page_presto-dashboard';
145 $slug = 'admin.php?page=presto-dashboard';
146 ?>
147 <style>
148 <?php echo esc_attr( $menu ); ?> li {
149 clear: both;
150 }
151 <?php echo esc_attr( $menu ); ?> li:not(:last-child) a[href^="<?php echo esc_attr( $slug ); ?>"]:after {
152 border-bottom: 1px solid hsla(0, 0%, 100%, .2);
153 display: block;
154 float: left;
155 margin: 13px -15px 8px;
156 content: "";
157 width: calc(100% + 26px);
158 }
159 <?php echo esc_attr( $menu ); ?> li:not(:last-child) a[href^="<?php echo esc_attr( $slug ); ?>&tab=MediaHub"]:after,
160 <?php echo esc_attr( $menu ); ?> li:not(:last-child) a[href^="<?php echo esc_attr( $slug ); ?>&tab=Analytics"]:after,
161 <?php echo esc_attr( $menu ); ?> li:not(:last-child) a[href^="<?php echo esc_attr( $slug ); ?>&tab=Settings"]:after {
162 content: none;
163 }
164 </style>
165 <?php
166 }
167
168 /**
169 * Style the "Upgrade to Pro" submenu link with an external-link icon.
170 * Hooked to admin_head only when Pro is not installed.
171 */
172 public function upgradeToProLinkStyles() {
173 ?>
174 <style>
175 #toplevel_page_presto-dashboard .wp-submenu a[href*="prestoplayer.com/pricing"]::after {
176 content: "\f504";
177 font-family: dashicons;
178 font-size: 13px;
179 margin-left: 6px;
180 vertical-align: middle;
181 opacity: 0.6;
182 }
183 </style>
184 <?php
185 }
186
187 /**
188 * Open the "Upgrade to Pro" submenu link in a new tab.
189 * Hooked to admin_footer (DOM must exist before the script runs).
190 * Follows the SureForms pattern: intercept click → window.open.
191 */
192 public function upgradeToProLinkScript() {
193 ?>
194 <script>
195 document.addEventListener( 'DOMContentLoaded', function() {
196 const link = document.querySelector( '#toplevel_page_presto-dashboard .wp-submenu a[href*="prestoplayer.com/pricing"]' );
197 if ( link ) {
198 link.addEventListener( 'click', function( e ) {
199 e.preventDefault();
200 window.open( link.href, '_blank' );
201 } );
202 }
203 } );
204 </script>
205 <?php
206 }
207
208 /**
209 * Get plugin status
210 *
211 * @param string $plugin_file Plugin file path.
212 * @return string Plugin status.
213 */
214 public function getPluginStatus( $plugin_file ) {
215 if ( ! function_exists( 'get_plugins' ) ) {
216 require_once ABSPATH . 'wp-admin/includes/plugin.php';
217 }
218
219 $installed_plugins = get_plugins();
220
221 if ( ! isset( $installed_plugins[ $plugin_file ] ) ) {
222 return 'not-installed';
223 }
224
225 return is_plugin_active( $plugin_file ) ? 'active' : 'inactive';
226 }
227
228 /**
229 * Scripts needed on dashboard page
230 */
231 public function dashboardAssets() {
232 wp_enqueue_media();
233
234 $assets = include trailingslashit( PRESTO_PLAYER_PLUGIN_DIR ) . 'dist/dashboard.asset.php';
235 wp_enqueue_script(
236 'presto/dashboard/admin',
237 trailingslashit( PRESTO_PLAYER_PLUGIN_URL ) . 'dist/dashboard.js',
238 array_merge( array( 'hls.js', 'presto-components', 'regenerator-runtime', 'updates' ), $assets['dependencies'] ),
239 $assets['version'],
240 true
241 );
242
243 // Dashboard style.
244 wp_enqueue_style( 'presto/dashboard/admin', trailingslashit( PRESTO_PLAYER_PLUGIN_URL ) . 'dist/dashboard.css', array(), $assets['version'] );
245
246 // Font styles for WhatsNew flyout.
247 wp_enqueue_style( 'presto/dashboard/fonts', trailingslashit( PRESTO_PLAYER_PLUGIN_URL ) . 'assets/css/font.css', array(), Plugin::version() );
248
249 wp_enqueue_style( 'wp-components' );
250
251 if ( function_exists( 'wp_set_script_translations' ) ) {
252 wp_set_script_translations( 'presto/dashboard/admin', 'presto-player' );
253 }
254
255 $current_user = wp_get_current_user();
256
257 // Check if SureDash is available and get onboarding image.
258 $onboarding_image = '';
259 if ( defined( 'SUREDASHBOARD_URL' ) ) {
260 $onboarding_image = SUREDASHBOARD_URL . 'assets/images/onboarding.svg';
261 }
262
263 wp_localize_script(
264 'presto/dashboard/admin',
265 'prestoPlayer',
266 array(
267 'root' => esc_url_raw( get_rest_url() ),
268 'nonce' => wp_create_nonce( 'presto_player_admin' ),
269 'ajaxurl' => admin_url( 'admin-ajax.php' ),
270 'wpVersionString' => 'wp/v2/',
271 'prestoVersionString' => 'presto-player/v1/',
272 'version' => Plugin::version(),
273 'proVersion' => Plugin::proVersion(),
274 'isPremium' => Plugin::isPro(),
275 'is_pro_available' => Plugin::isPro(),
276 'isProPluginActive' => class_exists( '\PrestoPlayer\Pro\Plugin' ),
277 'hasLicenseKey' => License::hasKey(),
278 'license_status' => Plugin::licenseStatus(),
279 'dashboardUrl' => admin_url( 'admin.php?page=presto-dashboard' ),
280 'upgradeLink' => 'https://prestoplayer.com/pricing/',
281 'upgrade_link' => 'https://prestoplayer.com/pricing/',
282 'onboarding_image' => $onboarding_image,
283 'upgrade_image' => trailingslashit( PRESTO_PLAYER_PLUGIN_URL ) . 'img/upgrade-illustration.png',
284 'createMediaUrl' => admin_url( 'post-new.php?post_type=pp_video_block' ),
285 'mediaHubUrl' => admin_url( 'admin.php?page=presto-dashboard&tab=MediaHub' ),
286 'onboardingUrl' => admin_url( 'admin.php?page=presto-dashboard&post_type=pp_video_block&tab=Onboarding' ),
287 'currentUser' => array(
288 'display_name' => $current_user->display_name,
289 'user_login' => $current_user->user_login,
290 'user_email' => $current_user->user_email,
291 'first_name' => $current_user->user_firstname ? $current_user->user_firstname : $current_user->display_name,
292 'last_name' => $current_user->user_lastname ? $current_user->user_lastname : '',
293 ),
294 'suredash_status' => $this->getPluginStatus( 'suredash/suredash.php' ),
295 'surecart_status' => $this->getPluginStatus( 'surecart/surecart.php' ),
296 'suretriggers_status' => $this->getPluginStatus( 'suretriggers/suretriggers.php' ),
297 'suremembers_status' => $this->getPluginStatus( 'suremembers/suremembers.php' ),
298 'suremails_status' => $this->getPluginStatus( 'suremails/suremails.php' ),
299 'sureforms_status' => $this->getPluginStatus( 'sureforms/sureforms.php' ),
300 'onboarding_completed' => get_option( 'presto_player_onboarding_completed', 'no' ) === 'yes',
301 'onboarding_redirect' => isset( $_GET['tab'] ) && 'Onboarding' === $_GET['tab'], // phpcs:ignore WordPress.Security.NonceVerification.Recommended
302 'onboarding' => array(
303 'addonList' => array(
304 array(
305 'slug' => 'suredash',
306 'title' => __( 'Build Your Video Community with SureDash', 'presto-player' ),
307 'logo' => 'https://ps.w.org/suredash/assets/icon-256x256.gif',
308 'description' => __( 'Create a members-only space around your video content with courses, forums, and community features.', 'presto-player' ),
309 ),
310 array(
311 'slug' => 'surecart',
312 'title' => __( 'Sell Video Content with SureCart', 'presto-player' ),
313 'logo' => 'https://ps.w.org/surecart/assets/icon-256x256.gif',
314 'description' => __( 'Accept payments for courses, memberships, and digital downloads directly from your site.', 'presto-player' ),
315 ),
316 array(
317 'slug' => 'suretriggers',
318 'title' => __( 'Automate Your Video Workflows with OttoKit', 'presto-player' ),
319 'logo' => 'https://ps.w.org/suretriggers/assets/icon-256x256.png',
320 'description' => __( 'Trigger actions when videos are watched, emails captured, or goals reached — no code needed.', 'presto-player' ),
321 ),
322 array(
323 'slug' => 'suremails',
324 'title' => __( 'Keep Emails Out of Spam with SureMail', 'presto-player' ),
325 'logo' => 'https://ps.w.org/suremails/assets/icon-256x256.gif',
326 'description' => __( 'Ensure video notifications and email captures actually reach your audience\'s inbox.', 'presto-player' ),
327 ),
328 ),
329 ),
330 'canManageEmailSubmissions' => current_user_can( 'manage_options' ),
331 'i18n' => Translation::geti18n(),
332 'api' => array(
333 'analyticsViews' => '/presto-player/v1/analytics/views',
334 'analyticsWatchTime' => '/presto-player/v1/analytics/watch-time',
335 'analyticsTopVideos' => '/presto-player/v1/analytics/top-videos',
336 'analyticsTopUsers' => '/presto-player/v1/analytics/top-users',
337 'activatePlugin' => '/presto-player/v1/activate-plugin',
338 ),
339 )
340 );
341 }
342 }
343