Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
19.86% |
29 / 146 |
|
40.00% |
2 / 5 |
CRAP | |
0.00% |
0 / 1 |
| Jetpack_Brightcove_Shortcode | |
20.28% |
29 / 143 |
|
40.00% |
2 / 5 |
550.81 | |
0.00% |
0 / 1 |
| convert | |
83.33% |
5 / 6 |
|
0.00% |
0 / 1 |
3.04 | |||
| normalize_attributes | |
28.57% |
2 / 7 |
|
0.00% |
0 / 1 |
6.28 | |||
| has_legacy_atts | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
4 | |||
| convert_to_new_studio | |
100.00% |
20 / 20 |
|
100.00% |
1 / 1 |
1 | |||
| convert_to_legacy_studio | |
0.00% |
0 / 108 |
|
0.00% |
0 / 1 |
462 | |||
| 1 | <?php //phpcs:ignore WordPress.Files.FileName.InvalidClassFileName |
| 2 | |
| 3 | use Automattic\Jetpack\Assets; |
| 4 | |
| 5 | if ( ! defined( 'ABSPATH' ) ) { |
| 6 | exit( 0 ); |
| 7 | } |
| 8 | |
| 9 | /** |
| 10 | * Brightcove shortcode. |
| 11 | * |
| 12 | * Brighcove had renovated their video player embedding code since they introduced their "new studio". |
| 13 | * See https://support.brightcove.com/en/video-cloud/docs. |
| 14 | * The new code is not 100% backward compatible, as long as a customized player is used. |
| 15 | * By the time I wrote this, there were about 150000+ posts embedded legacy players, so it would be a bad |
| 16 | * idea either to introduce a new brightcove shortcode, or to break those posts completely. |
| 17 | * |
| 18 | * That's why we introduce a less aggressive way: leaving the old embedding code untouched, and |
| 19 | * introduce a new set of shortcode parameters which are translated to the latest Brightcove embedding code. |
| 20 | * |
| 21 | * e.g. |
| 22 | * [brightcove video_id="12345" account_id="99999"] will be translated to the latest embedding code. |
| 23 | * [brightcove exp=627045696&vid=1415670151] or [brightcove exp=1463233149&vref=1601200825] will be translated |
| 24 | * to the legacy code. |
| 25 | */ |
| 26 | class Jetpack_Brightcove_Shortcode { |
| 27 | /** |
| 28 | * Shortcode name. |
| 29 | * |
| 30 | * @var string |
| 31 | */ |
| 32 | public static $shortcode = 'brightcove'; |
| 33 | |
| 34 | /** |
| 35 | * Parse shortcode arguments and render its output. |
| 36 | * |
| 37 | * @since 4.5.0 |
| 38 | * |
| 39 | * @param array $atts Shortcode parameters. |
| 40 | * |
| 41 | * @return string |
| 42 | */ |
| 43 | public static function convert( $atts ) { |
| 44 | $normalized_atts = self::normalize_attributes( $atts ); |
| 45 | |
| 46 | if ( empty( $atts ) ) { |
| 47 | return '<!-- Missing Brightcove parameters -->'; |
| 48 | } |
| 49 | |
| 50 | return self::has_legacy_atts( $normalized_atts ) |
| 51 | ? self::convert_to_legacy_studio( $normalized_atts ) |
| 52 | : self::convert_to_new_studio( $normalized_atts ); |
| 53 | } |
| 54 | |
| 55 | /** |
| 56 | * We need to take care of two kinds of shortcode format here. |
| 57 | * The latest: [shortcode a=1 b=2] and the legacy: [shortcode a=1&b=2] |
| 58 | * For an old shortcode: [shortcode a=1&b=2&c=3], it would be parsed into array( 'a' => 1&b=2&c=3' ), which is useless. |
| 59 | * However, since we want to determine whether to call convert_to_legacy_studio() or convert_to_new_studio() via passed parameters, we still need to parse the two properly. |
| 60 | * See https://jetpack.wp-a2z.org/oik_api/shortcode_new_to_old_params/ |
| 61 | * |
| 62 | * @since 4.5.0 |
| 63 | * |
| 64 | * @param array $atts Shortcode parameters. |
| 65 | * |
| 66 | * @return array |
| 67 | */ |
| 68 | public static function normalize_attributes( $atts ) { |
| 69 | if ( is_array( $atts ) && 1 === count( $atts ) ) { // this is the case we need to take care of. |
| 70 | $parsed_atts = array(); |
| 71 | $params = shortcode_new_to_old_params( $atts ); |
| 72 | |
| 73 | /** |
| 74 | * Filter the Brightcove shortcode parameters. |
| 75 | * |
| 76 | * @module shortcodes |
| 77 | * |
| 78 | * @since 4.5.0 |
| 79 | * |
| 80 | * @param string $params String of shortcode parameters. |
| 81 | */ |
| 82 | $params = apply_filters( 'brightcove_dimensions', $params ); |
| 83 | parse_str( $params, $parsed_atts ); |
| 84 | |
| 85 | return $parsed_atts; |
| 86 | } else { |
| 87 | return $atts; |
| 88 | } |
| 89 | } |
| 90 | |
| 91 | /** |
| 92 | * Check that it has legacy attributes. |
| 93 | * |
| 94 | * @since 4.5.0 |
| 95 | * |
| 96 | * @param array $atts Shortcode parameters. |
| 97 | * |
| 98 | * @return bool |
| 99 | */ |
| 100 | public static function has_legacy_atts( $atts ) { |
| 101 | return ( isset( $atts['vid'] ) || isset( $atts['vref'] ) ) |
| 102 | && ( isset( $atts['exp'] ) || isset( $atts['exp3'] ) ); |
| 103 | } |
| 104 | |
| 105 | /** |
| 106 | * Convert to latest player format. |
| 107 | * |
| 108 | * @since 4.5.0 |
| 109 | * |
| 110 | * @param array $atts Shortcode parameters. |
| 111 | * |
| 112 | * @return string |
| 113 | */ |
| 114 | public static function convert_to_new_studio( $atts ) { |
| 115 | $defaults = array( |
| 116 | 'account_id' => '', |
| 117 | 'video_id' => '', |
| 118 | 'player_id' => 'default', |
| 119 | 'width' => '100%', |
| 120 | 'height' => '100%', |
| 121 | ); |
| 122 | |
| 123 | $atts_applied = shortcode_atts( $defaults, $atts, self::$shortcode ); |
| 124 | |
| 125 | $player_url = sprintf( |
| 126 | '//players.brightcove.net/%s/%s_default/index.html?videoId=%s', |
| 127 | esc_attr( $atts_applied['account_id'] ), |
| 128 | esc_attr( $atts_applied['player_id'] ), |
| 129 | esc_attr( $atts_applied['video_id'] ) |
| 130 | ); |
| 131 | |
| 132 | $output_html = sprintf( |
| 133 | '<iframe src="' . esc_url( $player_url ) . '" allowfullscreen webkitallowfullscreen mozallowfullscreen style="width: %spx; height: %spx;"></iframe>', |
| 134 | esc_attr( $atts_applied['width'] ), |
| 135 | esc_attr( $atts_applied['height'] ) |
| 136 | ); |
| 137 | |
| 138 | return $output_html; |
| 139 | } |
| 140 | |
| 141 | /** |
| 142 | * Convert to legacy player format. |
| 143 | * |
| 144 | * [brightcove exp=627045696&vid=1415670151] for the older player and backward compatibility |
| 145 | * [brightcove exp=1463233149&vref=1601200825] for the new player |
| 146 | * |
| 147 | * @since 4.5.0 |
| 148 | * |
| 149 | * @param array $atts Shortcode parameters. |
| 150 | * |
| 151 | * @return string |
| 152 | */ |
| 153 | public static function convert_to_legacy_studio( $atts ) { |
| 154 | $attr = shortcode_atts( |
| 155 | array( |
| 156 | 'bg' => '', |
| 157 | 'exp' => '', |
| 158 | 'exp3' => '', |
| 159 | 'h' => '', |
| 160 | 'lbu' => '', |
| 161 | 'pk' => '', |
| 162 | 'pubid' => '', |
| 163 | 's' => '', |
| 164 | 'surl' => '', |
| 165 | 'vid' => '', |
| 166 | 'vref' => '', |
| 167 | 'w' => '', |
| 168 | ), |
| 169 | $atts |
| 170 | ); |
| 171 | |
| 172 | if ( isset( $attr['pk'] ) ) { |
| 173 | $attr['pk'] = rawurlencode( preg_replace( '/[^a-zA-Z0-9!*\'();:@&=+$,\/?#\[\]\-_.~ ]/', '', $attr['pk'] ) ); |
| 174 | } |
| 175 | |
| 176 | if ( isset( $attr['bg'] ) ) { |
| 177 | $attr['bg'] = preg_replace( '![^-a-zA-Z0-9#]!', '', $attr['bg'] ); |
| 178 | } |
| 179 | |
| 180 | $fv = array( |
| 181 | 'viewerSecureGatewayURL' => 'https://services.brightcove.com/services/amfgateway', |
| 182 | 'servicesURL' => 'http://services.brightcove.com/services', |
| 183 | 'cdnURL' => 'http://admin.brightcove.com', |
| 184 | 'autoStart' => 'false', |
| 185 | ); |
| 186 | |
| 187 | $js_tld = 'com'; |
| 188 | $src = ''; |
| 189 | $name = 'flashObj'; |
| 190 | $html5 = false; |
| 191 | |
| 192 | if ( isset( $attr['exp3'] ) ) { |
| 193 | if ( isset( $attr['surl'] ) && strpos( $attr['surl'], 'brightcove.co.jp' ) ) { |
| 194 | $js_tld = 'co.jp'; |
| 195 | } |
| 196 | if ( ! isset( $attr['surl'] ) || ! preg_match( '#^https?://(?:[a-z\d-]+\.)*brightcove\.(?:com|co\.jp)/#', $attr['surl'] ) ) { |
| 197 | $attr['surl'] = 'http://c.brightcove.com/services'; |
| 198 | } |
| 199 | |
| 200 | $attr['exp3'] = (int) $attr['exp3']; |
| 201 | $attr['pubid'] = (int) $attr['pubid']; |
| 202 | $attr['vid'] = (int) $attr['vid']; |
| 203 | |
| 204 | $fv['servicesURL'] = $attr['surl']; |
| 205 | $fv['playerID'] = $attr['exp3']; |
| 206 | $fv['domain'] = 'embed'; |
| 207 | $fv['videoID'] = (int) $attr['vid']; |
| 208 | |
| 209 | $src = sprintf( |
| 210 | '%s/viewer/federated_f9/%s?isVid=1&isUI=1&publisherID=%s', |
| 211 | $attr['surl'], |
| 212 | $attr['exp3'], |
| 213 | $attr['pubid'] |
| 214 | ); |
| 215 | $html5 = true; |
| 216 | } elseif ( isset( $attr['exp'] ) ) { |
| 217 | $attr['exp'] = (int) $attr['exp']; |
| 218 | $src = 'http://services.brightcove.com/services/viewer/federated_f8/' . $attr['exp']; |
| 219 | if ( $attr['vid'] ) { |
| 220 | $fv['videoId'] = $attr['vid']; |
| 221 | } elseif ( $attr['vref'] ) { |
| 222 | $fv['videoRef'] = $attr['vref']; |
| 223 | } |
| 224 | |
| 225 | $fv['playerId'] = $attr['exp']; |
| 226 | $fv['domain'] = 'embed'; |
| 227 | } else { |
| 228 | return '<small>brightcove error: missing required parameter exp or exp3</small>'; |
| 229 | } |
| 230 | |
| 231 | if ( ! empty( $attr['lbu'] ) ) { |
| 232 | $fv['linkBaseURL'] = $attr['lbu']; |
| 233 | } |
| 234 | |
| 235 | $flashvars = trim( add_query_arg( array_map( 'urlencode', $fv ), '' ), '?' ); |
| 236 | |
| 237 | $width = null; |
| 238 | $height = null; |
| 239 | |
| 240 | if ( ! empty( $attr['w'] ) && ! empty( $attr['h'] ) ) { |
| 241 | $w = abs( (int) $attr['w'] ); |
| 242 | $h = abs( (int) $attr['h'] ); |
| 243 | if ( $w && $h ) { |
| 244 | $width = $w; |
| 245 | $height = $h; |
| 246 | } |
| 247 | } elseif ( empty( $attr['s'] ) || 'l' === $attr['s'] ) { |
| 248 | $width = '480'; |
| 249 | $height = '360'; |
| 250 | } |
| 251 | |
| 252 | if ( empty( $width ) || empty( $height ) ) { |
| 253 | $width = '280'; |
| 254 | $height = '210'; |
| 255 | } |
| 256 | |
| 257 | if ( $html5 ) { |
| 258 | wp_enqueue_script( |
| 259 | 'brightcove-loader', |
| 260 | Assets::get_file_url_for_environment( '_inc/build/shortcodes/js/brightcove.min.js', 'modules/shortcodes/js/brightcove.js' ), |
| 261 | array( 'jquery' ), |
| 262 | 20121127, |
| 263 | false |
| 264 | ); |
| 265 | wp_localize_script( |
| 266 | 'brightcove-loader', |
| 267 | 'brightcoveData', |
| 268 | array( |
| 269 | 'tld' => $js_tld, |
| 270 | ) |
| 271 | ); |
| 272 | |
| 273 | return ' |
| 274 | <object id="myExperience" class="BrightcoveExperience"> |
| 275 | <param name="bgcolor" value="' . esc_attr( $attr['bg'] ) . '" /> |
| 276 | <param name="width" value="' . esc_attr( $width ) . '" /> |
| 277 | <param name="height" value="' . esc_attr( $height ) . '" /> |
| 278 | <param name="playerID" value="' . esc_attr( $attr['exp3'] ) . '" /> |
| 279 | <param name="@videoPlayer" value="' . esc_attr( $attr['vid'] ) . '" /> |
| 280 | <param name="playerKey" value="' . esc_attr( $attr['pk'] ) . '" /> |
| 281 | <param name="isVid" value="1" /> |
| 282 | <param name="isUI" value="1" /> |
| 283 | <param name="dynamicStreaming" value="true" /> |
| 284 | <param name="autoStart" value="false" /> |
| 285 | <param name="secureConnections" value="true" /> |
| 286 | <param name="secureHTMLConnections" value="true" /> |
| 287 | </object>'; |
| 288 | } |
| 289 | |
| 290 | return sprintf( |
| 291 | '<embed src="%s" bgcolor="#FFFFFF" flashvars="%s" base="http://admin.brightcove.com" name="%s" width="%s" height="%s" allowFullScreen="true" seamlesstabbing="false" type="application/x-shockwave-flash" swLiveConnect="true" pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash" />', |
| 292 | esc_url( $src ), |
| 293 | $flashvars, |
| 294 | esc_attr( $name ), |
| 295 | esc_attr( $width ), |
| 296 | esc_attr( $height ) |
| 297 | ); |
| 298 | } |
| 299 | } |
| 300 | |
| 301 | add_shortcode( Jetpack_Brightcove_Shortcode::$shortcode, array( 'Jetpack_Brightcove_Shortcode', 'convert' ) ); |