diff options
Diffstat (limited to 'plugins/jetpack/modules/shortcodes/audio.php')
-rw-r--r-- | plugins/jetpack/modules/shortcodes/audio.php | 380 |
1 files changed, 331 insertions, 49 deletions
diff --git a/plugins/jetpack/modules/shortcodes/audio.php b/plugins/jetpack/modules/shortcodes/audio.php index ec50436a..55e8b984 100644 --- a/plugins/jetpack/modules/shortcodes/audio.php +++ b/plugins/jetpack/modules/shortcodes/audio.php @@ -1,71 +1,353 @@ <?php /** - * Shortcode for audio - * [audio http://wpcom.files.wordpress.com/2007/01/mattmullenweg-interview.mp3|width=180|titles=1|artists=2] - * - * The important question here is whether the shortcode applies to widget_text: - * add_filter('widget_text', 'do_shortcode'); - * */ +* Class wrapper for audio shortcode +*/ +class AudioShortcode { -function audio_shortcode( $atts ) { - global $ap_playerID; + static $add_script = false; + + /** + * Add all the actions & resgister the shortcode + */ + function __construct() { + add_shortcode( 'audio', array( $this, 'audio_shortcode' ) ); + add_action( 'wp_enqueue_scripts', array( $this, 'check_infinite' ) ); + add_action( 'infinite_scroll_render', array( $this, 'audio_shortcode_infinite' ), 11 ); + } - if ( ! isset( $atts[0] ) ) - return ''; + /** + * Shortcode for audio + * [audio http://wpcom.files.wordpress.com/2007/01/mattmullenweg-interview.mp3|width=180|titles=1|artists=2] + * + * The important question here is whether the shortcode applies to widget_text: + * add_filter('widget_text', 'do_shortcode'); + * */ + function audio_shortcode( $atts ) { + global $ap_playerID; + global $post; + if ( ! is_array( $atts ) ) { + return '<!-- Audio shortcode passed invalid attributes -->'; + } - if ( count( $atts ) ) - $atts[0] = strip_tags( join( ' ', $atts ) ); + if ( ! isset( $atts[0] ) ) { + return '<!-- Audio shortcode source not set -->'; + } - $src = ltrim( $atts[0], '=' ); + // add the special .js + wp_enqueue_script( + 'audio-shortcode', + plugins_url( 'js/audio-shortcode.js', __FILE__ ), + array( 'jquery' ), + '1.1', + true); - $ap_options = apply_filters( 'audio_player_default_colors', array( "bg" => "0xf8f8f8", "leftbg" => "0xeeeeee", "lefticon" => "0x666666", "rightbg" => "0xcccccc", "rightbghover" => "0x999999", "righticon" => "0x666666", "righticonhover" => "0xffffff", "text" => "0x666666", "slider" => "0x666666", "track" => "0xFFFFFF", "border" => "0x666666", "loader" => "0x9FFFB8" ) ); + // alert the infinite scroll renderer that it should try to load the script + self::$add_script = true; + $atts[0] = strip_tags( join( ' ', $atts ) ); + $src = ltrim( $atts[0], '=' ); + $ap_options = apply_filters( + 'audio_player_default_colors', + array( + "bg" => "0xF8F8F8", + "leftbg" => "0xEEEEEE", + "lefticon" => "0x666666", + "rightbg" => "0xCCCCCC", + "rightbghover" => "0x999999", + "righticon" => "0x666666", + "righticonhover" => "0xFFFFFF", + "text" => "0x666666", + "slider" => "0x666666", + "track" => "0xFFFFFF", + "border" => "0x666666", + "loader" => "0x9FFFB8" + ) ); - if ( isset( $ap_playerID ) == false ) - $ap_playerID = 1; - else - $ap_playerID++; + if ( ! isset( $ap_playerID ) ) { + $ap_playerID = 1; + } else { + $ap_playerID++; + } - $src = trim( $src, ' "' ); + if ( ! isset( $load_audio_script ) ) { + $load_audio_script = true; + } - if ( strpos( '|', $src ) ) - $options = explode( '|', $src ); - else + // prep the audio files + $src = trim( $src, ' "' ); $options = array(); + $data = preg_split( "/\|/", $src ); + $sound_file = $data[0]; + $sound_files = explode( ',', $sound_file ); + $sound_files = array_map( 'trim', $sound_files ); + $sound_files = array_map( array( $this, 'unbreak_spacey_url' ), $sound_files ); + $sound_files = array_map( 'esc_url_raw', $sound_files ); // Ensure each is a valid URL + $num_files = count( $sound_files ); + $sound_types = array( + 'mp3' => 'mpeg', + 'wav' => 'wav', + 'ogg' => 'ogg', + 'oga' => 'ogg', + 'm4a' => 'mp4', + 'aac' => 'mp4', + 'webm' => 'webm' + ); - $data = preg_split( "/[\|]/", $src ); - $flashvars = "playerID={$ap_playerID}"; + for ( $i = 1; $i < count( $data ); $i++ ) { + $pair = explode( "=", $data[$i] ); + if ( strtolower( $pair[0] ) != 'autostart' ) { + $options[$pair[0]] = $pair[1]; + } + } - for ( $i = 1; $i < count( $data ); $i++ ) { - $pair = explode( "=", $data[$i] ); - if( strtolower( $pair[0] ) != 'autostart' ) - $options[$pair[0]] = $pair[1]; - } + // Merge runtime options to default colour options + // (runtime options overwrite default options) + foreach ( $ap_options as $key => $default ) { + if ( isset( $options[$key] ) ) { + if ( preg_match( '/^0x[a-f0-9]{6}$/i', $default ) && !preg_match( '/^0x[a-f0-9]{6}$/i', $options[$key] ) ) { + // Default is a hex color, but input is not + $options[$key] = $default; + } + } else { + $options[$key] = $default; + } + } + $options['soundFile'] = join( ',', $sound_files ); // Rebuild the option with our now sanitized data + $flash_vars = array(); + foreach ( $options as $key => $value ) { + $flash_vars[] = rawurlencode( $key ) . '=' . rawurlencode( $value ); + } + $flash_vars = implode( '&', $flash_vars ); + $flash_vars = esc_attr( $flash_vars ); - // Merge runtime options to default colour options (runtime options overwrite default options) - $options = array_merge( $ap_options, $options ); - $options['soundFile'] = $data[0]; - $flash_vars = ''; - foreach ( $options as $key => $value ) { - $flash_vars .= '&' . rawurlencode( $key ) . '=' . rawurlencode( $value ); - } - $flash_vars = esc_attr( $flash_vars ); + // extract some of the options to insert into the markup + if ( isset( $options['bgcolor'] ) && preg_match( '/^0x[a-f0-9]{6}$/i', $options['bgcolor'] ) ) { + $bgcolor = preg_replace( '/^0x/', '#', $options['bgcolor'] ); + $bgcolor = esc_attr( $bgcolor ); + } else { + $bgcolor = '#FFFFFF'; + } + + if ( isset( $options['width'] ) ) { + $width = intval( $options['width'] ); + } else { + $width = 290; + } + + $loop = ''; + $script_loop = 'false'; + if ( isset( $options['loop'] ) && 'yes' == $options['loop'] ) { + $script_loop = 'true'; + if ( 1 == $num_files ) { + $loop = 'loop'; + } + } + + $volume = 0.6; + if ( isset( $options['initialvolume'] ) && + 0.0 < floatval( $options['initialvolume'] ) && + 100.0 >= floatval( $options['initialvolume'] ) ) { + + $volume = floatval( $options['initialvolume'] )/100.0; + } + + $file_artists = array_pad( array(), $num_files, '' ); + if ( isset( $options['artists'] ) ) { + $artists = preg_split( '/,/', $options['artists'] ); + foreach ( $artists as $i => $artist ) { + $file_artists[$i] = esc_html( $artist ) . ' - '; + } + } + + // generate default titles + $file_titles = array(); + for ( $i = 0; $i < $num_files; $i++ ) { + $file_titles[] = 'Track #' . ($i+1); + } + + // replace with real titles if they exist + if ( isset( $options['titles'] ) ) { + $titles = preg_split( '/,/', $options['titles'] ); + foreach ( $titles as $i => $title ) { + $file_titles[$i] = esc_html( $title ); + } + } + + // fallback for the fallback, just a download link + $not_supported = ''; + foreach ( $sound_files as $sfile ) { + $not_supported .= sprintf( + __( 'Download: <a href="%s">%s</a><br />', 'jetpack' ), + esc_url( $sfile ), + esc_html( basename( $sfile ) ) ); + } + + // HTML5 audio tag + $html5_audio = ''; + $all_mp3 = true; + $add_audio = true; + $num_good = 0; + $to_remove = array(); + foreach ( $sound_files as $i => $sfile ) { + $file_extension = pathinfo( $sfile, PATHINFO_EXTENSION ); + if ( ! preg_match( '/^(mp3|wav|ogg|oga|m4a|aac|webm)$/', $file_extension ) ) { + $html5_audio .= '<!-- Audio shortcode unsupported audio format -->'; + if ( 1 == $num_files ) { + $html5_audio .= $not_supported; + } - if ( isset( $options['bgcolor'] ) ) - $bgcolor = esc_attr( $options['bgcolor'] ); - else - $bgcolor = '#FFFFFF'; + $to_remove[] = $i; // make a note of the bad files + $all_mp3 = false; + continue; + } elseif ( ! preg_match( '/^mp3$/', $file_extension ) ) { + $all_mp3 = false; + } - if ( isset( $options['width'] ) ) - $width = intval( $options['width'] ); - else - $width = 290; + if ( 0 == $i ) { // only need one player + $html5_audio .= <<<AUDIO + <span id="wp-as-{$post->ID}_{$ap_playerID}-container"> + <audio id='wp-as-{$post->ID}_{$ap_playerID}' controls preload='none' $loop style='background-color:$bgcolor;width:{$width}px;'> + <span id="wp-as-{$post->ID}_{$ap_playerID}-nope">$not_supported</span> + </audio> + </span> + <br /> +AUDIO; + } + $num_good++; + } - $swfurl = apply_filters( 'jetpack_static_url', 'http://en.wordpress.com/wp-content/plugins/audio-player/player.swf' ); + // player controls, if needed + if ( 1 < $num_files ) { + $html5_audio .= <<<CONTROLS + <span id='wp-as-{$post->ID}_{$ap_playerID}-controls' style='display:none;'> + <a id='wp-as-{$post->ID}_{$ap_playerID}-prev' + href='javascript:audioshortcode.prev_track( "{$post->ID}_{$ap_playerID}" );' + style='font-size:1.5em;'>«</a> + | + <a id='wp-as-{$post->ID}_{$ap_playerID}-next' + href='javascript:audioshortcode.next_track( "{$post->ID}_{$ap_playerID}", true, $script_loop );' + style='font-size:1.5em;'>»</a> + </span> +CONTROLS; + } + $html5_audio .= "<span id='wp-as-{$post->ID}_{$ap_playerID}-playing'></span>"; - $obj = "<p><object type='application/x-shockwave-flash' data='$swfurl' width='$width' height='24' id='audioplayer1'><param name='movie' value='$swfurl' /><param name='FlashVars' value='{$flash_vars}' /><param name='quality' value='high' /><param name='menu' value='false' /><param name='bgcolor' value='$bgcolor' /><param name='wmode' value='opaque' /></object></p>"; + $swfurl = apply_filters( + 'jetpack_static_url', + 'http://en.wordpress.com/wp-content/plugins/audio-player/player.swf' ); - return "<span style='text-align:left;display:block;'>$obj</span>"; + // process regular flash player, inserting HTML5 tags into object as fallback + if ( $all_mp3 ) { + $audio_tags = <<<FLASH + <object id='wp-as-{$post->ID}_{$ap_playerID}-flash' type='application/x-shockwave-flash' data='$swfurl' width='$width' height='24'> + <param name='movie' value='$swfurl' /> + <param name='FlashVars' value='{$flash_vars}' /> + <param name='quality' value='high' /> + <param name='menu' value='false' /> + <param name='bgcolor' value='$bgcolor' /> + <param name='wmode' value='opaque' /> + $html5_audio + </object> +FLASH; + } else { // just HTML5 for non-mp3 versions + $audio_tags = $html5_audio; + } + + // strip out all the bad files before it reaches .js + foreach ( $to_remove as $i ) { + array_splice( $sound_files, $i, 1 ); + array_splice( $file_artists, $i, 1 ); + array_splice( $file_titles, $i, 1 ); + } + + // mashup the artist/titles for the script + $script_titles = array(); + for ( $i = 0; $i < $num_files; $i++ ) { + $script_titles[] = $file_artists[$i] . $file_titles[$i]; + + } + + // javacript to control audio + $script_files = json_encode( $sound_files ); + $script_titles = json_encode( $script_titles ); + $script = <<<SCRIPT + <script type='text/javascript'> + //<![CDATA[ + jQuery(document).on( 'ready as-script-load', function($) { + if ( typeof window.audioshortcode != 'undefined' ) { + audioshortcode.prep( + '{$post->ID}_{$ap_playerID}', + $script_files, + $script_titles, + $volume, + $script_loop ); + } + } ); + //]]> + </script> +SCRIPT; + + // add the special javascript, if needed + if ( 0 < $num_good ) { + $audio_tags .= $script; + } + return "<span style='text-align:left;display:block;'><p>$audio_tags</p></span>"; + } + + /** + * If the theme uses infinite scroll, include jquery at the start + */ + function check_infinite() { + if ( current_theme_supports( 'infinite-scroll' ) ) { + wp_enqueue_script( 'jquery' ); + } + } + + /** + * Dynamically load the .js, if needed + * + * This hooks in late (priority 11) to infinite_scroll_render to determine + * a posteriori if a shortcode has been called. + */ + function audio_shortcode_infinite() { + // only try to load if a shortcode has been called + if( self::$add_script ) { + $script_url = json_encode( esc_url_raw( plugins_url( 'js/audio-shortcode.js', __FILE__ ) ) ); + + // if the script hasn't been loaded, load it + // if the script loads successfully, fire an 'as-script-load' event + echo <<<SCRIPT + <script type='text/javascript'> + //<![CDATA[ + if ( typeof window.audioshortcode === 'undefined' ) { + var wp_as_js = document.createElement( 'script' ); + wp_as_js.type = 'text/javascript'; + wp_as_js.src = $script_url; + wp_as_js.async = true; + wp_as_js.onload = function() { + jQuery( document.body ).trigger( 'as-script-load' ); + }; + document.getElementsByTagName( 'head' )[0].appendChild( wp_as_js ); + } else { + jQuery( document.body ).trigger( 'as-script-load' ); + } + //]]> + </script> +SCRIPT; + } + } + + /** + * Fixes URLs that have been pasted with spaces: + * [audio http://example.com/Some Cool Music.mp3] + * + * @param string $url + * @return string + */ + function unbreak_spacey_url( $url ) { + return str_replace( ' ', rawurlencode( ' ' ), $url ); + } } -add_shortcode( 'audio', 'audio_shortcode' ); +// kick it all off +new AudioShortcode(); |