<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[19815] trunk: Allow flexible sizes for custom header uploads.</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg > ul, #logmsg > ol { margin-left: 0; margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://core.trac.wordpress.org/changeset/19815">19815</a></dd>
<dt>Author</dt> <dd>ryan</dd>
<dt>Date</dt> <dd>2012-02-02 23:35:37 +0000 (Thu, 02 Feb 2012)</dd>
</dl>

<h3>Log Message</h3>
<pre>Allow flexible sizes for custom header uploads. Round 1. Props aaroncampbell, sabreuse. see <a href="http://core.trac.wordpress.org/ticket/17242">#17242</a></pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkwpadmincsswpadmindevcss">trunk/wp-admin/css/wp-admin.dev.css</a></li>
<li><a href="#trunkwpadmincustomheaderphp">trunk/wp-admin/custom-header.php</a></li>
<li><a href="#trunkwpincludesthemephp">trunk/wp-includes/theme.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkwpadmincsswpadmindevcss"></a>
<div class="modfile"><h4>Modified: trunk/wp-admin/css/wp-admin.dev.css (19814 => 19815)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-admin/css/wp-admin.dev.css        2012-02-01 22:41:34 UTC (rev 19814)
+++ trunk/wp-admin/css/wp-admin.dev.css        2012-02-02 23:35:37 UTC (rev 19815)
</span><span class="lines">@@ -4494,7 +4494,6 @@
</span><span class="cx"> 
</span><span class="cx"> .appearance_page_custom-header #headimg {
</span><span class="cx">         border: 1px solid #DFDFDF;
</span><del>-        min-height: 100px;
</del><span class="cx">         width: 100%;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkwpadmincustomheaderphp"></a>
<div class="modfile"><h4>Modified: trunk/wp-admin/custom-header.php (19814 => 19815)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-admin/custom-header.php        2012-02-01 22:41:34 UTC (rev 19814)
+++ trunk/wp-admin/custom-header.php        2012-02-02 23:35:37 UTC (rev 19815)
</span><span class="lines">@@ -188,7 +188,21 @@
</span><span class="cx"> 
</span><span class="cx">                 if ( isset( $_POST['resetheader'] ) ) {
</span><span class="cx">                         check_admin_referer( 'custom-header-options', '_wpnonce-custom-header-options' );
</span><del>-                        remove_theme_mod( 'header_image' );
</del><ins>+                        $this-&gt;process_default_headers();
+                        $default = defined( 'HEADER_IMAGE' ) ? HEADER_IMAGE : '';
+                        $default = sprintf( $default, get_template_directory_uri(), get_stylesheet_directory_uri() );
+                        foreach ( $this-&gt;default_headers as $header =&gt; $details ) {
+                                if ( $details['url'] == $default ) {
+                                        $default_data = $details;
+                                        break;
+                                }
+                        }
+                        set_theme_mod( 'header_image', $default );
+                        if ( empty( $default_data['width'] ) )
+                                $default_data['width'] = HEADER_IMAGE_WIDTH;
+                        if ( empty( $default_data['height'] ) )
+                                $default_data['height'] = HEADER_IMAGE_HEIGHT;
+                        set_theme_mod( 'header_image_data', (object) $default_data );
</ins><span class="cx">                         return;
</span><span class="cx">                 }
</span><span class="cx"> 
</span><span class="lines">@@ -225,10 +239,17 @@
</span><span class="cx">                         } else {
</span><span class="cx">                                 $this-&gt;process_default_headers();
</span><span class="cx">                                 $uploaded = get_uploaded_header_images();
</span><del>-                                if ( isset( $uploaded[$_POST['default-header']] ) )
</del><ins>+                                if ( isset( $uploaded[$_POST['default-header']] ) ) {
</ins><span class="cx">                                         set_theme_mod( 'header_image', esc_url( $uploaded[$_POST['default-header']]['url'] ) );
</span><del>-                                elseif ( isset( $this-&gt;default_headers[$_POST['default-header']] ) )
</del><ins>+                                        set_theme_mod( 'header_image_data', (object) $uploaded[$_POST['default-header']] );
+                                } elseif ( isset( $this-&gt;default_headers[$_POST['default-header']] ) ) {
</ins><span class="cx">                                         set_theme_mod( 'header_image', esc_url( $this-&gt;default_headers[$_POST['default-header']]['url'] ) );
</span><ins>+                                        if ( empty( $this-&gt;default_headers[$_POST['default-header']]['width'] ) )
+                                                $this-&gt;default_headers[$_POST['default-header']]['width'] = HEADER_IMAGE_WIDTH;
+                                        if ( empty( $this-&gt;default_headers[$_POST['default-header']]['height'] ) )
+                                                $this-&gt;default_headers[$_POST['default-header']]['height'] = HEADER_IMAGE_HEIGHT;
+                                        set_theme_mod( 'header_image_data', (object) $this-&gt;default_headers[$_POST['default-header']] );
+                                }
</ins><span class="cx">                         }
</span><span class="cx">                 }
</span><span class="cx">         }
</span><span class="lines">@@ -289,7 +310,7 @@
</span><span class="cx">                         echo '&lt;div class=&quot;default-header&quot;&gt;';
</span><span class="cx">                         echo '&lt;label&gt;&lt;input name=&quot;default-header&quot; type=&quot;radio&quot; value=&quot;' . esc_attr( $header_key ) . '&quot; ' . checked( $header_url, get_theme_mod( 'header_image' ), false ) . ' /&gt;';
</span><span class="cx">                         $width = '';
</span><del>-                        if ( !empty( $header['uploaded'] ) )
</del><ins>+                        if ( !empty( $header['attachment_id'] ) )
</ins><span class="cx">                                 $width = ' width=&quot;230&quot;';
</span><span class="cx">                         echo '&lt;img src=&quot;' . $header_thumbnail . '&quot; alt=&quot;' . esc_attr( $header_desc ) .'&quot; title=&quot;' . esc_attr( $header_desc ) . '&quot;' . $width . ' /&gt;&lt;/label&gt;';
</span><span class="cx">                         echo '&lt;/div&gt;';
</span><span class="lines">@@ -419,8 +440,17 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         jQuery(document).ready(function() {
</span><del>-                var xinit = &lt;?php echo HEADER_IMAGE_WIDTH; ?&gt;;
-                var yinit = &lt;?php echo HEADER_IMAGE_HEIGHT; ?&gt;;
</del><ins>+                &lt;?php
+                $xinit = HEADER_IMAGE_WIDTH;
+                $yinit = HEADER_IMAGE_HEIGHT;
+                $header_support = get_theme_support( 'custom-header' );
+                if ( !empty( $header_support[ 0 ][ 'suggested-width' ] ) )
+                        $xinit = $header_support[ 0 ][ 'suggested-width' ];
+                if ( !empty( $header_support[ 0 ][ 'suggested-height' ] ) )
+                        $yinit = $header_support[ 0 ][ 'suggested-height' ];
+                ?&gt;
+                var xinit = &lt;?php echo absint( $xinit ); ?&gt;;
+                var yinit = &lt;?php echo absint( $yinit ); ?&gt;;
</ins><span class="cx">                 var ratio = xinit / yinit;
</span><span class="cx">                 var ximg = jQuery('img#upload').width();
</span><span class="cx">                 var yimg = jQuery('img#upload').height();
</span><span class="lines">@@ -438,14 +468,28 @@
</span><span class="cx">                 jQuery('img#upload').imgAreaSelect({
</span><span class="cx">                         handles: true,
</span><span class="cx">                         keys: true,
</span><del>-                        aspectRatio: xinit + ':' + yinit,
</del><span class="cx">                         show: true,
</span><span class="cx">                         x1: 0,
</span><span class="cx">                         y1: 0,
</span><span class="cx">                         x2: xinit,
</span><span class="cx">                         y2: yinit,
</span><ins>+                        &lt;?php
+                        if ( ! current_theme_supports( 'custom-header', 'flex-height' ) &amp;&amp; ! current_theme_supports( 'custom-header', 'flex-width' ) ) {
+                        ?&gt;
+                        aspectRatio: xinit + ':' + yinit,
+                        &lt;?php
+                        }
+                        if ( ! current_theme_supports( 'custom-header', 'flex-height' ) ) {
+                        ?&gt;
</ins><span class="cx">                         maxHeight: &lt;?php echo HEADER_IMAGE_HEIGHT; ?&gt;,
</span><ins>+                        &lt;?php
+                        }
+                        if ( ! current_theme_supports( 'custom-header', 'flex-width' ) ) {
+                        ?&gt;
</ins><span class="cx">                         maxWidth: &lt;?php echo HEADER_IMAGE_WIDTH; ?&gt;,
</span><ins>+                        &lt;?php
+                        }
+                        ?&gt;
</ins><span class="cx">                         onInit: function () {
</span><span class="cx">                                 jQuery('#width').val(xinit);
</span><span class="cx">                                 jQuery('#height').val(yinit);
</span><span class="lines">@@ -492,7 +536,7 @@
</span><span class="cx">           call_user_func( $this-&gt;admin_image_div_callback );
</span><span class="cx">         } else {
</span><span class="cx">         ?&gt;
</span><del>-        &lt;div id=&quot;headimg&quot; style=&quot;max-width:&lt;?php echo HEADER_IMAGE_WIDTH; ?&gt;px;height:&lt;?php echo HEADER_IMAGE_HEIGHT; ?&gt;px;background-image:url(&lt;?php esc_url ( header_image() ) ?&gt;);&quot;&gt;
</del><ins>+        &lt;div id=&quot;headimg&quot; style=&quot;background-image:url(&lt;?php esc_url ( header_image() ) ?&gt;);max-width:&lt;?php echo get_header_image_width(); ?&gt;px;height:&lt;?php echo get_header_image_height(); ?&gt;px;&quot;&gt;
</ins><span class="cx">                 &lt;?php
</span><span class="cx">                 if ( 'blank' == get_theme_mod('header_textcolor', HEADER_TEXTCOLOR) || '' == get_theme_mod('header_textcolor', HEADER_TEXTCOLOR) || ! $this-&gt;header_text() )
</span><span class="cx">                         $style = ' style=&quot;display:none;&quot;';
</span><span class="lines">@@ -510,7 +554,24 @@
</span><span class="cx"> &lt;th scope=&quot;row&quot;&gt;&lt;?php _e( 'Upload Image' ); ?&gt;&lt;/th&gt;
</span><span class="cx"> &lt;td&gt;
</span><span class="cx">         &lt;p&gt;&lt;?php _e( 'You can upload a custom header image to be shown at the top of your site instead of the default one. On the next screen you will be able to crop the image.' ); ?&gt;&lt;br /&gt;
</span><del>-        &lt;?php printf( __( 'Images of exactly &lt;strong&gt;%1$d &amp;times; %2$d pixels&lt;/strong&gt; will be used as-is.' ), HEADER_IMAGE_WIDTH, HEADER_IMAGE_HEIGHT ); ?&gt;&lt;/p&gt;
</del><ins>+        &lt;?php
+        if ( ! current_theme_supports( 'custom-header', 'flex-height' ) &amp;&amp; ! current_theme_supports( 'custom-header', 'flex-width' ) ) {
+                printf( __( 'Images of exactly &lt;strong&gt;%1$d &amp;times; %2$d pixels&lt;/strong&gt; will be used as-is.' ) . '&lt;br /&gt;', HEADER_IMAGE_WIDTH, HEADER_IMAGE_HEIGHT );
+        } elseif ( current_theme_supports( 'custom-header', 'flex-height' ) ) {
+                if ( ! current_theme_supports( 'custom-header', 'flex-width' ) )
+                        printf( __( 'Images should be at least &lt;strong&gt;%1$d pixels&lt;/strong&gt; wide.' ) . '&lt;br /&gt;', HEADER_IMAGE_WIDTH );
+        } elseif ( current_theme_supports( 'custom-header', 'flex-width' ) ) {
+                if ( ! current_theme_supports( 'custom-header', 'flex-height' ) )
+                        printf( __( 'Images should be at least &lt;strong&gt;%1$d pixels&lt;/strong&gt; tall.' ) . '&lt;br /&gt;', HEADER_IMAGE_HEIGHT );
+        }
+        if ( current_theme_supports( 'custom-header', 'flex-height' ) || current_theme_supports( 'custom-header', 'flex-width' ) ) {
+                $header_support = get_theme_support( 'custom-header' );
+                if ( !empty( $header_support[ 0 ][ 'suggested-width' ] ) )
+                        printf( __( 'Suggested width is &lt;strong&gt;%1$d pixels&lt;/strong&gt;.' ) . '&lt;br /&gt;', absint( $header_support[ 0 ][ 'suggested-width' ] ) );
+                if ( !empty( $header_support[ 0 ][ 'suggested-height' ] ) )
+                        printf( __( 'Suggested height is &lt;strong&gt;%1$d pixels&lt;/strong&gt;.' ) . '&lt;br /&gt;', absint( $header_support[ 0 ][ 'suggested-height' ] ) );
+        }
+        ?&gt;&lt;/p&gt;
</ins><span class="cx">         &lt;form enctype=&quot;multipart/form-data&quot; id=&quot;upload-form&quot; method=&quot;post&quot; action=&quot;&lt;?php echo esc_attr( add_query_arg( 'step', 2 ) ) ?&gt;&quot;&gt;
</span><span class="cx">         &lt;p&gt;
</span><span class="cx">                 &lt;label for=&quot;upload&quot;&gt;&lt;?php _e( 'Choose an image from your computer:' ); ?&gt;&lt;/label&gt;&lt;br /&gt;
</span><span class="lines">@@ -662,7 +723,19 @@
</span><span class="cx"> 
</span><span class="cx">                 list($width, $height, $type, $attr) = getimagesize( $file );
</span><span class="cx"> 
</span><del>-                if ( $width == HEADER_IMAGE_WIDTH &amp;&amp; $height == HEADER_IMAGE_HEIGHT ) {
</del><ins>+                $header_support = get_theme_support( 'custom-header' );
+                $max_width = 0;
+                // For flex, limit size of image displayed to 1500px unless theme says otherwise
+                if ( current_theme_supports( 'custom-header', 'flex-width' ) )
+                        $max_width = 1500;
+
+                if ( !empty( $header_support[ 0 ][ 'max-width' ] ) )
+                        $max_width = max( $max_width, absint( $header_support[ 0 ][ 'max-width' ] ) );
+
+                if ( defined( 'HEADER_IMAGE_WIDTH' ) )
+                        $max_width = max( $max_width, HEADER_IMAGE_WIDTH );
+                // If flexible height isn't supported and the image is the exact right size
+                if ( ! current_theme_supports( 'custom-header', 'flex-height' ) &amp;&amp; ! current_theme_supports( 'custom-header', 'flex-width' ) &amp;&amp; $width == HEADER_IMAGE_WIDTH &amp;&amp; $height == HEADER_IMAGE_HEIGHT ) {
</ins><span class="cx">                         // Add the meta-data
</span><span class="cx">                         wp_update_attachment_metadata( $id, wp_generate_attachment_metadata( $id, $file ) );
</span><span class="cx">                         update_post_meta( $id, '_wp_attachment_is_custom_header', get_option('stylesheet' ) );
</span><span class="lines">@@ -670,9 +743,9 @@
</span><span class="cx">                         set_theme_mod('header_image', esc_url($url));
</span><span class="cx">                         do_action('wp_create_file_in_uploads', $file, $id); // For replication
</span><span class="cx">                         return $this-&gt;finished();
</span><del>-                } elseif ( $width &gt; HEADER_IMAGE_WIDTH ) {
-                        $oitar = $width / HEADER_IMAGE_WIDTH;
-                        $image = wp_crop_image($file, 0, 0, $width, $height, HEADER_IMAGE_WIDTH, $height / $oitar, false, str_replace(basename($file), 'midsize-'.basename($file), $file));
</del><ins>+                } elseif ( $width &gt; $max_width ) {
+                        $oitar = $width / $max_width;
+                        $image = wp_crop_image($file, 0, 0, $width, $height, $max_width, $height / $oitar, false, str_replace(basename($file), 'midsize-'.basename($file), $file));
</ins><span class="cx">                         if ( is_wp_error( $image ) )
</span><span class="cx">                                 wp_die( __( 'Image could not be processed. Please go back and try again.' ), __( 'Image Processing Error' ) );
</span><span class="cx"> 
</span><span class="lines">@@ -733,7 +806,33 @@
</span><span class="cx">                 $attachment_id = absint( $_POST['attachment_id'] );
</span><span class="cx">                 $original = get_attached_file($attachment_id);
</span><span class="cx"> 
</span><del>-                $cropped = wp_crop_image( $attachment_id, (int) $_POST['x1'], (int) $_POST['y1'], (int) $_POST['width'], (int) $_POST['height'], HEADER_IMAGE_WIDTH, HEADER_IMAGE_HEIGHT );
</del><ins>+                $header_support = get_theme_support( 'custom-header' );
+                $max_width = 0;
+                // For flex, limit size of image displayed to 1500px unless theme says otherwise
+                if ( current_theme_supports( 'custom-header', 'flex-width' ) )
+                        $max_width = 1500;
+
+                if ( !empty( $header_support[ 0 ][ 'max-width' ] ) )
+                        $max_width = max( $max_width, absint( $header_support[ 0 ][ 'max-width' ] ) );
+
+                if ( defined( 'HEADER_IMAGE_WIDTH' ) )
+                        $max_width = max( $max_width, HEADER_IMAGE_WIDTH );
+
+                if ( ( current_theme_supports( 'custom-header', 'flex-height' ) &amp;&amp; ! current_theme_supports( 'custom-header', 'flex-width' ) ) || $_POST['width'] &gt; $max_width )
+                        $dst_height = absint( $_POST['height'] * ( $max_width / $_POST['width'] ) );
+                elseif ( current_theme_supports( 'custom-header', 'flex-height' ) &amp;&amp; current_theme_supports( 'custom-header', 'flex-width' ) )
+                        $dst_height = absint( $_POST['height'] );
+                else
+                        $dst_height = HEADER_IMAGE_HEIGHT;
+
+                if ( ( current_theme_supports( 'custom-header', 'flex-width' ) &amp;&amp; ! current_theme_supports( 'custom-header', 'flex-height' ) ) || $_POST['width'] &gt; $max_width )
+                        $dst_width = absint( $_POST['width'] * ( $max_width / $_POST['width'] ) );
+                elseif ( current_theme_supports( 'custom-header', 'flex-width' ) &amp;&amp; current_theme_supports( 'custom-header', 'flex-height' ) )
+                        $dst_width = absint( $_POST['width'] );
+                else
+                        $dst_width = HEADER_IMAGE_WIDTH;
+
+                $cropped = wp_crop_image( $attachment_id, (int) $_POST['x1'], (int) $_POST['y1'], (int) $_POST['width'], (int) $_POST['height'], $dst_width, $dst_height );
</ins><span class="cx">                 if ( is_wp_error( $cropped ) )
</span><span class="cx">                         wp_die( __( 'Image could not be processed. Please go back and try again.' ), __( 'Image Processing Error' ) );
</span><span class="cx"> 
</span><span class="lines">@@ -760,6 +859,15 @@
</span><span class="cx"> 
</span><span class="cx">                 set_theme_mod('header_image', $url);
</span><span class="cx"> 
</span><ins>+                $header_data                = new stdClass();
+                $header_data-&gt;attachment_id = $attachment_id;
+                $header_data-&gt;url           = $url;
+                $header_data-&gt;thumbnail_url = $url;
+                $header_data-&gt;width         = $dst_width;
+                $header_data-&gt;height        = $dst_height;
+
+                set_theme_mod( 'header_image_data', $header_data );
+
</ins><span class="cx">                 // cleanup
</span><span class="cx">                 $medium = str_replace(basename($original), 'midsize-'.basename($original), $original);
</span><span class="cx">                 @unlink( apply_filters( 'wp_delete_file', $medium ) );
</span></span></pre></div>
<a id="trunkwpincludesthemephp"></a>
<div class="modfile"><h4>Modified: trunk/wp-includes/theme.php (19814 => 19815)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/theme.php        2012-02-01 22:41:34 UTC (rev 19814)
+++ trunk/wp-includes/theme.php        2012-02-02 23:35:37 UTC (rev 19815)
</span><span class="lines">@@ -1351,7 +1351,10 @@
</span><span class="cx">         if ( isset( $mods[ $name ] ) )
</span><span class="cx">                 return apply_filters( &quot;theme_mod_$name&quot;, $mods[ $name ] );
</span><span class="cx"> 
</span><del>-        return apply_filters( &quot;theme_mod_$name&quot;, sprintf( $default, get_template_directory_uri(), get_stylesheet_directory_uri() ) );
</del><ins>+        if ( is_string( $default ) )
+                $default = sprintf( $default, get_template_directory_uri(), get_stylesheet_directory_uri() );
+
+        return apply_filters( &quot;theme_mod_$name&quot;, $default );
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /**
</span><span class="lines">@@ -1457,40 +1460,62 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /**
</span><del>- * Get random header image from registered images in theme.
</del><ins>+ * Get random header image data from registered images in theme.
</ins><span class="cx">  *
</span><del>- * @since 3.2.0
</del><ins>+ * @since 3.4.0
</ins><span class="cx">  *
</span><ins>+ * @access private
+ *
</ins><span class="cx">  * @return string Path to header image
</span><span class="cx">  */
</span><del>-function get_random_header_image() {
-        global $_wp_default_headers;
</del><span class="cx"> 
</span><del>-        $header_image_mod = get_theme_mod( 'header_image', '' );
-        $headers = array();
</del><ins>+function _get_random_header_data() {
+        static $_wp_random_header;
</ins><span class="cx"> 
</span><del>-        if ( 'random-uploaded-image' == $header_image_mod )
-                $headers = get_uploaded_header_images();
-        elseif ( ! empty( $_wp_default_headers ) ) {
-                if ( 'random-default-image' == $header_image_mod ) {
-                        $headers = $_wp_default_headers;
-                } else {
-                        $is_random = get_theme_support( 'custom-header' );
-                        if ( isset( $is_random[ 0 ] ) &amp;&amp; !empty( $is_random[ 0 ][ 'random-default' ] ) )
</del><ins>+        if ( empty( $_wp_random_header ) ) {
+                global $_wp_default_headers;
+                $header_image_mod = get_theme_mod( 'header_image', '' );
+                $headers = array();
+
+                if ( 'random-uploaded-image' == $header_image_mod )
+                        $headers = get_uploaded_header_images();
+                elseif ( ! empty( $_wp_default_headers ) ) {
+                        if ( 'random-default-image' == $header_image_mod ) {
</ins><span class="cx">                                 $headers = $_wp_default_headers;
</span><ins>+                        } else {
+                                $is_random = get_theme_support( 'custom-header' );
+                                if ( isset( $is_random[ 0 ] ) &amp;&amp; !empty( $is_random[ 0 ][ 'random-default' ] ) )
+                                        $headers = $_wp_default_headers;
+                        }
</ins><span class="cx">                 }
</span><del>-        }
</del><span class="cx"> 
</span><del>-        if ( empty( $headers ) )
-                return '';
</del><ins>+                if ( empty( $headers ) )
+                        return stdClass();
</ins><span class="cx"> 
</span><del>-        $random_image = array_rand( $headers );
-        $header_url = sprintf( $headers[$random_image]['url'], get_template_directory_uri(), get_stylesheet_directory_uri() );
</del><ins>+                $_wp_random_header = (object) $headers[ array_rand( $headers ) ];
</ins><span class="cx"> 
</span><del>-        return $header_url;
</del><ins>+                $_wp_random_header-&gt;url =  sprintf( $_wp_random_header-&gt;url, get_template_directory_uri(), get_stylesheet_directory_uri() );
+                $_wp_random_header-&gt;thumbnail_url =  sprintf( $_wp_random_header-&gt;thumbnail_url, get_template_directory_uri(), get_stylesheet_directory_uri() );
+        }
+        return $_wp_random_header;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /**
</span><ins>+ * Get random header image url from registered images in theme.
+ *
+ * @since 3.2.0
+ *
+ * @return string Path to header image
+ */
+
+function get_random_header_image() {
+        $random_image = _get_random_header_data();
+        if ( empty( $random_image-&gt;url ) )
+                return '';
+        return $random_image-&gt;url;
+}
+
+/**
</ins><span class="cx">  * Check if random header image is in use.
</span><span class="cx">  *
</span><span class="cx">  * Always true if user expressly chooses the option in Appearance &gt; Header.
</span><span class="lines">@@ -1547,17 +1572,60 @@
</span><span class="cx"> 
</span><span class="cx">         foreach ( (array) $headers as $header ) {
</span><span class="cx">                 $url = esc_url_raw( $header-&gt;guid );
</span><del>-                $header = basename($url);
-                $header_images[$header] = array();
-                $header_images[$header]['url'] =  $url;
-                $header_images[$header]['thumbnail_url'] =  $url;
-                $header_images[$header]['uploaded'] = true;
</del><ins>+                $header_data = wp_get_attachment_metadata( $header-&gt;ID );
+                $header_index = basename($url);
+                $header_images[$header_index] = array();
+                $header_images[$header_index]['attachment_id'] =  $header-&gt;ID;
+                $header_images[$header_index]['url'] =  $url;
+                $header_images[$header_index]['thumbnail_url'] =  $url;
+                $header_images[$header_index]['width'] = $header_data['width'];
+                $header_images[$header_index]['height'] = $header_data['height'];
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         return $header_images;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /**
</span><ins>+ * Get the header image data.
+ *
+ * @since 3.4.0
+ *
+ * @return object
+ */
+function get_current_header_data() {
+        $data = is_random_header_image()? _get_random_header_data() : get_theme_mod( 'header_image_data' );
+        $default = array(
+                'url'           =&gt; '',
+                'thumbnail_url' =&gt; '',
+                'width'         =&gt; '',
+                'height'        =&gt; '',
+        );
+        return (object) wp_parse_args( $data, $default );
+}
+
+/**
+ * Get the header image width.
+ *
+ * @since 3.4.0
+ *
+ * @return int
+ */
+function get_header_image_width() {
+        return empty( get_current_header_data()-&gt;width )? HEADER_IMAGE_WIDTH : get_current_header_data()-&gt;width;
+}
+
+/**
+ * Get the header image height.
+ *
+ * @since 3.4.0
+ *
+ * @return int
+ */
+function get_header_image_height() {
+        return empty( get_current_header_data()-&gt;height )? HEADER_IMAGE_HEIGHT : get_current_header_data()-&gt;height;
+}
+
+/**
</ins><span class="cx">  * Add callbacks for image header display.
</span><span class="cx">  *
</span><span class="cx">  * The parameter $header_callback callback will be required to display the
</span><span class="lines">@@ -1955,6 +2023,13 @@
</span><span class="cx">                         $post_format = $args[0];
</span><span class="cx">                         return in_array( $post_format, $_wp_theme_features[$feature][0] );
</span><span class="cx">                         break;
</span><ins>+
+                case 'custom-header':
+                        // specific custom header capabilities can be registered by passing
+                        // an array to add_theme_support()
+                        $header_support = $args[0];
+                        return ( isset( $_wp_theme_features[$feature][0][$header_support] ) &amp;&amp; $_wp_theme_features[$feature][0][$header_support] );
+                        break;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         return apply_filters('current_theme_supports-' . $feature, true, $args, $_wp_theme_features[$feature]);
</span></span></pre>
</div>
</div>

</body>
</html>