818
828
$attachment_id = absint( $_POST['attachment_id'] );
819
829
$original = get_attached_file($attachment_id);
823
// For flex, limit size of image displayed to 1500px unless theme says otherwise
824
if ( current_theme_supports( 'custom-header', 'flex-width' ) )
827
if ( current_theme_supports( 'custom-header', 'max-width' ) )
828
$max_width = max( $max_width, get_theme_support( 'custom-header', 'max-width' ) );
829
$max_width = max( $max_width, get_theme_support( 'custom-header', 'width' ) );
831
if ( ( current_theme_supports( 'custom-header', 'flex-height' ) && ! current_theme_supports( 'custom-header', 'flex-width' ) ) || $_POST['width'] > $max_width )
832
$dst_height = absint( $_POST['height'] * ( $max_width / $_POST['width'] ) );
833
elseif ( current_theme_supports( 'custom-header', 'flex-height' ) && current_theme_supports( 'custom-header', 'flex-width' ) )
834
$dst_height = absint( $_POST['height'] );
836
$dst_height = get_theme_support( 'custom-header', 'height' );
838
if ( ( current_theme_supports( 'custom-header', 'flex-width' ) && ! current_theme_supports( 'custom-header', 'flex-height' ) ) || $_POST['width'] > $max_width )
839
$dst_width = absint( $_POST['width'] * ( $max_width / $_POST['width'] ) );
840
elseif ( current_theme_supports( 'custom-header', 'flex-width' ) && current_theme_supports( 'custom-header', 'flex-height' ) )
841
$dst_width = absint( $_POST['width'] );
843
$dst_width = get_theme_support( 'custom-header', 'width' );
831
$dimensions = $this->get_header_dimensions( array(
832
'height' => $_POST['height'],
833
'width' => $_POST['width'],
835
$height = $dimensions['dst_height'];
836
$width = $dimensions['dst_width'];
845
838
if ( empty( $_POST['skip-cropping'] ) )
846
$cropped = wp_crop_image( $attachment_id, (int) $_POST['x1'], (int) $_POST['y1'], (int) $_POST['width'], (int) $_POST['height'], $dst_width, $dst_height );
839
$cropped = wp_crop_image( $attachment_id, (int) $_POST['x1'], (int) $_POST['y1'], (int) $_POST['width'], (int) $_POST['height'], $width, $height );
847
840
elseif ( ! empty( $_POST['create-new-attachment'] ) )
848
841
$cropped = _copy_image_file( $attachment_id );
1040
1017
set_theme_mod( 'header_image', $default );
1041
1018
set_theme_mod( 'header_image_data', (object) $default_data );
1022
* Calculate width and height based on what the currently selected theme supports.
1024
* @return array dst_height and dst_width of header image.
1026
final public function get_header_dimensions( $dimensions ) {
1028
$width = absint( $dimensions['width'] );
1029
$height = absint( $dimensions['height'] );
1030
$theme_height = get_theme_support( 'custom-header', 'height' );
1031
$theme_width = get_theme_support( 'custom-header', 'width' );
1032
$has_flex_width = current_theme_supports( 'custom-header', 'flex-width' );
1033
$has_flex_height = current_theme_supports( 'custom-header', 'flex-height' );
1034
$has_max_width = current_theme_supports( 'custom-header', 'max-width' ) ;
1035
$dst = array( 'dst_height' => null, 'dst_height' => null );
1037
// For flex, limit size of image displayed to 1500px unless theme says otherwise
1038
if ( $has_flex_width ) {
1042
if ( $has_max_width ) {
1043
$max_width = max( $max_width, get_theme_support( 'custom-header', 'max-width' ) );
1045
$max_width = max( $max_width, $theme_width );
1047
if ( $has_flex_height && ( ! $has_flex_width || $width > $max_width ) ) {
1048
$dst['dst_height'] = absint( $height * ( $max_width / $width ) );
1050
elseif ( $has_flex_height && $has_flex_width ) {
1051
$dst['dst_height'] = $height;
1054
$dst['dst_height'] = $theme_height;
1057
if ( $has_flex_width && ( ! $has_flex_height || $width > $max_width ) ) {
1058
$dst['dst_width'] = absint( $width * ( $max_width / $width ) );
1060
elseif ( $has_flex_width && $has_flex_height ) {
1061
$dst['dst_width'] = $width;
1064
$dst['dst_width'] = $theme_width;
1071
* Create an attachment 'object'.
1073
* @param string $cropped Cropped image URL.
1074
* @param int $parent_attachment_id Attachment ID of parent image.
1076
* @return array Attachment object.
1078
final public function create_attachment_object( $cropped, $parent_attachment_id ) {
1079
$parent = get_post( $parent_attachment_id );
1080
$parent_url = $parent->guid;
1081
$url = str_replace( basename( $parent_url ), basename( $cropped ), $parent_url );
1083
$size = @getimagesize( $cropped );
1084
$image_type = ( $size ) ? $size['mime'] : 'image/jpeg';
1087
'ID' => $parent_attachment_id,
1088
'post_title' => basename($cropped),
1089
'post_content' => $url,
1090
'post_mime_type' => $image_type,
1092
'context' => 'custom-header'
1099
* Insert an attachment & its metadata.
1101
* @param array $object Attachment object.
1102
* @param string $cropped Cropped image URL.
1104
* @return int Attachment ID.
1106
final public function insert_attachment( $object, $cropped ) {
1107
$attachment_id = wp_insert_attachment( $object, $cropped );
1108
$metadata = wp_generate_attachment_metadata( $attachment_id, $cropped );
1110
* Allows us to insert custom meta data for an attachment.
1113
$metadata = apply_filters( 'wp_header_image_attachment_metadata', $metadata );
1114
wp_update_attachment_metadata( $attachment_id, $metadata );
1115
return $attachment_id;
1119
* Gets attachment uploaded by Media Manager, crops it, then saves it as a
1120
* new object. Returns JSON-encoded object details.
1122
function ajax_header_crop() {
1123
check_ajax_referer( 'image_editor-' . $_POST['id'], 'nonce' );
1125
if ( ! current_user_can( 'edit_theme_options' ) ) {
1126
wp_send_json_error();
1129
if ( ! current_theme_supports( 'custom-header', 'uploads' ) ) {
1130
wp_send_json_error();
1133
$crop_details = $_POST['cropDetails'];
1135
$dimensions = $this->get_header_dimensions( array(
1136
'height' => $crop_details['height'],
1137
'width' => $crop_details['width'],
1140
$attachment_id = absint( $_POST['id'] );
1142
$cropped = wp_crop_image(
1144
(int) $crop_details['x1'],
1145
(int) $crop_details['y1'],
1146
(int) $crop_details['width'],
1147
(int) $crop_details['height'],
1148
(int) $dimensions['dst_width'],
1149
(int) $dimensions['dst_height']
1152
if ( ! $cropped || is_wp_error( $cropped ) ) {
1153
wp_send_json_error( array( 'message' => __( 'Image could not be processed. Please go back and try again.' ) ) );
1156
$cropped = apply_filters( 'wp_create_file_in_uploads', $cropped, $attachment_id ); // For replication
1158
$object = $this->create_attachment_object( $cropped, $attachment_id );
1160
unset( $object['ID'] );
1162
$new_attachment_id = $this->insert_attachment( $object, $cropped );
1164
$object['attachment_id'] = $new_attachment_id;
1165
$object['width'] = $dimensions['dst_width'];
1166
$object['height'] = $dimensions['dst_height'];
1168
wp_send_json_success( $object );
1172
* Given an attachment ID for a header image, updates its "last used"
1175
* Triggered when the user tries adds a new header image from the
1176
* Media Manager, even if s/he doesn't save that change.
1178
function ajax_header_add() {
1179
check_ajax_referer( 'header-add', 'nonce' );
1181
if ( ! current_user_can( 'edit_theme_options' ) ) {
1182
wp_send_json_error();
1185
$attachment_id = absint( $_POST['attachment_id'] );
1186
if ( $attachment_id < 1 ) {
1187
wp_send_json_error();
1190
$key = '_wp_attachment_custom_header_last_used_' . get_stylesheet();
1191
update_post_meta( $attachment_id, $key, time() );
1192
update_post_meta( $attachment_id, '_wp_attachment_is_custom_header', get_stylesheet() );
1194
wp_send_json_success();
1198
* Given an attachment ID for a header image, unsets it as a user-uploaded
1199
* header image for the current theme.
1201
* Triggered when the user clicks the overlay "X" button next to each image
1202
* choice in the Customizer's Header tool.
1204
function ajax_header_remove() {
1205
check_ajax_referer( 'header-remove', 'nonce' );
1207
if ( ! current_user_can( 'edit_theme_options' ) ) {
1208
wp_send_json_error();
1211
$attachment_id = absint( $_POST['attachment_id'] );
1212
if ( $attachment_id < 1 ) {
1213
wp_send_json_error();
1216
$key = '_wp_attachment_custom_header_last_used_' . get_stylesheet();
1217
delete_post_meta( $attachment_id, $key );
1218
delete_post_meta( $attachment_id, '_wp_attachment_is_custom_header', get_stylesheet() );
1220
wp_send_json_success();
1223
function customize_set_last_used( $wp_customize ) {
1224
$data = $wp_customize->get_setting( 'header_image_data' )->post_value();
1226
if ( ! isset( $data['attachment_id'] ) ) {
1230
$attachment_id = $data['attachment_id'];
1231
$key = '_wp_attachment_custom_header_last_used_' . get_stylesheet();
1232
update_post_meta( $attachment_id, $key, time() );
1235
public function get_default_header_images() {
1236
$this->process_default_headers();
1238
// Get the default image if there is one.
1239
$default = get_theme_support( 'custom-header', 'default-image' );
1241
if ( ! $default ) { // If not,
1242
return $this->default_headers; // easy peasy.
1245
$default = sprintf( $default, get_template_directory_uri(), get_stylesheet_directory_uri() );
1246
$already_has_default = false;
1248
foreach ( $this->default_headers as $k => $h ) {
1249
if ( $h['url'] === $default ) {
1250
$already_has_default = true;
1255
if ( $already_has_default ) {
1256
return $this->default_headers;
1259
// If the one true image isn't included in the default set, prepend it.
1260
$header_images = array();
1261
$header_images['default'] = array(
1263
'thumbnail_url' => $default,
1264
'description' => 'Default'
1267
// The rest of the set comes after.
1268
$header_images = array_merge( $header_images, $this->default_headers );
1269
return $header_images;
1272
public function get_uploaded_header_images() {
1273
$header_images = get_uploaded_header_images();
1274
$timestamp_key = '_wp_attachment_custom_header_last_used_' . get_stylesheet();
1275
$alt_text_key = '_wp_attachment_image_alt';
1277
foreach ( $header_images as &$header_image ) {
1278
$header_meta = get_post_meta( $header_image['attachment_id'] );
1279
$header_image['timestamp'] = isset( $header_meta[ $timestamp_key ] ) ? $header_meta[ $timestamp_key ] : '';
1280
$header_image['alt_text'] = isset( $header_meta[ $alt_text_key ] ) ? $header_meta[ $alt_text_key ] : '';
1283
return $header_images;