on the container div. Per-post override * via _piperless_style meta. * * @since 0.1.0 */ class Player { /** @var Logger */ private Logger $logger; /** * Constructor. * * @param Logger $logger Logger. */ public function __construct( Logger $logger ) { $this->logger = $logger; } /** * Register hooks. */ public function init(): void { add_filter( 'the_content', [ $this, 'maybe_prepend_player' ], 20 ); add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_assets' ] ); add_shortcode( 'piperless_player', [ $this, 'shortcode' ] ); } /** * Insert the player before or after content based on settings. * * @param string $content Post content. * @return string */ public function maybe_prepend_player( string $content ): string { // Only on singular views. if ( ! is_singular() || ! in_the_loop() || ! is_main_query() ) { return $content; } $settings = get_option( 'piperless_settings', [] ); $post_meta = get_post_meta( get_the_ID(), '_piperless_placement', true ); $placement = ( '' !== $post_meta ) ? $post_meta : ( $settings['player_placement'] ?? 'after' ); if ( 'manual' === $placement ) { return $content; } $player_html = $this->render( get_the_ID() ); if ( '' === $player_html ) { return $content; } if ( 'before' === $placement ) { return $player_html . $content; } if ( 'both' === $placement ) { return $player_html . $content . $player_html; } return $content . $player_html; } /** * Shortcode: [piperless_player post_id="123"] * * @param array $atts Attributes. * @return string */ public function shortcode( array $atts ): string { $atts = shortcode_atts( [ 'post_id' => 0 ], $atts, 'piperless_player' ); $post_id = (int) $atts['post_id']; if ( 0 === $post_id ) { $post_id = get_the_ID(); } return $this->render( $post_id ); } /** * Render the audio player for a post. * * @param int $post_id Post ID. * @return string HTML or empty string. */ public function render( int $post_id ): string { $audio_url = get_post_meta( $post_id, '_piperless_audio_url', true ); if ( empty( $audio_url ) ) { return ''; } $settings = get_option( 'piperless_settings', [] ); $post_style = get_post_meta( $post_id, '_piperless_style', true ); $style = ( '' !== $post_style ) ? $post_style : ( $settings['player_style'] ?? 'classic' ); $show_meta = ( $settings['player_show_meta'] ?? '1' ) === '1'; $duration = (float) get_post_meta( $post_id, '_piperless_duration', true ); // Title: per-post override wins, then global default, then empty. $title = get_post_meta( $post_id, '_piperless_title', true ); if ( '' === $title ) { $title = $settings['player_title'] ?? ''; } $style_class = 'piperless-player--' . esc_attr( $style ); ob_start(); ?>
00:00 0 ) : ?> / format_duration( $duration ) ); ?>
0 ) { wp_add_inline_style( 'piperless-player-base', '.piperless-player{max-width:' . $max_width . 'px}' ); } else { wp_add_inline_style( 'piperless-player-base', '.piperless-player{max-width:none}' ); } // Custom CSS (inline). if ( 'custom' === $style && ! empty( $settings['player_custom_css'] ) ) { wp_add_inline_style( 'piperless-player-base', $settings['player_custom_css'] ); } // Player JavaScript. wp_enqueue_script( 'piperless-player', PIPERLESS_PLUGIN_URL . 'assets/js/player.js', [], PIPERLESS_VERSION, true ); } /** * Format seconds as mm:ss. * * @param float $seconds Duration in seconds. * @return string */ public function format_duration( float $seconds ): string { $minutes = (int) floor( $seconds / 60 ); $secs = (int) round( $seconds % 60 ); return sprintf( '%02d:%02d', $minutes, $secs ); } }