Make WordPress Core

Changeset 38985


Ignore:
Timestamp:
10/27/2016 09:50:56 PM (8 years ago)
Author:
joemcgill
Message:

Themes: Enable video in custom headers.

This adds the ability for themes to add support for videos in custom headers
by passing 'video' => true as an argument when adding theme support for
custom headers.

Custom video headers are managed through the “Header Visuals” (i.e. “Header Image”)
panel in the Customizer where you can select a video from the media library or set a
URL to an external video (YouTube for now) for use in custom headers.

This introduces several new functions:

has_header_video() – Check whether a header video is set or not.
get_header_video_url() – Retrieve header video URL for custom header.
the_header_video_url() – Display header video URL.
get_header_video_settings() – Retrieve header video settings.
has_custom_header() – Check whether a custom header is set or not.
get_custom_header_markup() – Retrieve the markup for a custom header.
the_custom_header_markup() – Print the markup for a custom header.

And a new file, wp-includes/js/wp-custom-header.js that handles loading videos
in custom headers.

This also enables video headers in the Twenty Seventeen and Twenty Fourteen themes.

Props davidakennedy, celloexpressions, bradyvercher, laurelfulford, joemcgill.
Fixes #38172.

Location:
trunk/src
Files:
1 added
18 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-content/themes/twentyfourteen/functions.php

    r38870 r38985  
    435435    }
    436436
    437     if ( get_header_image() ) {
     437    if ( get_header_image() || function_exists( 'has_header_video' ) && has_header_video() ) {
    438438        $classes[] = 'header-image';
    439439    } elseif ( ! in_array( $GLOBALS['pagenow'], array( 'wp-activate.php', 'wp-signup.php' ) ) ) {
  • trunk/src/wp-content/themes/twentyfourteen/header.php

    r31794 r38985  
    3333<body <?php body_class(); ?>>
    3434<div id="page" class="hfeed site">
    35     <?php if ( get_header_image() ) : ?>
     35    <?php if ( function_exists( 'has_header_video' ) && has_header_video() ) : ?>
     36        <div id="site-header">
     37            <?php the_custom_header_markup(); ?>
     38        </div>
     39    <?php elseif ( get_header_image() ) : ?>
    3640    <div id="site-header">
    3741        <a href="<?php echo esc_url( home_url( '/' ) ); ?>" rel="home">
  • trunk/src/wp-content/themes/twentyfourteen/inc/custom-header.php

    r31250 r38985  
    4141        'height'                 => 240,
    4242        'flex-height'            => true,
     43        'video'                  => true,
    4344        'wp-head-callback'       => 'twentyfourteen_header_style',
    4445        'admin-head-callback'    => 'twentyfourteen_admin_header_style',
  • trunk/src/wp-content/themes/twentyfourteen/inc/customizer.php

    r36797 r38985  
    1717function twentyfourteen_customize_register( $wp_customize ) {
    1818    // Add postMessage support for site title and description.
    19     $wp_customize->get_setting( 'blogname' )->transport         = 'postMessage';
    20     $wp_customize->get_setting( 'blogdescription' )->transport  = 'postMessage';
    21     $wp_customize->get_setting( 'header_textcolor' )->transport = 'postMessage';
     19    $wp_customize->get_setting( 'blogname' )->transport          = 'postMessage';
     20    $wp_customize->get_setting( 'blogdescription' )->transport   = 'postMessage';
     21    $wp_customize->get_setting( 'header_textcolor' )->transport  = 'postMessage';
     22    $wp_customize->get_setting( 'header_image' )->transport      = 'postMessage';
     23    $wp_customize->get_setting( 'header_image_data' )->transport = 'postMessage';
    2224
    2325    if ( isset( $wp_customize->selective_refresh ) ) {
  • trunk/src/wp-content/themes/twentyfourteen/js/functions.js

    r37040 r38985  
    9696        if ( _window.width() > 781 ) {
    9797            var mastheadHeight = $( '#masthead' ).height(),
    98                 toolbarOffset, mastheadOffset;
     98                mastheadOffset;
    9999
    100100            if ( mastheadHeight > 48 ) {
     
    102102            }
    103103
     104            mastheadOffset = $( '#site-header' ).height();
     105
    104106            if ( body.is( '.header-image' ) ) {
    105                 toolbarOffset  = body.is( '.admin-bar' ) ? $( '#wpadminbar' ).height() : 0;
    106                 mastheadOffset = $( '#masthead' ).offset().top - toolbarOffset;
     107
     108                // Recaculate the header height when a custom header loads.
     109                $( 'body' ).on( 'wp-custom-header-video-loaded', function() {
     110                    mastheadOffset = $( '#site-header' ).height();
     111                } );
    107112
    108113                _window.on( 'scroll.twentyfourteen', function() {
     
    113118                    }
    114119                } );
     120
     121                // Update masthead offset after a selective refresh.
     122                if ( 'undefined' !== typeof wp && wp.customize && wp.customize.selectiveRefresh ) {
     123                    wp.customize.selectiveRefresh.bind( 'partial-content-rendered', function() {
     124                        mastheadOffset = $( '#site-header' ).height();
     125                    } );
     126                }
    115127            }
    116128        }
  • trunk/src/wp-content/themes/twentyfourteen/style.css

    r38967 r38985  
    8989    display: inline-block;
    9090    max-width: 100%;
     91    height: auto;
    9192}
    9293
     
    607608    margin-bottom: 24px;
    608609    max-width: 100%;
     610}
     611
     612#wp-custom-header iframe,
     613#wp-custom-header video {
     614    margin-bottom: -8px;
    609615}
    610616
  • trunk/src/wp-content/themes/twentyseventeen/assets/css/ie8.css

    r38962 r38985  
    6767.site-branding {
    6868    padding: 45px 0;
     69}
     70
     71.has-header-image .custom-header-image img,
     72.has-header-image .custom-header-image video {
     73    left: 0;
     74    top: 0;
    6975}
    7076
  • trunk/src/wp-content/themes/twentyseventeen/footer.php

    r38875 r38985  
    1515?>
    1616
    17     </div><!-- #content -->
     17        </div><!-- #content -->
    1818
    19     <footer id="colophon" class="site-footer" role="contentinfo">
    20         <div class="wrap">
    21             <?php
    22             get_template_part( 'template-parts/footer/footer', 'widgets' );
     19        <footer id="colophon" class="site-footer" role="contentinfo">
     20            <div class="wrap">
     21                <?php
     22                get_template_part( 'template-parts/footer/footer', 'widgets' );
    2323
    24             if ( has_nav_menu( 'social' ) ) : ?>
    25                 <nav class="social-navigation" role="navigation" aria-label="<?php _e( 'Footer Social Links Menu', 'twentyseventeen' ); ?>">
    26                     <?php
    27                         wp_nav_menu( array(
    28                             'theme_location' => 'social',
    29                             'menu_class'     => 'social-links-menu',
    30                             'depth'          => 1,
    31                             'link_before'    => '<span class="screen-reader-text">',
    32                             'link_after'     => '</span>' . twentyseventeen_get_svg( array( 'icon' => 'chain' ) ),
    33                         ) );
    34                     ?>
    35                 </nav><!-- .social-navigation -->
    36             <?php endif;
     24                if ( has_nav_menu( 'social' ) ) : ?>
     25                    <nav class="social-navigation" role="navigation" aria-label="<?php _e( 'Footer Social Links Menu', 'twentyseventeen' ); ?>">
     26                        <?php
     27                            wp_nav_menu( array(
     28                                'theme_location' => 'social',
     29                                'menu_class'     => 'social-links-menu',
     30                                'depth'          => 1,
     31                                'link_before'    => '<span class="screen-reader-text">',
     32                                'link_after'     => '</span>' . twentyseventeen_get_svg( array( 'icon' => 'chain' ) ),
     33                            ) );
     34                        ?>
     35                    </nav><!-- .social-navigation -->
     36                <?php endif;
    3737
    38             get_template_part( 'template-parts/footer/site', 'info' );
    39             ?>
    40         </div><!-- .wrap -->
    41     </footer><!-- #colophon -->
     38                get_template_part( 'template-parts/footer/site', 'info' );
     39                ?>
     40            </div><!-- .wrap -->
     41        </footer><!-- #colophon -->
     42    </div><!-- .site-content-contain -->
    4243</div><!-- #page -->
    4344<?php wp_footer(); ?>
  • trunk/src/wp-content/themes/twentyseventeen/header.php

    r38875 r38985  
    5050    ?>
    5151
    52     <div id="content" class="site-content">
     52    <div class="site-content-contain">
     53        <div id="content" class="site-content">
  • trunk/src/wp-content/themes/twentyseventeen/inc/custom-header.php

    r38846 r38985  
    4040        'height'             => 1200,
    4141        'flex-height'        => true,
     42        'video'              => true,
    4243        'wp-head-callback'   => 'twentyseventeen_header_style',
    4344    ) ) );
  • trunk/src/wp-content/themes/twentyseventeen/inc/customizer.php

    r38966 r38985  
    1414 */
    1515function twentyseventeen_customize_register( $wp_customize ) {
    16     $wp_customize->get_setting( 'blogname' )->transport         = 'postMessage';
    17     $wp_customize->get_setting( 'blogdescription' )->transport  = 'postMessage';
    18     $wp_customize->get_setting( 'header_textcolor' )->transport = 'postMessage';
     16    $wp_customize->get_setting( 'blogname' )->transport          = 'postMessage';
     17    $wp_customize->get_setting( 'blogdescription' )->transport   = 'postMessage';
     18    $wp_customize->get_setting( 'header_textcolor' )->transport  = 'postMessage';
     19    $wp_customize->get_setting( 'header_image' )->transport      = 'postMessage';
     20    $wp_customize->get_setting( 'header_image_data' )->transport = 'postMessage';
    1921
    2022    $wp_customize->selective_refresh->add_partial( 'blogname', array(
  • trunk/src/wp-content/themes/twentyseventeen/inc/template-functions.php

    r38868 r38985  
    3636
    3737    // Add a class if there is a custom header.
    38     if ( has_header_image() ) {
     38    if ( has_header_image() || has_header_video() && is_front_page() ) {
    3939        $classes[] = 'has-header-image';
    4040    }
  • trunk/src/wp-content/themes/twentyseventeen/style.css

    r38969 r38985  
    13151315    font-size: 16px;
    13161316    font-size: 1rem;
     1317    position: relative;
    13171318}
    13181319
     
    15561557.site-branding {
    15571558    padding: 1em 0;
     1559    position: relative;
    15581560    -webkit-transition: margin-bottom 0.2s;
    15591561    transition: margin-bottom 0.2s;
     1562    z-index: 3;
    15601563}
    15611564
     
    16511654
    16521655.custom-header-image {
    1653     background-position: center center;
    1654     background-repeat: no-repeat;
    1655     -webkit-background-size: cover;
    1656     background-size: cover;
    16571656    bottom: 0;
    16581657    left: 0;
     1658    overflow: hidden;
    16591659    position: absolute;
    16601660    right: 0;
    16611661    top: 0;
     1662    width: 100%;
    16621663}
    16631664
     
    16751676    position: absolute;
    16761677    right: 0;
    1677 }
    1678 
    1679 .has-header-image:not(.twentyseventeen-front-page):not(.home) .custom-header-image {
    1680     background-position: center bottom;
     1678    z-index: 2;
     1679}
     1680
     1681.has-header-image .custom-header-image img,
     1682.has-header-image .custom-header-image video,
     1683.has-header-image .custom-header-image iframe {
     1684    position: fixed;
     1685    height: auto;
     1686    left: 50%;
     1687    max-width: 1000%;
     1688    min-height: 100%;
     1689    min-width: 100%;
     1690    min-width: 100vw; /* vw prevents 1px gap on left that 100% has */
     1691    width: auto;
     1692    top: 50%;
     1693    -ms-transform: translateX(-50%) translateY(-50%);
     1694    -moz-transform: translateX(-50%) translateY(-50%);
     1695    -webkit-transform: translateX(-50%) translateY(-50%);
     1696    transform: translateX(-50%) translateY(-50%);
     1697}
     1698
     1699.has-header-image:not(.twentyseventeen-front-page):not(.home) .custom-header-image img {
     1700    bottom: 0;
     1701    position: absolute;
     1702    top: auto;
     1703    -ms-transform: translateX(-50%) translateY(0);
     1704    -moz-transform: translateX(-50%) translateY(0);
     1705    -webkit-transform: translateX(-50%) translateY(0);
     1706    transform: translateX(-50%) translateY(0);
    16811707}
    16821708
     
    17771803## Regular Content
    17781804--------------------------------------------------------------*/
     1805
     1806.site-content-contain {
     1807    background-color: #fff;
     1808    position: relative;
     1809}
    17791810
    17801811.site-content {
     
    26432674--------------------------------------------------------------*/
    26442675
    2645 img {
     2676img,
     2677video {
    26462678    height: auto; /* Make sure images are scaled correctly. */
    26472679    max-width: 100%; /* Adhere to container width. */
     
    32883320    .has-header-image.twentyseventeen-front-page .custom-header,
    32893321    .has-header-image.home.blog .custom-header {
    3290         display: block;
    32913322        min-height: 0;
    32923323    }
     
    32943325    .custom-header-image {
    32953326        height: 165px;
     3327        position: relative;
     3328    }
     3329
     3330    .twentyseventeen-front-page.has-header-image .custom-header-image,
     3331    .home.blog.has-header-image .custom-header-image {
     3332        height: 0;
    32963333        position: relative;
    32973334    }
     
    33043341        right: 0;
    33053342        top: 0;
    3306     }
    3307 
    3308     .twentyseventeen-front-page.has-header-image .custom-header-image,
    3309     .home.blog.has-header-image .custom-header-image {
    3310         height: 0;
    3311         padding-top: 66%;
    3312         position: relative;
    33133343    }
    33143344
     
    35923622        height: 100vh;
    35933623        max-height: 100%;
    3594         padding: 10% 0;
     3624        overflow: hidden;
     3625        /* padding: 10% 0; */
    35953626    }
    35963627
     
    39383969
    39393970@media screen and ( min-width: 55em ) {
    3940 
    3941     .twentyseventeen-front-page.has-header-image .custom-header-image,
    3942     .home.blog.has-header-image .custom-header-image {
    3943         background-attachment: fixed;
    3944     }
    39453971
    39463972    .panel-image {
  • trunk/src/wp-content/themes/twentyseventeen/template-parts/header/header-image.php

    r38875 r38985  
    1515
    1616    // Check if Custom Header image has been added.
    17     if ( ! empty( $header_image ) ) : ?>
     17    if ( has_custom_header() ) :
     18    ?>
    1819
    19         <div class="custom-header-image" style="background-image: url(<?php echo esc_url( $header_image ); ?>)"></div>
     20        <?php // Output the full custom header - video and/or image fallback. ?>
     21        <div class="custom-header-image">
     22            <?php the_custom_header_markup(); ?>
     23        </div>
    2024        <?php get_template_part( 'template-parts/header/site', 'branding' ); ?>
    2125
    2226    <?php else : ?>
     27
    2328        <?php // Otherwise, show a blank header. ?>
    2429        <div class="custom-header-simple">
  • trunk/src/wp-includes/class-wp-customize-manager.php

    r38948 r38985  
    363363        add_action( 'customize_controls_print_footer_scripts', array( $this, 'render_section_templates' ), 1 );
    364364        add_action( 'customize_controls_print_footer_scripts', array( $this, 'render_control_templates' ), 1 );
     365
     366        // Export header video settings with the partial response.
     367        add_filter( 'customize_render_partials_response', array( $this, 'export_header_video_settings' ), 10, 3 );
    365368
    366369        // Export the settings to JS via the _wpCustomizeSettings variable.
     
    32503253        /* Custom Header */
    32513254
     3255        if ( current_theme_supports( 'custom-header', 'video' ) ) {
     3256            $title = __( 'Header Visuals' );
     3257            $description = __( 'If you add a video, the image will be used as a fallback while the video loads.' );
     3258            $width = absint( get_theme_support( 'custom-header', 'width' ) );
     3259            $height = absint( get_theme_support( 'custom-header', 'height' ) );
     3260            if ( $width && $height ) {
     3261                /* translators: %s: header size in pixels */
     3262                $control_description = sprintf( __( 'Upload your video in <code>.mp4</code> format and minimize its file size for best results. Your theme recommends dimensions of %s pixels.' ),
     3263                    sprintf( '<strong>%s &times; %s</strong>', $width, $height )
     3264                );
     3265            } elseif ( $width ) {
     3266                /* translators: %s: header width in pixels */
     3267                $control_description = sprintf( __( 'Upload your video in <code>.mp4</code> format and minimize its file size for best results. Your theme recommends a width of %s pixels.' ),
     3268                    sprintf( '<strong>%s</strong>', $width )
     3269                );
     3270            } else {
     3271                /* translators: %s: header height in pixels */
     3272                $control_description = sprintf( __( 'Upload your video in <code>.mp4</code> format and minimize its file size for best results. Your theme recommends a height of %s pixels.' ),
     3273                    sprintf( '<strong>%s</strong>', $height )
     3274                );
     3275            }
     3276        } else {
     3277            $title = __( 'Header Image' );
     3278            $description = '';
     3279            $control_description = '';
     3280        }
     3281
    32523282        $this->add_section( 'header_image', array(
    3253             'title'          => __( 'Header Image' ),
     3283            'title'          => $title,
     3284            'description'    => $description,
    32543285            'theme_supports' => 'custom-header',
    32553286            'priority'       => 60,
     3287        ) );
     3288
     3289        $this->add_setting( 'header_video', array(
     3290            'theme_supports'    => array( 'custom-header', 'video' ),
     3291            'transport'         => 'postMessage',
     3292            'sanitize_callback' => 'absint',
     3293            'validate_callback' => array( $this, '_validate_header_video' ),
     3294        ) );
     3295
     3296        $this->add_setting( 'external_header_video', array(
     3297            'theme_supports'    => array( 'custom-header', 'video' ),
     3298            'transport'         => 'postMessage',
     3299            'sanitize_callback' => 'esc_url',
     3300            'validate_callback' => array( $this, '_validate_external_header_video' ),
    32563301        ) );
    32573302
     
    32663311        ) ) );
    32673312
     3313        $this->add_control( new WP_Customize_Media_Control( $this, 'header_video', array(
     3314            'theme_supports' => array( 'custom-header', 'video' ),
     3315            'label'          => __( 'Header Video' ),
     3316            'description'    => $control_description,
     3317            'section'        => 'header_image',
     3318            'mime_type'      => 'video',
     3319        ) ) );
     3320
     3321        $this->add_control( 'external_header_video', array(
     3322            'theme_supports' => array( 'custom-header', 'video' ),
     3323            'type'           => 'url',
     3324            'description'    => __( 'Or, enter a YouTube or Vimeo URL:' ),
     3325            'section'        => 'header_image',
     3326        ) );
     3327
    32683328        $this->add_control( new WP_Customize_Header_Image_Control( $this ) );
     3329
     3330        $this->selective_refresh->add_partial( 'custom_header', array(
     3331            'selector'            => '#wp-custom-header',
     3332            'render_callback'     => 'the_custom_header_markup',
     3333            'settings'            => array( 'header_video', 'external_header_video', 'header_image' ), // The image is used as a video fallback here.
     3334            'container_inclusive' => true,
     3335        ) );
    32693336
    32703337        /* Custom Background */
     
    37063773
    37073774    /**
     3775     * Export header video settings to facilitate selective refresh.
     3776     *
     3777     * @since 4.7.0
     3778     *
     3779     * @param array $response Response.
     3780     * @param WP_Customize_Selective_Refresh $selective_refresh Selective refresh component.
     3781     * @param array $partials Array of partials.
     3782     * @return array
     3783     */
     3784    public function export_header_video_settings( $response, $selective_refresh, $partials ) {
     3785        if ( isset( $partials['header_video'] ) || isset( $partials['external_header_video'] ) ) {
     3786            $response['custom_header_settings'] = get_header_video_settings();
     3787        }
     3788
     3789        return $response;
     3790    }
     3791
     3792    /**
     3793     * Callback for validating the header_video value.
     3794     *
     3795     * Ensures that the selected video is less than 8MB and provides an error message.
     3796     *
     3797     * @since 4.7.0
     3798     *
     3799     * @param WP_Error $validity
     3800     * @param mixed $value
     3801     * @return mixed
     3802     */
     3803    public function _validate_header_video( $validity, $value ) {
     3804        $video = get_attached_file( absint( $value ) );
     3805        if ( $video ) {
     3806            $size = filesize( $video );
     3807            if ( 8 < $size / pow( 1024, 2 ) ) { // Check whether the size is larger than 8MB.
     3808                $validity->add( 'size_too_large', __( 'This video file is too large to use as a header video. Try a shorter video or optimize the compression settings and re-upload a file that is less than 8MB. Or, upload your video to YouTube and link it with the option below.' ) );
     3809            }
     3810            if ( '.mp4' !== substr( $video, -4 ) && '.mov' !== substr( $video, -4 ) ) { // Check for .mp4 or .mov format, which (assuming h.264 encoding) are the only cross-browser-supported formats.
     3811                $validity->add( 'invalid_file_type', __( 'Only <code>.mp4</code> or <code>.mov</code> files may be used for header video. Please convert your video file and try again, or, upload your video to YouTube and link it with the option below.' ) );
     3812            }
     3813        }
     3814        return $validity;
     3815    }
     3816
     3817    /**
     3818     * Callback for validating the external_header_video value.
     3819     *
     3820     * Ensures that the provided URL is for YouTube or Vimeo.
     3821     *
     3822     * @since 4.7.0
     3823     *
     3824     * @param WP_Error $validity
     3825     * @param mixed $value
     3826     * @return mixed
     3827     */
     3828    public function _validate_external_header_video( $validity, $value ) {
     3829        $video = esc_url( $value );
     3830        if ( $video ) {
     3831            if ( ! preg_match( '#^https?://(?:www\.)?(?:youtube\.com/watch|youtu\.be/)#', $video )
     3832                 && ! preg_match( '#^https?://(.+\.)?vimeo\.com/.*#', $video ) ) {
     3833                $validity->add( 'invalid_url', __( 'Please enter a valid YouTube or Vimeo video URL.' ) );
     3834            }
     3835        }
     3836        return $validity;
     3837    }
     3838
     3839    /**
    37083840     * Callback for rendering the custom logo, used in the custom_logo partial.
    37093841     *
  • trunk/src/wp-includes/customize/class-wp-customize-header-image-control.php

    r38881 r38985  
    167167        ?>
    168168        <div class="customize-control-content">
    169             <p class="customizer-section-intro">
     169            <?php if ( current_theme_supports( 'custom-header', 'video' ) ) {
     170                echo '<span class="customize-control-title">' . $this->label . '</span>';
     171            } ?>
     172            <p class="customizer-section-intro customize-control-description">
    170173                <?php
    171                 if ( $width && $height ) {
     174                if ( current_theme_supports( 'custom-header', 'video' ) ) {
     175                    _e( 'While you can crop images to your liking after clicking <strong>Add new image</strong>, we recommend matching the size of your video.' );
     176                } elseif ( $width && $height ) {
    172177                    /* translators: %s: header size in pixels */
    173178                    printf( __( 'While you can crop images to your liking after clicking <strong>Add new image</strong>, your theme recommends a header size of %s pixels.' ),
  • trunk/src/wp-includes/script-loader.php

    r38967 r38985  
    479479    $scripts->add( 'customize-nav-menus', "/wp-admin/js/customize-nav-menus$suffix.js", array( 'jquery', 'wp-backbone', 'customize-controls', 'accordion', 'nav-menu' ), false, 1 );
    480480    $scripts->add( 'customize-preview-nav-menus', "/wp-includes/js/customize-preview-nav-menus$suffix.js", array( 'jquery', 'wp-util', 'customize-preview', 'customize-selective-refresh' ), false, 1 );
     481
     482    $scripts->add( 'wp-custom-header', "/wp-includes/js/wp-custom-header$suffix.js", array(), false, 1 );
    481483
    482484    $scripts->add( 'accordion', "/wp-admin/js/accordion$suffix.js", array( 'jquery' ), false, 1 );
  • trunk/src/wp-includes/theme.php

    r38948 r38985  
    12651265        'width'         => get_theme_support( 'custom-header', 'width' ),
    12661266        'height'        => get_theme_support( 'custom-header', 'height' ),
     1267        'video'         => get_theme_support( 'custom-header', 'video' ),
    12671268    );
    12681269    return (object) wp_parse_args( $data, $default );
     
    13081309    } else {
    13091310        return false;
     1311    }
     1312}
     1313
     1314/**
     1315 * Check whether a header video is set or not.
     1316 *
     1317 * @since 4.7.0
     1318 *
     1319 * @see get_header_video_url()
     1320 *
     1321 * @return bool Whether a header video is set or not.
     1322 */
     1323function has_header_video() {
     1324    return (bool) get_header_video_url();
     1325}
     1326
     1327/* Retrieve header video URL for custom header.
     1328 *
     1329 * Uses a local video if present, or falls back to an external video. Returns false if there is no video.
     1330 *
     1331 * @since 4.7.0
     1332 *
     1333 * @return string|false
     1334 */
     1335function get_header_video_url() {
     1336    $id = absint( get_theme_mod( 'header_video' ) );
     1337    $url = esc_url( get_theme_mod( 'external_header_video' ) );
     1338
     1339    if ( ! $id && ! $url ) {
     1340        return false;
     1341    }
     1342
     1343    if ( $id ) {
     1344        // Get the file URL from the attachment ID.
     1345        $url = wp_get_attachment_url( $id );
     1346    }
     1347
     1348    return esc_url_raw( set_url_scheme( $url ) );
     1349}
     1350
     1351/**
     1352 * Display header video URL.
     1353 *
     1354 * @since 4.7.0
     1355 */
     1356function the_header_video_url() {
     1357    $video = get_header_video_url();
     1358    if ( $video ) {
     1359        echo esc_url( $video );
     1360    }
     1361}
     1362
     1363/**
     1364 * Retrieve header video settings.
     1365 *
     1366 * @since 4.7.0
     1367 *
     1368 * @return array
     1369 */
     1370function get_header_video_settings() {
     1371    $header     = get_custom_header();
     1372    $video_url  = get_header_video_url();
     1373    $video_type = wp_check_filetype( $video_url, wp_get_mime_types() );
     1374
     1375    $settings = array(
     1376        'mimeType'  => '',
     1377        'posterUrl' => get_header_image(),
     1378        'videoUrl'  => $video_url,
     1379        'width'     => absint( $header->width ),
     1380        'height'    => absint( $header->height ),
     1381        'minWidth'  => 900,
     1382        'minHeight' => 500,
     1383    );
     1384
     1385    if ( preg_match( '#^https?://(?:www\.)?(?:youtube\.com/watch|youtu\.be/)#', $video_url ) ) {
     1386        $settings['mimeType'] = 'video/x-youtube';
     1387    } elseif ( preg_match( '#^https?://(.+\.)?vimeo\.com/.*#', $video_url ) ) {
     1388        $settings['mimeType'] = 'video/x-vimeo';
     1389    } elseif ( ! empty( $video_type['type'] ) ) {
     1390        $settings['mimeType'] = $video_type['type'];
     1391    }
     1392
     1393    return apply_filters( 'header_video_settings', $settings );
     1394}
     1395
     1396/**
     1397 * Check whether a custom header is set or not.
     1398 *
     1399 * @since 4.7.0
     1400 *
     1401 * @return bool True if a custom header is set. False if not.
     1402 */
     1403function has_custom_header() {
     1404    if ( has_header_image() || ( is_front_page() && has_header_video() ) ) {
     1405        return true;
     1406    }
     1407
     1408    return false;
     1409}
     1410
     1411/**
     1412 * Retrieve the markup for a custom header.
     1413 *
     1414 * @since 4.7.0
     1415 *
     1416 * @return string|false The markup for a custom header on success. False if not.
     1417 */
     1418function get_custom_header_markup() {
     1419    if ( ! has_custom_header() ) {
     1420        return false;
     1421    }
     1422
     1423    return sprintf(
     1424        '<div id="wp-custom-header" class="wp-custom-header">%s</div>',
     1425        get_header_image_tag()
     1426    );
     1427}
     1428
     1429/**
     1430 * Print the markup for a custom header.
     1431 *
     1432 * @since 4.7.0
     1433 */
     1434function the_custom_header_markup() {
     1435    if ( ! $custom_header = get_custom_header_markup() ) {
     1436        return;
     1437    }
     1438    echo $custom_header;
     1439
     1440    if ( has_header_video() && is_front_page() ) {
     1441        wp_enqueue_script( 'wp-custom-header' );
     1442        wp_localize_script( 'wp-custom-header', '_wpCustomHeaderSettings', get_header_video_settings() );
    13101443    }
    13111444}
     
    17331866                'admin-head-callback' => '',
    17341867                'admin-preview-callback' => '',
     1868                'video' => false,
    17351869            );
    17361870
Note: See TracChangeset for help on using the changeset viewer.