From 55fd899391b97bb25cf283f7a5a85d57a1a0cb2d Mon Sep 17 00:00:00 2001
From: Peter Wilson <peterwilsoncc@git.wordpress.org>
Date: Tue, 15 Nov 2016 07:15:20 +0000
Subject: [PATCH] Themes: Remove front page restriction from video header
 functions.

Adds a callback for determining when video headers should be displayed in themes supporting custom headers. By default, video headers are only displayed on the front page of a site.

Theme authors may set a custom callback by passing `'video-active-callback' => 'mytheme_video_active_callback'` as an argument. The default callback is `is_front_page()`.

This introduces the new function `is_header_video_active()` - returns `true` on pages that should display video headers. The return value can be filtered using the new filter of the same name.

Props flixos90, bradyvercher, peterwilsoncc, joemcgill.
Fixes #38738.


git-svn-id: https://develop.svn.wordpress.org/trunk@39240 602fd350-edb4-49c9-b593-d223f7449a82
---
 .../class-wp-customize-manager.php            |   2 +-
 src/wp-includes/theme.php                     |  46 ++++++-
 tests/phpunit/tests/theme/customHeader.php    | 125 ++++++++++++++++++
 3 files changed, 167 insertions(+), 6 deletions(-)
 create mode 100644 tests/phpunit/tests/theme/customHeader.php

diff --git a/src/wp-includes/class-wp-customize-manager.php b/src/wp-includes/class-wp-customize-manager.php
index 54c3f0eac1..1a9c1c5523 100644
--- a/src/wp-includes/class-wp-customize-manager.php
+++ b/src/wp-includes/class-wp-customize-manager.php
@@ -3491,7 +3491,7 @@ final class WP_Customize_Manager {
 				'frame_title'  => __( 'Select Video' ),
 				'frame_button' => __( 'Choose Video' ),
 			),
