+ /**
+ * Unused since 3.5.0.
+ *
+ * @since 3.4.0
+ */
+ public function filter_upload_tabs( $tabs ) {
+ return $tabs;
+ }
+
+ /**
+ * Choose a header image, selected from existing uploaded and default headers,
+ * or provide an array of uploaded header data (either new, or from media library).
+ *
+ * @param mixed $choice Which header image to select. Allows for values of 'random-default-image',
+ * for randomly cycling among the default images; 'random-uploaded-image', for randomly cycling
+ * among the uploaded images; the key of a default image registered for that theme; and
+ * the key of an image uploaded for that theme (the basename of the URL).
+ * Or an array of arguments: attachment_id, url, width, height. All are required.
+ *
+ * @since 3.4.0
+ */
+ final public function set_header_image( $choice ) {
+ if ( is_array( $choice ) || is_object( $choice ) ) {
+ $choice = (array) $choice;
+ if ( ! isset( $choice['attachment_id'] ) || ! isset( $choice['url'] ) )
+ return;
+
+ $choice['url'] = esc_url_raw( $choice['url'] );
+
+ $header_image_data = (object) array(
+ 'attachment_id' => $choice['attachment_id'],
+ 'url' => $choice['url'],
+ 'thumbnail_url' => $choice['url'],
+ 'height' => $choice['height'],
+ 'width' => $choice['width'],
+ );
+
+ update_post_meta( $choice['attachment_id'], '_wp_attachment_is_custom_header', get_stylesheet() );
+ set_theme_mod( 'header_image', $choice['url'] );
+ set_theme_mod( 'header_image_data', $header_image_data );
+ return;
+ }
+
+ if ( in_array( $choice, array( 'remove-header', 'random-default-image', 'random-uploaded-image' ) ) ) {
+ set_theme_mod( 'header_image', $choice );
+ remove_theme_mod( 'header_image_data' );
+ return;
+ }
+
+ $uploaded = get_uploaded_header_images();
+ if ( $uploaded && isset( $uploaded[ $choice ] ) ) {
+ $header_image_data = $uploaded[ $choice ];
+
+ } else {
+ $this->process_default_headers();
+ if ( isset( $this->default_headers[ $choice ] ) )
+ $header_image_data = $this->default_headers[ $choice ];
+ else
+ return;
+ }
+
+ set_theme_mod( 'header_image', esc_url_raw( $header_image_data['url'] ) );
+ set_theme_mod( 'header_image_data', $header_image_data );
+ }
+
+ /**
+ * Remove a header image.
+ *
+ * @since 3.4.0
+ */
+ final public function remove_header_image() {
+ return $this->set_header_image( 'remove-header' );
+ }
+
+ /**
+ * Reset a header image to the default image for the theme.
+ *
+ * This method does not do anything if the theme does not have a default header image.
+ *
+ * @since 3.4.0
+ */
+ final public function reset_header_image() {
+ $this->process_default_headers();
+ $default = get_theme_support( 'custom-header', 'default-image' );
+
+ if ( ! $default )
+ return $this->remove_header_image();
+
+ $default = sprintf( $default, get_template_directory_uri(), get_stylesheet_directory_uri() );
+
+ $default_data = array();
+ foreach ( $this->default_headers as $header => $details ) {
+ if ( $details['url'] == $default ) {
+ $default_data = $details;
+ break;
+ }
+ }
+
+ set_theme_mod( 'header_image', $default );
+ set_theme_mod( 'header_image_data', (object) $default_data );
+ }
+
+ /**
+ * Calculate width and height based on what the currently selected theme supports.
+ *
+ * @return array dst_height and dst_width of header image.
+ */
+ final public function get_header_dimensions( $dimensions ) {
+ $max_width = 0;
+ $width = absint( $dimensions['width'] );
+ $height = absint( $dimensions['height'] );
+ $theme_height = get_theme_support( 'custom-header', 'height' );
+ $theme_width = get_theme_support( 'custom-header', 'width' );
+ $has_flex_width = current_theme_supports( 'custom-header', 'flex-width' );
+ $has_flex_height = current_theme_supports( 'custom-header', 'flex-height' );
+ $has_max_width = current_theme_supports( 'custom-header', 'max-width' ) ;
+ $dst = array( 'dst_height' => null, 'dst_height' => null );
+
+ // For flex, limit size of image displayed to 1500px unless theme says otherwise
+ if ( $has_flex_width ) {
+ $max_width = 1500;
+ }
+
+ if ( $has_max_width ) {
+ $max_width = max( $max_width, get_theme_support( 'custom-header', 'max-width' ) );
+ }
+ $max_width = max( $max_width, $theme_width );
+
+ if ( $has_flex_height && ( ! $has_flex_width || $width > $max_width ) ) {
+ $dst['dst_height'] = absint( $height * ( $max_width / $width ) );
+ }
+ elseif ( $has_flex_height && $has_flex_width ) {
+ $dst['dst_height'] = $height;
+ }
+ else {
+ $dst['dst_height'] = $theme_height;
+ }
+
+ if ( $has_flex_width && ( ! $has_flex_height || $width > $max_width ) ) {
+ $dst['dst_width'] = absint( $width * ( $max_width / $width ) );
+ }
+ elseif ( $has_flex_width && $has_flex_height ) {
+ $dst['dst_width'] = $width;
+ }
+ else {
+ $dst['dst_width'] = $theme_width;
+ }
+
+ return $dst;
+ }
+
+ /**
+ * Create an attachment 'object'.
+ *
+ * @param string $cropped Cropped image URL.
+ * @param int $parent_attachment_id Attachment ID of parent image.
+ *
+ * @return array Attachment object.
+ */
+ final public function create_attachment_object( $cropped, $parent_attachment_id ) {
+ $parent = get_post( $parent_attachment_id );