diff --git a/wp-admin/custom-header.php b/wp-admin/custom-header.php index a06756a280..8b2973fc11 100644 --- a/wp-admin/custom-header.php +++ b/wp-admin/custom-header.php @@ -1164,7 +1164,8 @@ wp_nonce_field( 'custom-header-options', '_wpnonce-custom-header-options' ); ?> 'post_title' => basename($cropped), 'post_mime_type' => $image_type, 'guid' => $url, - 'context' => 'custom-header' + 'context' => 'custom-header', + 'post_parent' => $parent_attachment_id, ); return $object; @@ -1180,8 +1181,12 @@ wp_nonce_field( 'custom-header-options', '_wpnonce-custom-header-options' ); ?> * @return int Attachment ID. */ final public function insert_attachment( $object, $cropped ) { + $parent_id = isset( $object['post_parent'] ) ? $object['post_parent'] : null; + unset( $object['post_parent'] ); + $attachment_id = wp_insert_attachment( $object, $cropped ); $metadata = wp_generate_attachment_metadata( $attachment_id, $cropped ); + /** * Filters the header image attachment metadata. * @@ -1193,6 +1198,11 @@ wp_nonce_field( 'custom-header-options', '_wpnonce-custom-header-options' ); ?> */ $metadata = apply_filters( 'wp_header_image_attachment_metadata', $metadata ); wp_update_attachment_metadata( $attachment_id, $metadata ); + + if ( $parent_id ) { + $meta = add_post_meta( $attachment_id, '_wp_attachment_parent', $parent_id, true ); + } + return $attachment_id; } @@ -1241,7 +1251,13 @@ wp_nonce_field( 'custom-header-options', '_wpnonce-custom-header-options' ); ?> $object = $this->create_attachment_object( $cropped, $attachment_id ); - unset( $object['ID'] ); + $previous = $this->get_previous_crop( $object ); + + if ( $previous ) { + $object['ID'] = $previous; + } else { + unset( $object['ID'] ); + } $new_attachment_id = $this->insert_attachment( $object, $cropped ); @@ -1396,4 +1412,32 @@ wp_nonce_field( 'custom-header-options', '_wpnonce-custom-header-options' ); ?> return $header_images; } + + /** + * Get the ID of a previous crop from the same base image. + * + * @since 4.9.0 + * + * @param array $object A crop attachment object. + * @return int|false An attachment ID if one exists. False if none. + */ + public function get_previous_crop( $object ) { + $header_images = $this->get_uploaded_header_images(); + + // Bail early if there are no header images. + if ( empty( $header_images ) ) { + return false; + } + + $previous = false; + + foreach ( $header_images as $image ) { + if ( $image['attachment_parent'] === $object['post_parent'] ) { + $previous = $image['attachment_id']; + break; + } + } + + return $previous; + } } diff --git a/wp-includes/js/customize-models.js b/wp-includes/js/customize-models.js index 372cad6273..e2a5dfbcd3 100644 --- a/wp-includes/js/customize-models.js +++ b/wp-includes/js/customize-models.js @@ -164,6 +164,7 @@ this.on('control:setImage', this.setImage, this); this.on('control:removeImage', this.removeImage, this); + this.on('add', this.maybeRemoveOldCrop, this); this.on('add', this.maybeAddRandomChoice, this); _.each(this.data, function(elt, index) { @@ -187,6 +188,25 @@ } }, + maybeRemoveOldCrop: function( model ) { + var newID = model.get( 'header' ).attachment_id || false, + oldCrop; + + // Bail early if we don't have a new attachment ID. + if ( ! newID ) { + return; + } + + oldCrop = this.find( function( item ) { + return ( item.cid !== model.cid && item.get( 'header' ).attachment_id === newID ); + } ); + + // If we found an old crop, remove it from the collection. + if ( oldCrop ) { + this.remove( oldCrop ); + } + }, + maybeAddRandomChoice: function() { if (this.size() === 1) { this.addRandomChoice(); diff --git a/wp-includes/js/customize-models.min.js b/wp-includes/js/customize-models.min.js index 0e7def5114..3ba2c87979 100644 --- a/wp-includes/js/customize-models.min.js +++ b/wp-includes/js/customize-models.min.js @@ -1 +1 @@ -!function(a,b){var c=b.customize;c.HeaderTool={},c.HeaderTool.ImageModel=Backbone.Model.extend({defaults:function(){return{header:{attachment_id:0,url:"",timestamp:_.now(),thumbnail_url:""},choice:"",selected:!1,random:!1}},initialize:function(){this.on("hide",this.hide,this)},hide:function(){this.set("choice",""),c("header_image").set("remove-header"),c("header_image_data").set("remove-header")},destroy:function(){var a=this.get("header"),d=c.HeaderTool.currentHeader.get("header").attachment_id;d&&a.attachment_id===d&&c.HeaderTool.currentHeader.trigger("hide"),b.ajax.post("custom-header-remove",{nonce:_wpCustomizeHeader.nonces.remove,wp_customize:"on",theme:c.settings.theme.stylesheet,attachment_id:a.attachment_id}),this.trigger("destroy",this,this.collection)},save:function(){this.get("random")?(c("header_image").set(this.get("header").random),c("header_image_data").set(this.get("header").random)):this.get("header").defaultName?(c("header_image").set(this.get("header").url),c("header_image_data").set(this.get("header").defaultName)):(c("header_image").set(this.get("header").url),c("header_image_data").set(this.get("header"))),c.HeaderTool.combinedList.trigger("control:setImage",this)},importImage:function(){var a=this.get("header");void 0!==a.attachment_id&&b.ajax.post("custom-header-add",{nonce:_wpCustomizeHeader.nonces.add,wp_customize:"on",theme:c.settings.theme.stylesheet,attachment_id:a.attachment_id})},shouldBeCropped:function(){return(this.get("themeFlexWidth")!==!0||this.get("themeFlexHeight")!==!0)&&((this.get("themeFlexWidth")!==!0||this.get("themeHeight")!==this.get("imageHeight"))&&((this.get("themeFlexHeight")!==!0||this.get("themeWidth")!==this.get("imageWidth"))&&((this.get("themeWidth")!==this.get("imageWidth")||this.get("themeHeight")!==this.get("imageHeight"))&&!(this.get("imageWidth")<=this.get("themeWidth")))))}}),c.HeaderTool.ChoiceList=Backbone.Collection.extend({model:c.HeaderTool.ImageModel,comparator:function(a){return-a.get("header").timestamp},initialize:function(){var a=c.HeaderTool.currentHeader.get("choice").replace(/^https?:\/\//,""),b=this.isRandomChoice(c.get().header_image);this.type||(this.type="uploaded"),"undefined"==typeof this.data&&(this.data=_wpCustomizeHeader.uploads),b&&(a=c.get().header_image),this.on("control:setImage",this.setImage,this),this.on("control:removeImage",this.removeImage,this),this.on("add",this.maybeAddRandomChoice,this),_.each(this.data,function(b,c){b.attachment_id||(b.defaultName=c),"undefined"==typeof b.timestamp&&(b.timestamp=0),this.add({header:b,choice:b.url.split("/").pop(),selected:a===b.url.replace(/^https?:\/\//,"")},{silent:!0})},this),this.size()>0&&this.addRandomChoice(a)},maybeAddRandomChoice:function(){1===this.size()&&this.addRandomChoice()},addRandomChoice:function(a){var b=RegExp(this.type).test(a),c="random-"+this.type+"-image";this.add({header:{timestamp:0,random:c,width:245,height:41},choice:c,random:!0,selected:b})},isRandomChoice:function(a){return/^random-(uploaded|default)-image$/.test(a)},shouldHideTitle:function(){return this.size()<2},setImage:function(a){this.each(function(a){a.set("selected",!1)}),a&&a.set("selected",!0)},removeImage:function(){this.each(function(a){a.set("selected",!1)})}}),c.HeaderTool.DefaultsList=c.HeaderTool.ChoiceList.extend({initialize:function(){this.type="default",this.data=_wpCustomizeHeader.defaults,c.HeaderTool.ChoiceList.prototype.initialize.apply(this)}})}(jQuery,window.wp); \ No newline at end of file +!function(a,b){var c=b.customize;c.HeaderTool={},c.HeaderTool.ImageModel=Backbone.Model.extend({defaults:function(){return{header:{attachment_id:0,url:"",timestamp:_.now(),thumbnail_url:""},choice:"",selected:!1,random:!1}},initialize:function(){this.on("hide",this.hide,this)},hide:function(){this.set("choice",""),c("header_image").set("remove-header"),c("header_image_data").set("remove-header")},destroy:function(){var a=this.get("header"),d=c.HeaderTool.currentHeader.get("header").attachment_id;d&&a.attachment_id===d&&c.HeaderTool.currentHeader.trigger("hide"),b.ajax.post("custom-header-remove",{nonce:_wpCustomizeHeader.nonces.remove,wp_customize:"on",theme:c.settings.theme.stylesheet,attachment_id:a.attachment_id}),this.trigger("destroy",this,this.collection)},save:function(){this.get("random")?(c("header_image").set(this.get("header").random),c("header_image_data").set(this.get("header").random)):this.get("header").defaultName?(c("header_image").set(this.get("header").url),c("header_image_data").set(this.get("header").defaultName)):(c("header_image").set(this.get("header").url),c("header_image_data").set(this.get("header"))),c.HeaderTool.combinedList.trigger("control:setImage",this)},importImage:function(){var a=this.get("header");void 0!==a.attachment_id&&b.ajax.post("custom-header-add",{nonce:_wpCustomizeHeader.nonces.add,wp_customize:"on",theme:c.settings.theme.stylesheet,attachment_id:a.attachment_id})},shouldBeCropped:function(){return(this.get("themeFlexWidth")!==!0||this.get("themeFlexHeight")!==!0)&&((this.get("themeFlexWidth")!==!0||this.get("themeHeight")!==this.get("imageHeight"))&&((this.get("themeFlexHeight")!==!0||this.get("themeWidth")!==this.get("imageWidth"))&&((this.get("themeWidth")!==this.get("imageWidth")||this.get("themeHeight")!==this.get("imageHeight"))&&!(this.get("imageWidth")<=this.get("themeWidth")))))}}),c.HeaderTool.ChoiceList=Backbone.Collection.extend({model:c.HeaderTool.ImageModel,comparator:function(a){return-a.get("header").timestamp},initialize:function(){var a=c.HeaderTool.currentHeader.get("choice").replace(/^https?:\/\//,""),b=this.isRandomChoice(c.get().header_image);this.type||(this.type="uploaded"),"undefined"==typeof this.data&&(this.data=_wpCustomizeHeader.uploads),b&&(a=c.get().header_image),this.on("control:setImage",this.setImage,this),this.on("control:removeImage",this.removeImage,this),this.on("add",this.maybeRemoveOldCrop,this),this.on("add",this.maybeAddRandomChoice,this),_.each(this.data,function(b,c){b.attachment_id||(b.defaultName=c),"undefined"==typeof b.timestamp&&(b.timestamp=0),this.add({header:b,choice:b.url.split("/").pop(),selected:a===b.url.replace(/^https?:\/\//,"")},{silent:!0})},this),this.size()>0&&this.addRandomChoice(a)},maybeRemoveOldCrop:function(a){var b,c=a.get("header").attachment_id||!1;c&&(b=this.find(function(b){return b.cid!==a.cid&&b.get("header").attachment_id===c}),b&&this.remove(b))},maybeAddRandomChoice:function(){1===this.size()&&this.addRandomChoice()},addRandomChoice:function(a){var b=RegExp(this.type).test(a),c="random-"+this.type+"-image";this.add({header:{timestamp:0,random:c,width:245,height:41},choice:c,random:!0,selected:b})},isRandomChoice:function(a){return/^random-(uploaded|default)-image$/.test(a)},shouldHideTitle:function(){return this.size()<2},setImage:function(a){this.each(function(a){a.set("selected",!1)}),a&&a.set("selected",!0)},removeImage:function(){this.each(function(a){a.set("selected",!1)})}}),c.HeaderTool.DefaultsList=c.HeaderTool.ChoiceList.extend({initialize:function(){this.type="default",this.data=_wpCustomizeHeader.defaults,c.HeaderTool.ChoiceList.prototype.initialize.apply(this)}})}(jQuery,window.wp); \ No newline at end of file diff --git a/wp-includes/theme.php b/wp-includes/theme.php index 6909d0fe2e..2ee66fbddf 100644 --- a/wp-includes/theme.php +++ b/wp-includes/theme.php @@ -1214,6 +1214,7 @@ function get_uploaded_header_images() { $header_images[$header_index]['url'] = $url; $header_images[$header_index]['thumbnail_url'] = $url; $header_images[$header_index]['alt_text'] = get_post_meta( $header->ID, '_wp_attachment_image_alt', true ); + $header_images[$header_index]['attachment_parent'] = (int) get_post_meta( $header->ID, '_wp_attachment_parent', true ); if ( isset( $header_data['width'] ) ) $header_images[$header_index]['width'] = $header_data['width']; diff --git a/wp-includes/version.php b/wp-includes/version.php index 0f6a55c375..15b58e59c6 100644 --- a/wp-includes/version.php +++ b/wp-includes/version.php @@ -4,7 +4,7 @@ * * @global string $wp_version */ -$wp_version = '4.9-alpha-41731'; +$wp_version = '4.9-alpha-41732'; /** * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.