-			'active_callback' => 'is_front_page',
+			'active_callback' => 'is_header_video_active',
 		) ) );
 
 		$this->add_control( 'external_header_video', array(
diff --git a/src/wp-includes/theme.php b/src/wp-includes/theme.php
index 66e10b24e8..9ca52735cb 100644
--- a/src/wp-includes/theme.php
+++ b/src/wp-includes/theme.php
@@ -1400,13 +1400,45 @@ function get_header_video_settings() {
  * @return bool True if a custom header is set. False if not.
  */
 function has_custom_header() {
-	if ( has_header_image() || ( is_front_page() && has_header_video() ) ) {
+	if ( has_header_image() || ( has_header_video() && is_header_video_active() ) ) {
 		return true;
 	}
 
 	return false;
 }
 
+/**
+ * Checks whether the custom header video is eligible to show on the current page.
+ *
+ * @since 4.7.0
+ *
+ * @return bool True if the custom header video should be shown. False if not.
+ */
+function is_header_video_active() {
+	if ( ! get_theme_support( 'custom-header', 'video' ) ) {
+		return false;
+	}
+
+	$video_active_cb = get_theme_support( 'custom-header', 'video-active-callback' );
+
+	if ( empty( $video_active_cb ) || ! is_callable( $video_active_cb ) ) {
+		$show_video = true;
+	} else {
+		$show_video = call_user_func( $video_active_cb );
+	}
+
+	/**
+	 * Modify whether the custom header video is eligible to show on the current page.
+	 *
+	 * @since 4.7.0
+	 *
+	 * @param bool $show_video Whether the custom header video should be shown. Returns the value
+	 *                         of the theme setting for the `custom-header`'s `video-active-callback`.
+	 *                         If no callback is set, the default value is that of `is_front_page()`.
+	 */
+	return apply_filters( 'is_header_video_active', $show_video );
+}
+
 /**
  * Retrieve the markup for a custom header.
  *
@@ -1442,7 +1474,7 @@ function the_custom_header_markup() {
 
 	echo $custom_header;
 
-	if ( is_front_page() && ( has_header_video() || is_customize_preview() ) ) {
+	if ( is_header_video_active() && ( has_header_video() || is_customize_preview() ) ) {
 		wp_enqueue_script( 'wp-custom-header' );
 		wp_localize_script( 'wp-custom-header', '_wpCustomHeaderSettings', get_header_video_settings() );
 	}
@@ -2058,6 +2090,7 @@ function add_theme_support( $feature ) {
 				'admin-head-callback' => '',
 				'admin-preview-callback' => '',
 				'video' => false,
+				'video-active-callback' => 'is_front_page',
 			);
 
 			$jit = isset( $args[0]['__jit'] );
@@ -2319,10 +2352,13 @@ function _remove_theme_support( $feature ) {
 			if ( ! did_action( 'wp_loaded' ) )
 				break;
 			$support = get_theme_support( 'custom-header' );
-			if ( $support[0]['wp-head-callback'] )
+			if ( isset( $support[0]['wp-head-callback'] ) ) {
 				remove_action( 'wp_head', $support[0]['wp-head-callback'] );
-			remove_action( 'admin_menu', array( $GLOBALS['custom_image_header'], 'init' ) );
-			unset( $GLOBALS['custom_image_header'] );
+			}
+			if ( isset( $GLOBALS['custom_image_header'] ) ) {
+				remove_action( 'admin_menu', array( $GLOBALS['custom_image_header'], 'init' ) );
+				unset( $GLOBALS['custom_image_header'] );
+			}
 			break;
 
 		case 'custom-background' :
diff --git a/tests/phpunit/tests/theme/customHeader.php b/tests/phpunit/tests/theme/customHeader.php
new file mode 100644
index 0000000000..875c8ba79d
--- /dev/null
+++ b/tests/phpunit/tests/theme/customHeader.php
@@ -0,0 +1,125 @@
+<?php
+/**
+ * @group themes
+ */
+class Tests_Theme_Custom_Header extends WP_UnitTestCase {
+
+	static $post;
+
+	public static function wpSetUpBeforeClass( $factory ) {
+		self::$post = self::factory()->post->create( array(
+			'post_status' => 'publish',
+		) );
+	}
+
+	function tearDown() {
+		remove_theme_support( 'custom-header' );
+		parent::tearDown();
+	}
+
+	/**
+	 * @ticket 38738
+	 */
+	function test_video_header_callback_front_page_from_front_page() {
+		$this->_add_theme_support( array(
+			'video' => true,
+		) );
+
+		$this->go_to( home_url() );
+
+		$result = is_header_video_active();
+
+		$this->assertTrue( $result );
+	}
+
+	/**
+	 * @ticket 38738
+	 */
+	function test_video_header_callback_front_page_from_elsewhere() {
+		$this->_add_theme_support( array(
+			'video' => true,
+		) );
+
+		$this->go_to( get_permalink( self::$post ) );
+
+		$result = is_header_video_active();
+
+		$this->assertFalse( $result );
+	}
+
+	/**
+	 * @ticket 38738
+	 */
+	function test_video_header_callback_globally_from_front_page() {
+		$this->_add_theme_support( array(
+			'video' => true,
+			'video-active-callback' => '__return_true',
+		) );
+
+		$this->go_to( home_url() );
+
+		$result = is_header_video_active();
+
+		$this->assertTrue( $result );
+	}
+
+	/**
+	 * @ticket 38738
+	 */
+	function test_video_header_callback_globally_from_elsewhere() {
+		$this->_add_theme_support( array(
+			'video' => true,
+			'video-active-callback' => '__return_true',
+		) );
+
+		$this->go_to( get_permalink( self::$post ) );
+
+		$result = is_header_video_active();
+
+		$this->assertTrue( $result );
+	}
+
+	/**
+	 * @ticket 38738
+	 */
+	function test_video_header_callback_globally_with_negative_filter() {
+		$this->_add_theme_support( array(
+			'video' => true,
+			'video-active-callback' => '__return_true',
+		) );
+
+		$this->go_to( get_permalink( self::$post ) );
+
+		add_filter( 'is_header_video_active', '__return_false' );
+		$result = is_header_video_active();
+		remove_filter( 'is_header_video_active', '__return_false' );
+
+		$this->assertFalse( $result );
+	}
+
+	/**
+	 * Adds arguments directly to the $_wp_theme_features global. Calling
+	 * add_theme_support( 'custom-header' ) will poison subsequent tests since
+	 * it defines constants.
+	 */
+	function _add_theme_support( $args = array() ) {
+		global $_wp_theme_features;
+
+		$_wp_theme_features['custom-header'][0] = wp_parse_args( $args, array(
+			'default-image' => '',
+			'random-default' => false,
+			'width' => 0,
+			'height' => 0,
+			'flex-height' => false,
+			'flex-width' => false,
+			'default-text-color' => '',
+			'header-text' => true,
+			'uploads' => true,
+			'wp-head-callback' => '',
+			'admin-head-callback' => '',
+			'admin-preview-callback' => '',
+			'video' => false,
+			'video-active-callback' => 'is_front_page',
+		) );
+	}
+}