<commit_before><?php 
namespace Podlove\Modules\PodloveWebPlayer;

use Podlove\Model;
use Podlove\Model\Episode;
use Podlove\Model\EpisodeAsset;
use Podlove\Model\MediaFile;

/**
 * Print HTML & stuff required for Podlove Web Player
 */
class Printer {

	// unique player index
	private static $index = 0;

	// unique player id
	private $html_id;

	// Model\Episode
	private $episode;

	private $audio_formats = array( 'mp3', 'mp4', 'ogg', 'opus' );
	private $video_formats = array( 'mp4', 'ogg', 'webm' );

	// determined player type, based on $files
	private $is_video = true;

	// List of Model\MediaFile
	private $files = array();

	public function __construct( Episode $episode ) {
		$this->episode = $episode;
		$this->player_format_assignments = $this->get_player_format_assignments();
		$this->files = $this->get_files();
	}

	public function render() {

		if ( count( $this->player_format_assignments ) == 0 )
			return '';

		// build main audio/video tag
		$xml = new \SimpleXMLElement( '<' . $this->get_media_tag() . '/>' );
		$xml->addAttribute( 'id', $this->get_html_id() );
		$xml->addAttribute( 'controls', 'controls' );
		$xml->addAttribute( 'preload', 'none' );

		$width  = strtolower( trim( $this->get_webplayer_setting( $this->get_media_tag(), 'width' ) ) );
		$height = strtolower( trim( $this->get_webplayer_setting( $this->get_media_tag(), 'height' ) ) );

		if ( $this->is_video ) {
			$xml->addAttribute( 'poster', $this->episode->get_cover_art_with_fallback() );
			$xml->addAttribute( 'width', $width );
			$xml->addAttribute( 'height', $height );
		} else {
			$xml->addAttribute(
				'style',
				sprintf(
					'width: %s; height: %s',
					empty( $width ) ||  $width == 'auto' ? 'auto' : $width . 'px',
					empty( $height ) ? '30px' : $height
				)
			);
		}

		// get all relevant info about media files
		$media_files = array();
		foreach ( $this->files as $file ) {
			$mime = $file->episode_asset()->file_type()->mime_type;
			$media_files[ $mime ] = array(
				'file'      => $file,
				'mime_type' => $mime,
				'url'       => $file->get_file_url()
			);
		}

		// sort files bases on mime type so preferred get output first
		$sorted_files = array();
		$preferred_order = array( 'audio/mp4', 'audio/aac', 'audio/opus', 'audio/ogg', 'audio/vorbis' );
		foreach ( $preferred_order as $order_key ) {
			if ( isset($media_files[ $order_key ]) && $media_files[ $order_key ] ) {
				$sorted_files[] = $media_files[ $order_key ];
				unset($media_files[ $order_key ]);
			}
		}
		foreach ( $media_files as $file ) {
			$sorted_files[] = $file;
		}

		// add all sources
		$flash_fallback_func = function( &$xml ) {};
		foreach ( $sorted_files as $file ) {
			$mime_type = $file['mime_type'];

			$source = $xml->addChild('source');
			$source->addAttribute( 'src', $file['url'] );
			$source->addAttribute( 'type', $mime_type );

			if ( $mime_type == 'audio/mpeg' ) {
				$flash_fallback_func = function( &$xml ) use ( $file ) {
					$flash_fallback = $xml->addChild('object');
					$flash_fallback->addAttribute( 'type', 'application/x-shockwave-flash' );
					$flash_fallback->addAttribute( 'data', 'flashmediaelement.swf' );

					$params = array(
						array( 'name' => 'movie', 'value' => 'flashmediaelement.swf' ),
						array( 'name' => 'flashvars', 'value' => 'controls=true&file=' . $file['url'] )
					);

					foreach ( $params as $param ) {
						$p = $flash_fallback->addChild( 'param' );
						$p->addAttribute( 'name', $param['name'] );
						$p->addAttribute( 'value', $param['value'] );
					}
					
				};
			}
		}
		// add flash fallback after all <source>s
		$flash_fallback_func( $xml );

		// prettify and prepare to render
		$xml_string = $xml->asXML();
		$xml_string = $this->format_xml( $xml_string );
		$xml_string = $this->remove_xml_header( $xml_string );

		// set JavaScript options
		$truthy = array( true, 'true', 'on', 1, "1" );
		$init_options = array(
			'pluginPath'          => plugins_url( 'player/podlove-web-player/static/', __FILE__),
			'alwaysShowHours'     => true,
			'alwaysShowControls'  => true,
			'timecontrolsVisible' => false,
			'summaryVisible'      => false,
			'hidetimebutton'      => in_array( $this->get_webplayer_setting('buttons_time'), $truthy, true ),
			'hidedownloadbutton'  => in_array( $this->get_webplayer_setting('buttons_download'), $truthy, true ),
			'hidesharebutton'     => in_array( $this->get_webplayer_setting('buttons_share'), $truthy, true ),
			'sharewholeepisode'   => in_array( $this->get_webplayer_setting('buttons_sharemode'), $truthy, true ),
			'loop'                => false,
			'chapterlinks'        => 'all',
			'permalink'           => get_permalink(),
			'title'               => get_the_title(),
			'subtitle'            => wptexturize( convert_chars( trim( $this->episode->subtitle ) ) ),
			'summary'             => nl2br( wptexturize( convert_chars( trim( $this->episode->summary ) ) ) ),
			'poster'              => $this->episode->get_cover_art_with_fallback(),
			'duration'            => $this->episode->get_duration(),
			'chaptersVisible'     => in_array( \Podlove\get_webplayer_setting( 'chaptersVisible' ), $truthy, true ),
			'features'            => array( "current", "progress", "duration", "tracks", "fullscreen", "volume" )
		);

		if ( $chapters = $this->episode->get_chapters( 'json' ) )
			$init_options['chapters'] = json_decode( $chapters );

		$xml_string .= "\n"
		             . "\n<script>\n"
		             . "jQuery('#" . $this->get_html_id() . "').podlovewebplayer(" . json_encode( $init_options ) . ");"
		             . "\n</script>\n";

		return $xml_string;
	}

