next_tag( array( 'class_name' => 'wp-block-gutsliders-videos-carousel' ) ) ) { $processor->set_attribute( 'data-embed-preview', 'true' ); $block_content = $processor->get_updated_html(); } } if ( ! empty( $attrs['videoSchema'] ) ) { $block_content .= $this->get_schema( $attrs ); } return $block_content; } /** * VideoObject structured data for the carousel's videos (Google video results). * Videos without a still image are left out: Google requires one. * * @since 3.1.1 * * @param array $attrs Block attributes. * @return string `'; } /** * A video's upload date (ISO 8601): the one set on the video, else the page's date. * * @since 3.1.1 * * @param array $item Video item. * @return string Date. */ private function get_upload_date( array $item ): string { if ( ! empty( $item['uploadDate'] ) && preg_match( '/^\d{4}-\d{2}-\d{2}$/', (string) $item['uploadDate'] ) ) { try { return ( new \DateTimeImmutable( $item['uploadDate'] . ' 00:00:00', wp_timezone() ) )->format( 'c' ); } catch ( \Exception $e ) { unset( $e ); } } $date = get_the_date( 'c' ); return $date ? (string) $date : gmdate( 'c' ); } /** * "4:12" or "1:02:03" as an ISO 8601 duration (PT4M12S); '' when unreadable. * * @since 3.1.1 * * @param string $duration Duration as shown on the card. * @return string ISO duration. */ private function get_iso_duration( string $duration ): string { if ( ! preg_match( '/^(?:(\d+):)?(\d{1,2}):(\d{2})$/', trim( $duration ), $match ) ) { return ''; } $hours = (int) $match[1]; $minutes = (int) $match[2]; $seconds = (int) $match[3]; return 'PT' . ( $hours ? $hours . 'H' : '' ) . ( $minutes ? $minutes . 'M' : '' ) . $seconds . 'S'; } /** * Adjust the block's iframes and play buttons. * * @since 3.1.1 * * @param string $block_content Rendered block HTML. * @param array $block Parsed block. * @return string Block HTML. */ public function tune_players( $block_content, $block = array() ): string { $block_content = (string) $block_content; if ( false === stripos( $block_content, 'next_tag() ) { $tag = $processor->get_tag(); // Each slide holds one video; count slides to find its item. if ( 'DIV' === $tag && $processor->has_class( 'swiper-slide' ) ) { ++$slide; continue; } $item = isset( $items[ $slide ] ) && is_array( $items[ $slide ] ) ? $items[ $slide ] : array(); $name = $this->get_video_name( $item, max( 0, $slide ) ); if ( 'BUTTON' === $tag && $processor->has_class( 'play-btn' ) && null === $processor->get_attribute( 'aria-label' ) ) { /* translators: %s: video name. */ $processor->set_attribute( 'aria-label', sprintf( __( 'Play video: %s', 'slider-blocks' ), $name ) ); continue; } // Self-hosted players (Classic): a name for screen readers. if ( 'VIDEO' === $tag && $processor->has_class( 'video-carousel-slide' ) ) { if ( null === $processor->get_attribute( 'aria-label' ) ) { $processor->set_attribute( 'aria-label', $name ); } continue; } if ( 'IFRAME' !== $tag ) { continue; } $src = (string) $processor->get_attribute( 'src' ); if ( 'video-carousel-slide' === $processor->get_attribute( 'title' ) ) { $processor->set_attribute( 'title', $name ); } // youtube.com or the privacy-enhanced youtube-nocookie.com. if ( preg_match( '#youtube(?:-nocookie)?\.com/embed#i', $src ) && null === $processor->get_attribute( 'referrerpolicy' ) ) { $processor->set_attribute( 'referrerpolicy', 'strict-origin-when-cross-origin' ); } if ( preg_match( '/[?&]autoplay=1\b/', $src ) ) { $has_thumbnail = $custom_poster && ! empty( $item['thumbnail']['url'] ); if ( 0 === $player && ! $has_thumbnail ) { // Browsers only start playback by themselves when it's muted. $src = (string) preg_replace( '/([?&])mute=0\b/', '$1mute=1', $src ); if ( ! preg_match( '/[?&]mute=1\b/', $src ) ) { $src .= ( false === strpos( $src, '?' ) ? '?' : '&' ) . 'mute=1'; } } else { $src = (string) preg_replace( '/([?&])autoplay=1\b/', '$1autoplay=0', $src ); } $processor->set_attribute( 'src', $src ); } if ( $player > 0 && null === $processor->get_attribute( 'loading' ) ) { $processor->set_attribute( 'loading', 'lazy' ); } ++$player; } return $processor->get_updated_html(); } /** * A human name for a video: its title, its editor name, else "Video N". * * @since 3.1.1 * * @param array $item Video item. * @param int $index Position in the carousel. * @return string Name. */ private function get_video_name( array $item, int $index ): string { foreach ( array( 'title', 'panelTitle' ) as $key ) { if ( ! empty( $item[ $key ] ) && is_string( $item[ $key ] ) ) { return wp_strip_all_tags( $item[ $key ] ); } } /* translators: %d: video position in the carousel. */ return sprintf( __( 'Video %d', 'slider-blocks' ), $index + 1 ); } }