(int) $player_id ); if ( in_array( $theme, array( 'light', 'dark' ), true ) ) { $args['theme'] = $theme; } return add_query_arg( $args, home_url( '/' ) ); } /** * Expose the URL pattern to the admin app. * * @param array $data Bootstrap data. * @return array */ public function admin_data( $data ) { $data['previewUrl'] = self::url( 0 ); return $data; } /** * Output the preview document. */ public function render() { $player_id = (int) get_query_var( self::QUERY ); if ( ! $player_id ) { return; } /** This filter is documented in includes/Admin/Menu.php */ if ( ! current_user_can( apply_filters( 'streamsera_required_cap', 'edit_posts', 'preview' ) ) ) { auth_redirect(); exit; } $post = get_post( $player_id ); if ( ! $post || Player::POST_TYPE !== $post->post_type || ! current_user_can( 'edit_post', $player_id ) ) { status_header( 404 ); header( 'Content-Type: text/plain; charset=utf-8' ); echo esc_html__( 'StreamSera: player not found.', 'streamsera' ); exit; } $config = Player::get_config( $player_id, true ); $theme = sanitize_key( isset( $_GET['theme'] ) && is_string( $_GET['theme'] ) ? wp_unslash( $_GET['theme'] ) : '' ); // phpcs:ignore WordPress.Security.NonceVerification $theme = in_array( $theme, array( 'light', 'dark' ), true ) ? $theme : ''; $device = sanitize_key( isset( $_GET['device'] ) && is_string( $_GET['device'] ) ? wp_unslash( $_GET['device'] ) : '' ); // phpcs:ignore WordPress.Security.NonceVerification $device = in_array( $device, array( 'tablet', 'phone' ), true ) ? $device : ''; $scheme = $theme ? $theme : ( isset( $config['theme'] ) && 'dark' === $config['theme'] ? 'dark' : 'light' ); $layout = isset( $config['layout'] ) ? (string) $config['layout'] : 'card'; /** * Filter layouts that should preview at full page width (the rest are centred at a fixed width). * * @param string[] $wide Layout ids. */ $wide = (array) apply_filters( 'streamsera_preview_wide_layouts', array( 'hero', 'shelf' ) ); // Headers first, then register exactly the player handles (core + add-ons): template_redirect // runs before wp_enqueue_scripts, and this document prints its own head. nocache_headers(); header( 'Content-Type: text/html; charset=utf-8' ); header( 'X-Robots-Tag: noindex' ); Assets::register_standalone(); $markup = Assets::render_player( $player_id, $theme ? array( 'theme' => $theme ) : array(), array( 'preview' => true, 'standalone' => true, ) ); $title = get_the_title( $player_id ); $status = 'publish' === $post->post_status ? __( 'Published', 'streamsera' ) : __( 'Draft', 'streamsera' ); $builder = admin_url( 'admin.php?page=streamsera-players#/players/' . $player_id ); ?> data-theme="">