	private function get_webplayer_setting( $key, $subkey = false ) {

		$options = get_option( 'podlovewebplayer_options', array() );

		// try simple key
		if ( isset( $options[ $key ] ) )
			return $options[ $key ];<commit_msg>pass podcast-metadata into web player<commit_after><?php 
namespace Podlove\Modules\PodloveWebPlayer;

use Podlove\Model;
use Podlove\Model\Episode;
use Podlove\Model\Podcast;
use Podlove\Model\EpisodeAsset;
use Podlove\Model\MediaFile;

/**
 * Print HTML & stuff required for Podlove Web Player
 */
class Printer {

	// unique player index
	private static $index = 0;

	// unique player id
	private $html_id;

	// Model\Episode
	private $episode;

	private $audio_formats = array( 'mp3', 'mp4', 'ogg', 'opus' );
	private $video_formats = array( 'mp4', 'ogg', 'webm' );

	// determined player type, based on $files
	private $is_video = true;

	// List of Model\MediaFile
	private $files = array();

	public function __construct( Episode $episode ) {
		$this->episode = $episode;
		$this->player_format_assignments = $this->get_player_format_assignments();
		$this->files = $this->get_files();
	}

	public function render() {

		if ( count( $this->player_format_assignments ) == 0 )
			return '';

		// build main audio/video tag
		$xml = new \SimpleXMLElement( '<' . $this->get_media_tag() . '/>' );
		$xml->addAttribute( 'id', $this->get_html_id() );
		$xml->addAttribute( 'controls', 'controls' );
		$xml->addAttribute( 'preload', 'none' );

		$width  = strtolower( trim( $this->get_webplayer_setting( $this->get_media_tag(), 'width' ) ) );
		$height = strtolower( trim( $this->get_webplayer_setting( $this->get_media_tag(), 'height' ) ) );

		if ( $this->is_video ) {
			$xml->addAttribute( 'poster', $this->episode->get_cover_art_with_fallback() );
			$xml->addAttribute( 'width', $width );
			$xml->addAttribute( 'height', $height );
		} else {
			$xml->addAttribute(
				'style',
				sprintf(
					'width: %s; height: %s',
					empty( $width ) ||  $width == 'auto' ? 'auto' : $width . 'px',
					empty( $height ) ? '30px' : $height
				)
			);
		}

		// get all relevant info about media files
		$media_files = array();
		foreach ( $this->files as $file ) {
			$mime = $file->episode_asset()->file_type()->mime_type;
			$media_files[ $mime ] = array(
				'file'      => $file,
				'mime_type' => $mime,
				'url'       => $file->get_file_url()
			);
		}

		// sort files bases on mime type so preferred get output first
		$sorted_files = array();
		$preferred_order = array( 'audio/mp4', 'audio/aac', 'audio/opus', 'audio/ogg', 'audio/vorbis' );
		foreach ( $preferred_order as $order_key ) {
			if ( isset($media_files[ $order_key ]) && $media_files[ $order_key ] ) {
				$sorted_files[] = $media_files[ $order_key ];
				unset($media_files[ $order_key ]);
			}
		}
		foreach ( $media_files as $file ) {
			$sorted_files[] = $file;
		}

		// add all sources
		$flash_fallback_func = function( &$xml ) {};
		foreach ( $sorted_files as $file ) {
			$mime_type = $file['mime_type'];

			$source = $xml->addChild('source');
			$source->addAttribute( 'src', $file['url'] );
			$source->addAttribute( 'type', $mime_type );

			if ( $mime_type == 'audio/mpeg' ) {
				$flash_fallback_func = function( &$xml ) use ( $file ) {
					$flash_fallback = $xml->addChild('object');
					$flash_fallback->addAttribute( 'type', 'application/x-shockwave-flash' );
					$flash_fallback->addAttribute( 'data', 'flashmediaelement.swf' );

					$params = array(
						array( 'name' => 'movie', 'value' => 'flashmediaelement.swf' ),
						array( 'name' => 'flashvars', 'value' => 'controls=true&file=' . $file['url'] )
					);

					foreach ( $params as $param ) {
						$p = $flash_fallback->addChild( 'param' );
						$p->addAttribute( 'name', $param['name'] );
						$p->addAttribute( 'value', $param['value'] );
					}
					
				};
			}
		}
		// add flash fallback after all <source>s
		$flash_fallback_func( $xml );

		// prettify and prepare to render
		$xml_string = $xml->asXML();
		$xml_string = $this->format_xml( $xml_string );
		$xml_string = $this->remove_xml_header( $xml_string );

		// get podcast object
		$podcast = Podcast::get_instance();

		// set JavaScript options
		$truthy = array( true, 'true', 'on', 1, "1" );
		$init_options = array(
			'pluginPath'          => plugins_url( 'player/podlove-web-player/static/', __FILE__),
			'alwaysShowHours'     => true,
			'alwaysShowControls'  => true,
			'timecontrolsVisible' => false,
			'summaryVisible'      => false,
			'hidetimebutton'      => in_array( $this->get_webplayer_setting('buttons_time'), $truthy, true ),
			'hidedownloadbutton'  => in_array( $this->get_webplayer_setting('buttons_download'), $truthy, true ),
			'hidesharebutton'     => in_array( $this->get_webplayer_setting('buttons_share'), $truthy, true ),
			'sharewholeepisode'   => in_array( $this->get_webplayer_setting('buttons_sharemode'), $truthy, true ),
			'loop'                => false,
			'chapterlinks'        => 'all',
			'permalink'           => get_permalink(),
			'title'               => get_the_title(),
			'subtitle'            => wptexturize( convert_chars( trim( $this->episode->subtitle ) ) ),
			'summary'             => nl2br( wptexturize( convert_chars( trim( $this->episode->summary ) ) ) ),
			'poster'              => $this->episode->get_cover_art_with_fallback(),
			'showTitle'           => $podcast->title,
			'showSubtitle'        => $podcast->subtitle,
			'showSummary'         => $podcast->summary,
			'showPoster'          => $podcast->cover_image,
			'duration'            => $this->episode->get_duration(),
			'chaptersVisible'     => in_array( \Podlove\get_webplayer_setting( 'chaptersVisible' ), $truthy, true ),
			'features'            => array( "current", "progress", "duration", "tracks", "fullscreen", "volume" )
		);

		if ( $chapters = $this->episode->get_chapters( 'json' ) )
			$init_options['chapters'] = json_decode( $chapters );

		$xml_string .= "\n"
		             . "\n<script>\n"
		             . "jQuery('#" . $this->get_html_id() . "').podlovewebplayer(" . json_encode( $init_options ) . ");"
		             . "\n</script>\n";

		return $xml_string;
	}

	private function get_webplayer_setting( $key, $subkey = false ) {

		$options = get_option( 'podlovewebplayer_options', array() );

		// try simple key
		if ( isset( $options[ $key ] ) )
			return $options[ $key ];
{'fraction_non_alphanumeric': 0.1804617821121947, 'fraction_numerical': 0.001833791781278653, 'mean_word_length': 3.340810419681621, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 179, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 46}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 14, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3213874', 'n_tokens_mistral': 4702, 'n_tokens_neox': 4134, 'n_words': 835}