Make WordPress Core


Ignore:
Timestamp:
03/11/2014 04:12:17 AM (11 years ago)
Author:
nacin
Message:

Add header image uploads with cropping to the customizer.

props mcsf, ehg, gcorne.
see #21785.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/custom-header.php

    r27469 r27497  
    4444
    4545    /**
    46      * Holds custom headers uploaded by the user
     46     * Holds custom headers uploaded by the user.
    4747     *
    4848     * @var array
     
    7474
    7575        add_action( 'admin_menu', array( $this, 'init' ) );
     76
     77        add_action( 'customize_save_after',         array( $this, 'customize_set_last_used' ) );
     78        add_action( 'wp_ajax_custom-header-crop',   array( $this, 'ajax_header_crop'        ) );
     79        add_action( 'wp_ajax_custom-header-add',    array( $this, 'ajax_header_add'         ) );
     80        add_action( 'wp_ajax_custom-header-remove', array( $this, 'ajax_header_remove'      ) );
    7681    }
    7782
     
    9499        if ( $this->admin_header_callback )
    95100            add_action("admin_head-$page", $this->admin_header_callback, 51);
     101
    96102    }
    97103
     
    820826        $original = get_attached_file($attachment_id);
    821827
    822 
    823         $max_width = 0;
    824         // For flex, limit size of image displayed to 1500px unless theme says otherwise
    825         if ( current_theme_supports( 'custom-header', 'flex-width' ) )
    826             $max_width = 1500;
    827 
    828         if ( current_theme_supports( 'custom-header', 'max-width' ) )
    829             $max_width = max( $max_width, get_theme_support( 'custom-header', 'max-width' ) );
    830         $max_width = max( $max_width, get_theme_support( 'custom-header', 'width' ) );
    831 
    832         if ( ( current_theme_supports( 'custom-header', 'flex-height' ) && ! current_theme_supports( 'custom-header', 'flex-width' ) ) || $_POST['width'] > $max_width )
    833             $dst_height = absint( $_POST['height'] * ( $max_width / $_POST['width'] ) );
    834         elseif ( current_theme_supports( 'custom-header', 'flex-height' ) && current_theme_supports( 'custom-header', 'flex-width' ) )
    835             $dst_height = absint( $_POST['height'] );
    836         else
    837             $dst_height = get_theme_support( 'custom-header', 'height' );
    838 
    839         if ( ( current_theme_supports( 'custom-header', 'flex-width' ) && ! current_theme_supports( 'custom-header', 'flex-height' ) ) || $_POST['width'] > $max_width )
    840             $dst_width = absint( $_POST['width'] * ( $max_width / $_POST['width'] ) );
    841         elseif ( current_theme_supports( 'custom-header', 'flex-width' ) && current_theme_supports( 'custom-header', 'flex-height' ) )
    842             $dst_width = absint( $_POST['width'] );
    843         else
    844             $dst_width = get_theme_support( 'custom-header', 'width' );
     828        $dimensions = $this->get_header_dimensions( array(
     829            'height' => $_POST['height'],
     830            'width'  => $_POST['width'],
     831        ) );
     832        $height = $dimensions['dst_height'];
     833        $width = $dimensions['dst_width'];
    845834
    846835        if ( empty( $_POST['skip-cropping'] ) )
    847             $cropped = wp_crop_image( $attachment_id, (int) $_POST['x1'], (int) $_POST['y1'], (int) $_POST['width'], (int) $_POST['height'], $dst_width, $dst_height );
     836            $cropped = wp_crop_image( $attachment_id, (int) $_POST['x1'], (int) $_POST['y1'], (int) $_POST['width'], (int) $_POST['height'], $width, $height );
    848837        elseif ( ! empty( $_POST['create-new-attachment'] ) )
    849838            $cropped = _copy_image_file( $attachment_id );
     
    857846        $cropped = apply_filters( 'wp_create_file_in_uploads', $cropped, $attachment_id ); // For replication
    858847
    859         $parent = get_post($attachment_id);
    860         $parent_url = $parent->guid;
    861         $url = str_replace( basename( $parent_url ), basename( $cropped ), $parent_url );
    862 
    863         $size = @getimagesize( $cropped );
    864         $image_type = ( $size ) ? $size['mime'] : 'image/jpeg';
    865 
    866         // Construct the object array
    867         $object = array(
    868             'ID' => $attachment_id,
    869             'post_title' => basename($cropped),
    870             'post_content' => $url,
    871             'post_mime_type' => $image_type,
    872             'guid' => $url,
    873             'context' => 'custom-header'
    874         );
     848        $object = $this->create_attachment_object( $cropped, $attachment_id );
     849
    875850        if ( ! empty( $_POST['create-new-attachment'] ) )
    876851            unset( $object['ID'] );
    877852
    878853        // Update the attachment
    879         $attachment_id = wp_insert_attachment( $object, $cropped );
    880         wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, $cropped ) );
    881 
    882         $width = $dst_width;
    883         $height = $dst_height;
     854        $attachment_id = $this->insert_attachment( $object, $cropped );
     855
     856        $url = $object['guid'];
    884857        $this->set_header_image( compact( 'url', 'attachment_id', 'width', 'height' ) );
    885858
     
    10421015        set_theme_mod( 'header_image_data', (object) $default_data );
    10431016    }
     1017
     1018    /**
     1019     * Calculate width and height based on what the currently selected theme supports.
     1020     *
     1021     * @return array dst_height and dst_width of header image.
     1022     */
     1023    final public function get_header_dimensions( $dimensions ) {
     1024        $max_width = 0;
     1025        $width = absint( $dimensions['width'] );
     1026        $height = absint( $dimensions['height'] );
     1027        $theme_height = get_theme_support( 'custom-header', 'height' );
     1028        $theme_width = get_theme_support( 'custom-header', 'width' );
     1029        $has_flex_width = current_theme_supports( 'custom-header', 'flex-width' );
     1030        $has_flex_height = current_theme_supports( 'custom-header', 'flex-height' );
     1031        $has_max_width = current_theme_supports( 'custom-header', 'max-width' ) ;
     1032        $dst = array( 'dst_height' => null, 'dst_height' => null );
     1033
     1034        // For flex, limit size of image displayed to 1500px unless theme says otherwise
     1035        if ( $has_flex_width ) {
     1036            $max_width = 1500;
     1037        }
     1038
     1039        if ( $has_max_width ) {
     1040            $max_width = max( $max_width, get_theme_support( 'custom-header', 'max-width' ) );
     1041        }
     1042        $max_width = max( $max_width, $theme_width );
     1043
     1044        if ( $has_flex_height && ( ! $has_flex_width || $width > $max_width ) ) {
     1045            $dst['dst_height'] = absint( $height * ( $max_width / $width ) );
     1046        }
     1047        elseif ( $has_flex_height && $has_flex_width ) {
     1048            $dst['dst_height'] = $height;
     1049        }
     1050        else {
     1051            $dst['dst_height'] = $theme_height;
     1052        }
     1053
     1054        if ( $has_flex_width && ( ! $has_flex_height || $width > $max_width ) ) {
     1055            $dst['dst_width'] = absint( $width * ( $max_width / $width ) );
     1056        }
     1057        elseif ( $has_flex_width && $has_flex_height ) {
     1058            $dst['dst_width'] = $width;
     1059        }
     1060        else {
     1061            $dst['dst_width'] = $theme_width;
     1062        }
     1063
     1064        return $dst;
     1065    }
     1066
     1067    /**
     1068     * Create an attachment 'object'.
     1069     *
     1070     * @param string $cropped Cropped image URL.
     1071     * @param int $parent_attachment_id Attachment ID of parent image.
     1072     *
     1073     * @return array Attachment object.
     1074     */
     1075    final public function create_attachment_object( $cropped, $parent_attachment_id ) {
     1076        $parent = get_post( $parent_attachment_id );
     1077        $parent_url = $parent->guid;
     1078        $url = str_replace( basename( $parent_url ), basename( $cropped ), $parent_url );
     1079
     1080        $size = @getimagesize( $cropped );
     1081        $image_type = ( $size ) ? $size['mime'] : 'image/jpeg';
     1082
     1083        $object = array(
     1084            'ID' => $parent_attachment_id,
     1085            'post_title' => basename($cropped),
     1086            'post_content' => $url,
     1087            'post_mime_type' => $image_type,
     1088            'guid' => $url,
     1089            'context' => 'custom-header'
     1090        );
     1091
     1092        return $object;
     1093    }
     1094
     1095    /**
     1096     * Insert an attachment & its metadata.
     1097     *
     1098     * @param array $object Attachment object.
     1099     * @param string $cropped Cropped image URL.
     1100     *
     1101     * @return int Attachment ID.
     1102     */
     1103    final public function insert_attachment( $object, $cropped ) {
     1104        $attachment_id = wp_insert_attachment( $object, $cropped );
     1105        $metadata = wp_generate_attachment_metadata( $attachment_id, $cropped );
     1106        /**
     1107         * Allows us to insert custom meta data for an attachment.
     1108         *
     1109         */
     1110        $metadata = apply_filters( 'wp_header_image_attachment_metadata', $metadata );
     1111        wp_update_attachment_metadata( $attachment_id, $metadata );
     1112        return $attachment_id;
     1113    }
     1114
     1115    /**
     1116     * Gets attachment uploaded by Media Manager, crops it, then saves it as a
     1117     * new object. Returns JSON-encoded object details.
     1118     */
     1119    function ajax_header_crop() {
     1120        check_ajax_referer( 'image_editor-' . $_POST['id'], 'nonce' );
     1121
     1122        if ( ! current_user_can( 'edit_theme_options' ) ) {
     1123            wp_send_json_error();
     1124        }
     1125
     1126        if ( ! current_theme_supports( 'custom-header', 'uploads' ) ) {
     1127            wp_send_json_error();
     1128        }
     1129
     1130        $crop_details = $_POST['cropDetails'];
     1131
     1132        $dimensions = $this->get_header_dimensions( array(
     1133            'height' => $crop_details['height'],
     1134            'width'  => $crop_details['width'],
     1135        ) );
     1136
     1137        $attachment_id = absint( $_POST['id'] );
     1138
     1139        $cropped = wp_crop_image(
     1140            $attachment_id,
     1141            (int) $crop_details['x1'],
     1142            (int) $crop_details['y1'],
     1143            (int) $crop_details['width'],
     1144            (int) $crop_details['height'],
     1145            (int) $dimensions['dst_width'],
     1146            (int) $dimensions['dst_height']
     1147        );
     1148
     1149        if ( ! $cropped || is_wp_error( $cropped ) ) {
     1150            wp_send_json_error( array( 'message' => __( 'Image could not be processed. Please go back and try again.' ) ) );
     1151        }
     1152
     1153        $cropped = apply_filters( 'wp_create_file_in_uploads', $cropped, $attachment_id ); // For replication
     1154
     1155        $object = $this->create_attachment_object( $cropped, $attachment_id );
     1156
     1157        unset( $object['ID'] );
     1158
     1159        $new_attachment_id = $this->insert_attachment( $object, $cropped );
     1160
     1161        $object['attachment_id'] = $new_attachment_id;
     1162        $object['width']         = $dimensions['dst_width'];
     1163        $object['height']        = $dimensions['dst_height'];
     1164
     1165        wp_send_json_success( $object );
     1166    }
     1167
     1168    /**
     1169     * Given an attachment ID for a header image, updates its "last used"
     1170     * timestamp to now.
     1171     *
     1172     * Triggered when the user tries adds a new header image from the
     1173     * Media Manager, even if s/he doesn't save that change.
     1174     */
     1175    function ajax_header_add() {
     1176        check_ajax_referer( 'header-add', 'nonce' );
     1177
     1178        if ( ! current_user_can( 'edit_theme_options' ) ) {
     1179            wp_send_json_error();
     1180        }
     1181
     1182        $attachment_id = absint( $_POST['attachment_id'] );
     1183        if ( $attachment_id < 1 ) {
     1184            wp_send_json_error();
     1185        }
     1186
     1187        $key = '_wp_attachment_custom_header_last_used_' . get_stylesheet();
     1188        update_post_meta( $attachment_id, $key, time() );
     1189        update_post_meta( $attachment_id, '_wp_attachment_is_custom_header', get_stylesheet() );
     1190
     1191        wp_send_json_success();
     1192    }
     1193
     1194    /**
     1195     * Given an attachment ID for a header image, unsets it as a user-uploaded
     1196     * header image for the current theme.
     1197     *
     1198     * Triggered when the user clicks the overlay "X" button next to each image
     1199     * choice in the Customizer's Header tool.
     1200     */
     1201    function ajax_header_remove() {
     1202        check_ajax_referer( 'header-remove', 'nonce' );
     1203
     1204        if ( ! current_user_can( 'edit_theme_options' ) ) {
     1205            wp_send_json_error();
     1206        }
     1207
     1208        $attachment_id = absint( $_POST['attachment_id'] );
     1209        if ( $attachment_id < 1 ) {
     1210            wp_send_json_error();
     1211        }
     1212
     1213        $key = '_wp_attachment_custom_header_last_used_' . get_stylesheet();
     1214        delete_post_meta( $attachment_id, $key );
     1215        delete_post_meta( $attachment_id, '_wp_attachment_is_custom_header', get_stylesheet() );
     1216
     1217        wp_send_json_success();
     1218    }
     1219
     1220    function customize_set_last_used( $wp_customize ) {
     1221        $data = $wp_customize->get_setting( 'header_image_data' )->post_value();
     1222
     1223        if ( ! isset( $data['attachment_id'] ) ) {
     1224            return;
     1225        }
     1226
     1227        $attachment_id = $data['attachment_id'];
     1228        $key = '_wp_attachment_custom_header_last_used_' . get_stylesheet();
     1229        update_post_meta( $attachment_id, $key, time() );
     1230    }
    10441231}
Note: See TracChangeset for help on using the changeset viewer.