PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3
Jetpack – WP Security, Backup, Speed, & Growth v16.3
16.3 16.3-beta 16.3-a.5 16.3-a.7 16.3-a.3 16.3-a.1 16.2 16.2-beta 12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 All 508 releases
← All changes | jetpack_vendor/automattic/jetpack-videopress/src/class-initializer.php +198 -27 16.3-a.1 → 16.3 View file →
@@ -11,8 +11,16 @@
11 11 * Initialized the VideoPress package
12 12 */
13 13 class Initializer {
14 14
15 + /**
16 + * Bounds of the Latest Videos Playlist block's "Number of videos" setting;
17 + * the editor control uses the same range.
18 + */
19 + const LATEST_VIDEOS_PLAYLIST_MIN_COUNT = 1;
20 + const LATEST_VIDEOS_PLAYLIST_MAX_COUNT = 20;
21 + const LATEST_VIDEOS_PLAYLIST_DEFAULT_COUNT = 5;
22 +
15 23 const JETPACK_VIDEOPRESS_IFRAME_API_HANDLER = 'jetpack-videopress-iframe-api';
16 24
17 25 /**
18 26 * Initialization optinos
@@ -127,8 +135,9 @@
127 135 new WPCOM_REST_API_V2_Endpoint_VideoPress();
128 136 new WPCOM_REST_API_V2_Endpoint_VideoPress_Caption_Tracks();
129 137 new WPCOM_REST_API_V2_Attachment_VideoPress_Field();
130 138 new WPCOM_REST_API_V2_Attachment_VideoPress_Data();
139 + new WPCOM_REST_API_V2_Endpoint_VideoPress_Edits();
131 140 };
132 141 add_action( 'rest_api_init', $register_rest_api_v2_endpoints, 0 );
133 142 add_action( 'restapi_theme_init', $register_rest_api_v2_endpoints, 0 );
134 143
@@ -194,8 +203,11 @@
194 203 Caption_Tracks::init();
195 204 Initial_State::init();
196 205 XMLRPC::init();
197 206 Block_Editor_Content::init();
207 + Channel::init();
208 + Playlist_Index::init();
209 + Analytics_Dashboard::init();
198 210
199 211 /*
200 212 * These endpoints only add their routes on REST init, so defer calling
201 213 * init() (and autoloading the endpoint classes) until a REST request is
@@ -276,11 +288,30 @@
276 288 self::register_videopress_video_block();
277 289
278 290 // Register Video Playlist block.
279 291 self::register_videopress_playlist_block();
292 +
293 + // Register Latest Videos Playlist block.
294 + self::register_videopress_latest_videos_playlist_block();
295 +
296 + // Register All Playlists block.
297 + self::register_videopress_all_playlists_block();
280 298 }
281 299
282 300 /**
301 + * Register the All Playlists block, which lists the site's Video Playlist
302 + * blocks from the playlist index.
303 + *
304 + * @param string|null $metadata_file Path to the block.json metadata file. Defaults to the
305 + * package build output; tests can point it at a fixture.
306 + *
307 + * @return void
308 + */
309 + public static function register_videopress_all_playlists_block( $metadata_file = null ) {
310 + All_Playlists_Block::register( $metadata_file );
311 + }
312 +
313 + /**
283 314 * VideoPress video block render method
284 315 *
285 316 * @global \WP_Embed $wp_embed WordPress embed handler.
286 317 *
@@ -428,9 +459,13 @@
428 459 $video_wrapper_classes,
429 460 Inline_Player::render(
430 461 $guid,
431 462 Inline_Player::get_player_options( $block_attributes ),
432 - $block_attributes['videoRatio'] ?? null
463 + $block_attributes['videoRatio'] ?? null,
464 + array(
465 + 'poster' => Inline_Player::get_poster_url( $guid, $block_attributes ),
466 + 'title' => $block_attributes['title'] ?? '',
467 + )
433 468 )
434 469 );
435 470 } elseif ( $videopress_url ) {
436 471 $videopress_url = wp_kses_post( $videopress_url );
@@ -630,8 +665,77 @@
630 665 );
631 666 }
632 667
633 668 /**
669 + * Register the Latest Videos Playlist block.
670 + *
671 + * It reuses the Video Playlist block's registered view script and styles, so
672 + * it is only registered once that block is. Its inner Video Playlist block is
673 + * the editor canvas only: the front end renders the newest videos fresh.
674 + *
675 + * @param string|null $metadata_file Path to the block.json metadata file. Defaults to the
676 + * package build output; tests can point it at a fixture.
677 + *
678 + * @return void
679 + */
680 + public static function register_videopress_latest_videos_playlist_block( $metadata_file = null ) {
681 + if ( ! \WP_Block_Type_Registry::get_instance()->is_registered( 'videopress/playlist' ) ) {
682 + return;
683 + }
684 +
685 + if ( null === $metadata_file ) {
686 + $metadata_file = __DIR__ . '/../build/block-editor/blocks/latest-videos-playlist/block.json';
687 + }
688 +
689 + if ( ! file_exists( $metadata_file ) ) {
690 + return;
691 + }
692 +
693 + $metadata = json_decode(
694 + // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
695 + file_get_contents( $metadata_file )
696 + );
697 +
698 + if ( empty( $metadata->name )
699 + || \WP_Block_Type_Registry::get_instance()->is_registered( $metadata->name )
700 + ) {
701 + return;
702 + }
703 +
704 + register_block_type(
705 + $metadata_file,
706 + array(
707 + 'render_callback' => array( __CLASS__, 'render_videopress_latest_videos_playlist_block' ),
708 + 'skip_inner_blocks' => true,
709 + )
710 + );
711 + }
712 +
713 + /**
714 + * Latest Videos Playlist block render callback: the newest VideoPress videos
715 + * on the site, rendered by the Video Playlist block's callback.
716 + *
717 + * @param array $block_attributes Block attributes.
718 + * @param string $content Current block markup, unused: the inner block is never rendered.
719 + * @param \WP_Block|null $block Current block.
720 + *
721 + * @return string Block markup, or an empty string when the site has no VideoPress videos.
722 + */
723 + public static function render_videopress_latest_videos_playlist_block( $block_attributes, $content = '', $block = null ) {
724 + $count = isset( $block_attributes['count'] ) && is_numeric( $block_attributes['count'] )
725 + ? (int) $block_attributes['count']
726 + : self::LATEST_VIDEOS_PLAYLIST_DEFAULT_COUNT;
727 + $count = max( self::LATEST_VIDEOS_PLAYLIST_MIN_COUNT, min( self::LATEST_VIDEOS_PLAYLIST_MAX_COUNT, $count ) );
728 +
729 + $block_attributes['videos'] = Data::get_latest_videopress_playlist_entries( $count );
730 +
731 + // Dynamic playlists have no title of their own, so no heading either.
732 + unset( $block_attributes['playlistTitle'], $block_attributes['showPlaylistTitle'] );
733 +
734 + return self::render_videopress_playlist_block( $block_attributes, '', $block );
735 + }
736 +
737 + /**
634 738 * Sanitize the playlist block's videos attribute into rendering-ready entries.
635 739 *
636 740 * @param mixed $videos Raw attribute value.
637 741 *
@@ -636,9 +740,9 @@
636 740 * @param mixed $videos Raw attribute value.
637 741 *
638 742 * @return array Entries with guid, title, durationMs, height and poster keys.
639 743 */
640 - private static function sanitize_playlist_entries( $videos ) {
744 + public static function sanitize_playlist_entries( $videos ) {
641 745 if ( ! is_array( $videos ) ) {
642 746 return array();
643 747 }
644 748
@@ -765,9 +869,9 @@
765 869 /**
766 870 * Video Playlist block render callback.
767 871 *
768 872 * @param array $block_attributes Block attributes.
769 - * @param string $content Current block markup.
873 + * @param string $content Rendered inner blocks: the title heading, when there is one.
770 874 * @param \WP_Block|null $block Current block.
771 875 *
772 876 * @return string Block markup, or an empty string when the playlist has no playable entries.
773 877 */
@@ -793,8 +897,14 @@
793 897 $layout = isset( $block_attributes['layout'] ) && in_array( $block_attributes['layout'], array( 'side-rail', 'grid', 'strip' ), true )
794 898 ? $block_attributes['layout']
795 899 : 'side-rail';
796 900
901 + $show_player = $enabled( 'showPlayer' );
902 + // A hidden player can still be revealed by the first click on an entry.
903 + $reveal_player = ! $show_player
904 + && isset( $block_attributes['entryClickAction'] )
905 + && 'show-player' === $block_attributes['entryClickAction'];
906 + $has_player = $show_player || $reveal_player;
797 907 $show_thumbnail = $enabled( 'showThumbnail' );
798 908 $show_title = $enabled( 'showTitle' );
799 909 $show_res = $enabled( 'showResolution' );
800 910 $show_duration = $enabled( 'showDuration' );
@@ -805,8 +915,11 @@
805 915 $classes = array( 'videopress-playlist', 'is-layout-' . $layout );
806 916 if ( $enabled( 'darkPlayer', false ) ) {
807 917 $classes[] = 'is-dark';
808 918 }
919 + if ( ! $show_player ) {
920 + $classes[] = 'hide-player';
921 + }
809 922 if ( ! $show_thumbnail ) {
810 923 $classes[] = 'hide-thumbnails';
811 924 }
812 925 if ( ! $show_title ) {
@@ -882,28 +995,57 @@
882 995 $duration_markup = '' !== $timecode
883 996 ? sprintf( '<span class="videopress-playlist__entry-duration">%s</span>', esc_html( $timecode ) )
884 997 : '';
885 998
999 + if ( $has_player ) {
1000 + $is_current = $show_player && 0 === $index;
1001 + $entry_open = sprintf(
1002 + '<button type="button" class="videopress-playlist__select%1$s"%2$s data-guid="%3$s" data-embed-url="%4$s" data-title="%5$s" data-position="%6$s" data-details="%7$s" data-progress="%8$s">',
1003 + $is_current ? ' is-current' : '',
1004 + $is_current ? ' aria-current="true"' : '',
1005 + esc_attr( $entry['guid'] ),
1006 + esc_url( self::playlist_embed_url( $entry['guid'], true, $muted ) ),
1007 + esc_attr( $title ),
1008 + esc_attr( $position ),
1009 + esc_attr( $details ),
1010 + esc_attr( $progress )
1011 + );
1012 + $entry_close = '</button>';
1013 + } else {
1014 + // No player to load the video into: the entry opens its VideoPress page instead.
1015 + $entry_open = sprintf(
1016 + '<a class="videopress-playlist__select" href="%1$s" target="_blank" rel="noopener noreferrer" data-guid="%2$s" data-title="%3$s" data-position="%4$s" data-details="%5$s">',
1017 + /**
1018 + * Filters where a playlist entry opens when the block has no player.
1019 + *
1020 + * @since 0.55.0
1021 + *
1022 + * @param string $url The video's page on videopress.com.
1023 + * @param string $guid The video GUID.
1024 + */
1025 + esc_url( apply_filters( 'videopress_playlist_entry_url', 'https://videopress.com/v/' . $entry['guid'], $entry['guid'] ) ),
1026 + esc_attr( $entry['guid'] ),
1027 + esc_attr( $title ),
1028 + esc_attr( $position ),
1029 + esc_attr( $details )
1030 + );
1031 + $entry_close = '</a>';
1032 + }
1033 +
886 1034 $items .= sprintf(
887 - '<li class="videopress-playlist__entry"><button type="button" class="videopress-playlist__select%1$s"%2$s data-guid="%3$s" data-embed-url="%4$s" data-title="%5$s" data-position="%6$s" data-details="%7$s" data-progress="%8$s">' .
888 - '%9$s<span class="videopress-playlist__entry-thumb"><span class="videopress-playlist__entry-flag">%10$s</span>%15$s%11$s</span>' .
889 - '<span class="videopress-playlist__entry-body"><span class="videopress-playlist__entry-title">%12$s</span><span class="videopress-playlist__entry-meta">%13$s%14$s</span></span>' .
890 - '</button></li>',
891 - 0 === $index ? ' is-current' : '',
892 - 0 === $index ? ' aria-current="true"' : '',
893 - esc_attr( $entry['guid'] ),
894 - esc_url( self::playlist_embed_url( $entry['guid'], true, $muted ) ),
895 - esc_attr( $title ),
896 - esc_attr( $position ),
897 - esc_attr( $details ),
898 - esc_attr( $progress ),
1035 + '<li class="videopress-playlist__entry">%1$s' .
1036 + '%2$s<span class="videopress-playlist__entry-thumb"><span class="videopress-playlist__entry-flag">%3$s</span>%4$s%5$s</span>' .
1037 + '<span class="videopress-playlist__entry-body"><span class="videopress-playlist__entry-title">%6$s</span><span class="videopress-playlist__entry-meta">%7$s%8$s</span></span>' .
1038 + '%9$s</li>',
1039 + $entry_open,
899 1040 $number_markup,
900 1041 esc_html__( 'Playing', 'jetpack-videopress-pkg' ),
1042 + $lock_markup,
901 1043 $time_markup,
902 1044 esc_html( $title ),
903 1045 $resolution_markup,
904 1046 $duration_markup,
905 - $lock_markup
1047 + $entry_close
906 1048 );
907 1049 }
908 1050
909 1051 $first = $entries[0];
@@ -930,17 +1072,30 @@
930 1072 esc_html( $count_label . ' · ' . $runtime_label )
931 1073 )
932 1074 : '';
933 1075
934 - $stage_markup = sprintf(
935 - '<div class="videopress-playlist__stage">' .
936 - '<div class="videopress-playlist__player"><iframe class="videopress-playlist__iframe" title="%1$s" src="%2$s" allowfullscreen allow="clipboard-write"></iframe></div>%3$s</div>',
937 - esc_attr( $first_title ),
938 - esc_url( self::playlist_embed_url( $first['guid'], false, $muted ) ),
939 - $now_markup
940 - );
1076 + if ( $show_player ) {
1077 + $stage_markup = sprintf(
1078 + '<div class="videopress-playlist__stage">' .
1079 + '<div class="videopress-playlist__player"><iframe class="videopress-playlist__iframe" title="%1$s" src="%2$s" allowfullscreen allow="clipboard-write"></iframe></div>%3$s</div>',
1080 + esc_attr( $first_title ),
1081 + esc_url( self::playlist_embed_url( $first['guid'], false, $muted ) ),
1082 + $now_markup
1083 + );
1084 + } elseif ( $reveal_player ) {
1085 + // No src: nothing loads until the view script reveals the stage on a click.
1086 + $stage_markup = sprintf(
1087 + '<div class="videopress-playlist__stage" hidden>' .
1088 + '<div class="videopress-playlist__player"><iframe class="videopress-playlist__iframe" title="%1$s" allowfullscreen allow="clipboard-write"></iframe></div></div>%2$s',
1089 + esc_attr( $first_title ),
1090 + $now_markup
1091 + );
1092 + } else {
1093 + // Without a player only the grid layout's runtime line remains of the stage.
1094 + $stage_markup = $now_markup;
1095 + }
941 1096
942 - $progress_markup = '' !== $total_timecode
1097 + $progress_markup = $has_player && '' !== $total_timecode
943 1098 ? sprintf(
944 1099 '<span class="videopress-playlist__list-progress">%s</span>',
945 1100 /* translators: 1: position of the current video. 2: number of videos. 3: total playlist timecode. */
946 1101 esc_html( sprintf( __( '%1$d / %2$d · %3$s total', 'jetpack-videopress-pkg' ), 1, $count, $total_timecode ) )
@@ -952,9 +1107,11 @@
952 1107 '<div class="videopress-playlist__list-header">' .
953 1108 '<span class="videopress-playlist__list-label videopress-playlist__list-label--rail">%1$s</span>' .
954 1109 '<span class="videopress-playlist__list-label videopress-playlist__list-label--strip">%2$s</span>%3$s%4$s</div>' .
955 1110 '<ol class="videopress-playlist__entries">%5$s</ol></div>',
956 - esc_html__( 'Up next', 'jetpack-videopress-pkg' ),
1111 + $show_player
1112 + ? esc_html__( 'Up next', 'jetpack-videopress-pkg' )
1113 + : esc_html__( 'Playlist', 'jetpack-videopress-pkg' ),
957 1114 /* translators: %s: number of videos in the playlist, e.g. "5 videos". */
958 1115 esc_html( sprintf( __( 'Playlist — %s', 'jetpack-videopress-pkg' ), $count_label ) ),
959 1116 $list_meta_markup,
960 1117 $progress_markup,
@@ -991,11 +1148,21 @@
991 1148 }
992 1149
993 1150 $wrapper_attributes = get_block_wrapper_attributes( $wrapper_extra_attributes );
994 1151
1152 + // The Heading inner block saved with the post; an empty title renders none.
1153 + $playlist_title = isset( $block_attributes['playlistTitle'] ) && is_string( $block_attributes['playlistTitle'] )
1154 + ? trim( $block_attributes['playlistTitle'] )
1155 + : '';
1156 + $content = is_string( $content ) ? trim( $content ) : '';
1157 + $heading_markup = $enabled( 'showPlaylistTitle' ) && '' !== $playlist_title && '' !== $content
1158 + ? '<div class="videopress-playlist__heading">' . $content . '</div>'
1159 + : '';
1160 +
995 1161 return sprintf(
996 - '<figure %1$s><div class="videopress-playlist__body">%2$s%3$s</div></figure>',
1162 + '<figure %1$s>%2$s<div class="videopress-playlist__body">%3$s%4$s</div></figure>',
997 1163 $wrapper_attributes,
1164 + $heading_markup,
998 1165 $stage_markup,
999 1166 $list_markup
1000 1167 );
1001 1168 }
@@ -1073,10 +1240,14 @@
1073 1240 if ( null === $guid ) {
1074 1241 return null;
1075 1242 }
1076 1243
1244 + $attributes = Inline_Player::get_attributes_from_embed_url( $url );
1245 +
1077 1246 return Inline_Player::render(
1078 1247 $guid,
1079 - Inline_Player::get_player_options( Inline_Player::get_attributes_from_embed_url( $url ) )
1248 + Inline_Player::get_player_options( $attributes ),
1249 + null,
1250 + array( 'poster' => Inline_Player::get_poster_url( $guid, $attributes ) )
1080 1251 );
1081 1252 }
1082 1253 }