Ticket #29211: 29211.4.diff
File 29211.4.diff, 27.4 KB (added by , 10 years ago) |
---|
-
src/wp-admin/css/customize-controls.css
762 788 .customize-control-upload .current, 763 789 .customize-control-image .current, 764 790 .customize-control-background .current, 791 .customize-control-cropped_image .current, 765 792 .customize-control-header .current { 766 793 margin-bottom: 8px; 767 794 } … … 797 824 .customize-control-background .remove-button, 798 825 .customize-control-background .default-button, 799 826 .customize-control-background .upload-button, 827 .customize-control-cropped_image .remove-button, 828 .customize-control-cropped_image .default-button, 829 .customize-control-cropped_image .upload-button, 800 830 .customize-control-header button.new, 801 831 .customize-control-header button.remove { 802 832 white-space: normal; … … 808 838 .customize-control-upload .current .container, 809 839 .customize-control-image .current .container, 810 840 .customize-control-background .current .container, 841 .customize-control-cropped_image .current .container, 811 842 .customize-control-header .current .container { 812 843 overflow: hidden; 813 844 -webkit-border-radius: 2px; … … 819 850 .customize-control-media .current .container, 820 851 .customize-control-upload .current .container, 821 852 .customize-control-background .current .container, 853 .customize-control-cropped_image .current .container, 822 854 .customize-control-image .current .container { 823 855 min-height: 40px; 824 856 } … … 827 859 .customize-control-upload .placeholder, 828 860 .customize-control-image .placeholder, 829 861 .customize-control-background .placeholder, 862 .customize-control-cropped_image .placeholder, 830 863 .customize-control-header .placeholder { 831 864 width: 100%; 832 865 position: relative; … … 838 871 .customize-control-upload .inner, 839 872 .customize-control-image .inner, 840 873 .customize-control-background .inner, 874 .customize-control-cropped_image .inner, 841 875 .customize-control-header .inner { 842 876 display: none; 843 877 position: absolute; … … 851 885 .customize-control-media .inner, 852 886 .customize-control-upload .inner, 853 887 .customize-control-background .inner, 888 .customize-control-cropped_image .inner, 854 889 .customize-control-image .inner { 855 890 display: block; 856 891 min-height: 40px; … … 860 895 .customize-control-upload .inner, 861 896 .customize-control-image .inner, 862 897 .customize-control-background .inner, 898 .customize-control-cropped_image .inner, 863 899 .customize-control-header .inner, 864 900 .customize-control-header .inner .dashicons { 865 901 line-height: 20px; … … 963 999 .customize-control-upload .actions, 964 1000 .customize-control-image .actions, 965 1001 .customize-control-background .actions, 1002 .customize-control-cropped_image .actions, 966 1003 .customize-control-header .actions { 967 1004 margin-bottom: 32px; 968 1005 } … … 981 1018 .customize-control-upload img, 982 1019 .customize-control-image img, 983 1020 .customize-control-background img, 1021 .customize-control-cropped_image img, 984 1022 .customize-control-header img { 985 1023 width: 100%; 986 1024 -webkit-border-radius: 2px; … … 995 1033 .customize-control-image .default-button, 996 1034 .customize-control-background .remove-button, 997 1035 .customize-control-background .default-button, 1036 .customize-control-cropped_image .remove-button, 1037 .customize-control-cropped_image .default-button, 998 1038 .customize-control-header .remove { 999 1039 float: left; 1000 1040 margin-right: 3px; … … 1004 1044 .customize-control-upload .upload-button, 1005 1045 .customize-control-image .upload-button, 1006 1046 .customize-control-background .upload-button, 1047 .customize-control-cropped_image .upload-button, 1007 1048 .customize-control-header .new { 1008 1049 float: right; 1009 1050 } -
src/wp-admin/js/customize-controls.js
1795 1795 * @augments wp.customize.Control 1796 1796 * @augments wp.customize.Class 1797 1797 */ 1798 api.ImageControl = api. UploadControl.extend({1798 api.ImageControl = api.MediaControl.extend({ 1799 1799 // @deprecated 1800 1800 thumbnailSrc: function() {} 1801 1801 }); … … 1836 1836 }); 1837 1837 1838 1838 /** 1839 * A control for selecting and cropping an image. 1840 * 1839 1841 * @class 1842 * @augments wp.customize.MediaControl 1840 1843 * @augments wp.customize.Control 1841 1844 * @augments wp.customize.Class 1842 1845 */ 1843 api.HeaderControl = api.Control.extend({ 1844 ready: function() { 1845 this.btnRemove = $('#customize-control-header_image .actions .remove'); 1846 this.btnNew = $('#customize-control-header_image .actions .new'); 1846 api.CroppedImageControl = api.MediaControl.extend({ 1847 /** 1848 * Open the media modal to the library state. 1849 */ 1850 openFrame: function( event ) { 1851 if ( api.utils.isKeydownButNotEnterEvent( event ) ) { 1852 return; 1853 } 1847 1854 1848 _.bindAll(this, 'openMedia', 'removeImage'); 1855 if ( this.frame ) { 1856 this.frame.setState( 'library' ); 1857 } 1849 1858 1850 this.btnNew.on( 'click', this.openMedia);1851 this.btnRemove.on( 'click', this.removeImage );1859 api.MediaControl.prototype.openFrame.call( this, event ); 1860 }, 1852 1861 1853 api.HeaderTool.currentHeader = this.getInitialHeaderImage(); 1862 /** 1863 * Create a media modal select frame, and store it so the instance can be reused when needed. 1864 */ 1865 initFrame: function() { 1866 var l10n = _wpMediaViewsL10n; 1854 1867 1855 new api.HeaderTool.CurrentView({ 1856 model: api.HeaderTool.currentHeader, 1857 el: '#customize-control-header_image .current .container' 1868 this.frame = wp.media({ 1869 button: { 1870 text: l10n.selectAndCrop, 1871 close: false 1872 }, 1873 states: [ 1874 new wp.media.controller.Library({ 1875 title: this.params.button_labels.frame_title, 1876 library: wp.media.query({ type: 'image' }), 1877 multiple: false, 1878 date: false, 1879 priority: 20, 1880 suggestedWidth: this.params.width, 1881 suggestedHeight: this.params.height 1882 }), 1883 new wp.media.controller.customizeImageCropper({ 1884 imgSelectOptions: this.calculateImageSelectOptions, 1885 control: this 1886 }) 1887 ] 1858 1888 }); 1859 1889 1860 new api.HeaderTool.ChoiceListView({1861 collection: api.HeaderTool.UploadsList = new api.HeaderTool.ChoiceList(),1862 el: '#customize-control-header_image .choices .uploaded .list'1863 });1890 this.frame.on( 'select', this.onSelect, this ); 1891 this.frame.on( 'cropped', this.onCropped, this ); 1892 this.frame.on( 'skippedcrop', this.onSkippedCrop, this ); 1893 }, 1864 1894 1865 new api.HeaderTool.ChoiceListView({ 1866 collection: api.HeaderTool.DefaultsList = new api.HeaderTool.DefaultsList(), 1867 el: '#customize-control-header_image .choices .default .list' 1868 }); 1869 1870 api.HeaderTool.combinedList = api.HeaderTool.CombinedList = new api.HeaderTool.CombinedList([ 1871 api.HeaderTool.UploadsList, 1872 api.HeaderTool.DefaultsList 1873 ]); 1895 /** 1896 * After an image is selected in the media modal, 1897 * switch to the cropper state. 1898 */ 1899 onSelect: function() { 1900 this.frame.setState( 'cropper' ); 1874 1901 }, 1875 1902 1876 1903 /** 1877 * Returns a new instance of api.HeaderTool.ImageModel based on the currently 1878 * saved header image (if any). 1904 * After the image has been cropped, apply the cropped image data to the setting. 1879 1905 * 1880 * @since 4.2.0 1881 * 1882 * @returns {Object} Options 1906 * @param {object} croppedImage Cropped attachment data. 1883 1907 */ 1884 getInitialHeaderImage: function() { 1885 if ( ! api.get().header_image || ! api.get().header_image_data || _.contains( [ 'remove-header', 'random-default-image', 'random-uploaded-image' ], api.get().header_image ) ) { 1886 return new api.HeaderTool.ImageModel(); 1887 } 1888 1889 // Get the matching uploaded image object. 1890 var currentHeaderObject = _.find( _wpCustomizeHeader.uploads, function( imageObj ) { 1891 return ( imageObj.attachment_id === api.get().header_image_data.attachment_id ); 1892 } ); 1893 // Fall back to raw current header image. 1894 if ( ! currentHeaderObject ) { 1895 currentHeaderObject = { 1896 url: api.get().header_image, 1897 thumbnail_url: api.get().header_image, 1898 attachment_id: api.get().header_image_data.attachment_id 1899 }; 1900 } 1901 1902 return new api.HeaderTool.ImageModel({ 1903 header: currentHeaderObject, 1904 choice: currentHeaderObject.url.split( '/' ).pop() 1905 }); 1908 onCropped: function( croppedImage ) { 1909 this.setImageFromPost( croppedImage ); 1906 1910 }, 1907 1911 1908 1912 /** 1909 1913 * Returns a set of options, computed from the attached image data and 1910 * theme-specific data, to be fed to the imgAreaSelect plugin in1914 * control-specific data, to be fed to the imgAreaSelect plugin in 1911 1915 * wp.media.view.Cropper. 1912 1916 * 1913 1917 * @param {wp.media.model.Attachment} attachment … … 1914 1918 * @param {wp.media.controller.Cropper} controller 1915 1919 * @returns {Object} Options 1916 1920 */ 1917 calculateImageSelectOptions: function(attachment, controller) { 1918 var xInit = parseInt(_wpCustomizeHeader.data.width, 10), 1919 yInit = parseInt(_wpCustomizeHeader.data.height, 10), 1920 flexWidth = !! parseInt(_wpCustomizeHeader.data['flex-width'], 10), 1921 flexHeight = !! parseInt(_wpCustomizeHeader.data['flex-height'], 10), 1922 ratio, xImg, yImg, realHeight, realWidth, 1923 imgSelectOptions; 1921 calculateImageSelectOptions: function( attachment, controller ) { 1922 var control = controller.get( 'control' ), 1923 xInit = parseInt( control.params.width, 10 ), 1924 yInit = parseInt( control.params.height, 10 ), 1925 flexWidth = !! parseInt( control.params.flex_width, 10 ), 1926 flexHeight = !! parseInt( control.params.flex_height, 10 ), 1927 ratio, xImg, yImg, realHeight, realWidth, 1928 imgSelectOptions; 1924 1929 1925 realWidth = attachment.get( 'width');1926 realHeight = attachment.get( 'height');1930 realWidth = attachment.get( 'width' ); 1931 realHeight = attachment.get( 'height' ); 1927 1932 1928 this.headerImage = new api.HeaderTool.ImageModel(); 1929 this.headerImage.set({ 1930 themeWidth: xInit, 1931 themeHeight: yInit, 1932 themeFlexWidth: flexWidth, 1933 themeFlexHeight: flexHeight, 1934 imageWidth: realWidth, 1935 imageHeight: realHeight 1936 }); 1933 controller.set( 'canSkipCrop', ! control.mustBeCropped( flexWidth, flexHeight, xInit, yInit, realWidth, realHeight ) ); 1937 1934 1938 controller.set( 'canSkipCrop', ! this.headerImage.shouldBeCropped() );1939 1940 1935 ratio = xInit / yInit; 1941 1936 xImg = realWidth; 1942 1937 yImg = realHeight; … … 1962 1957 y2: yInit 1963 1958 }; 1964 1959 1965 if ( flexHeight === false && flexWidth === false) {1960 if ( flexHeight === false && flexWidth === false ) { 1966 1961 imgSelectOptions.aspectRatio = xInit + ':' + yInit; 1967 1962 } 1968 if ( flexHeight === false ) {1963 if ( flexHeight === false ) { 1969 1964 imgSelectOptions.maxHeight = yInit; 1970 1965 } 1971 if ( flexWidth === false ) {1966 if ( flexWidth === false ) { 1972 1967 imgSelectOptions.maxWidth = xInit; 1973 1968 } 1974 1969 … … 1976 1971 }, 1977 1972 1978 1973 /** 1979 * Sets up and opens the Media Manager in order to select an image. 1980 * Depending on both the size of the image and the properties of the 1981 * current theme, a cropping step after selection may be required or 1982 * skippable. 1983 * 1984 * @param {event} event 1974 * Return whether the image must be cropped, based on required dimensions. 1985 1975 */ 1986 openMedia: function(event) { 1987 var l10n = _wpMediaViewsL10n; 1976 mustBeCropped: function( flexW, flexH, dstW, dstH, imgW, imgH ) { 1977 if ( flexW === true && flexH === true ) { 1978 return false; 1979 } 1988 1980 1989 event.preventDefault(); 1981 if ( flexW === true && dstH === imgH ) { 1982 return false; 1983 } 1990 1984 1991 this.frame = wp.media({ 1992 button: { 1993 text: l10n.selectAndCrop, 1994 close: false 1995 }, 1996 states: [ 1997 new wp.media.controller.Library({ 1998 title: l10n.chooseImage, 1999 library: wp.media.query({ type: 'image' }), 2000 multiple: false, 2001 date: false, 2002 priority: 20, 2003 suggestedWidth: _wpCustomizeHeader.data.width, 2004 suggestedHeight: _wpCustomizeHeader.data.height 2005 }), 2006 new wp.media.controller.Cropper({ 2007 imgSelectOptions: this.calculateImageSelectOptions 2008 }) 2009 ] 2010 }); 1985 if ( flexH === true && dstW === imgW ) { 1986 return false; 1987 } 2011 1988 2012 this.frame.on('select', this.onSelect, this);2013 this.frame.on('cropped', this.onCropped, this);2014 this.frame.on('skippedcrop', this.onSkippedCrop, this);1989 if ( dstW === imgW && dstH === imgH ) { 1990 return false; 1991 } 2015 1992 2016 this.frame.open(); 2017 }, 1993 if ( imgW <= dstW ) { 1994 return false; 1995 } 2018 1996 2019 /** 2020 * After an image is selected in the media modal, 2021 * switch to the cropper state. 2022 */ 2023 onSelect: function() { 2024 this.frame.setState('cropper'); 1997 return true; 2025 1998 }, 2026 1999 2027 2000 /** 2028 * After the image has been cropped, apply the cropped image data to the setting.2029 *2030 * @param {object} croppedImage Cropped attachment data.2031 */2032 onCropped: function(croppedImage) {2033 var url = croppedImage.post_content,2034 attachmentId = croppedImage.attachment_id,2035 w = croppedImage.width,2036 h = croppedImage.height;2037 this.setImageFromURL(url, attachmentId, w, h);2038 },2039 2040 /**2041 2001 * If cropping was skipped, apply the image data directly to the setting. 2042 2002 * 2043 2003 * @param {object} selection 2044 2004 */ 2045 onSkippedCrop: function(selection) { 2046 var url = selection.get('url'), 2047 w = selection.get('width'), 2048 h = selection.get('height'); 2049 this.setImageFromURL(url, selection.id, w, h); 2005 onSkippedCrop: function( selection ) { 2006 this.setImageFromPost( selection ); 2050 2007 }, 2051 2008 2052 2009 /** 2053 * Creates a new wp.customize.HeaderTool.ImageModel from provided 2054 * header image data and inserts it into the user-uploaded headers 2055 * collection. 2010 * Creates a new attachment model from provided header image data 2011 * and updates the setting, re-rendering the control UI. 2056 2012 * 2057 * @param {String} url 2058 * @param {Number} attachmentId 2059 * @param {Number} width 2060 * @param {Number} height 2013 * @param {object} post 2061 2014 */ 2062 setImageFromURL: function(url, attachmentId, width, height) { 2063 var choice, data = {}; 2015 setImageFromPost: function( post ) { 2016 var attachment = { 2017 id: post.attachment_id, 2018 type: 'image', 2019 sizes: { 2020 full: { 2021 url: post.guid 2022 } 2023 } 2024 }; 2025 this.params.attachment = attachment; 2064 2026 2065 data.url = url;2066 data.thumbnail_url = url;2067 data.timestamp = _.now();2027 // Set the Customizer setting; the callback takes care of rendering. 2028 this.setting( attachment.id ); 2029 }, 2068 2030 2069 if (attachmentId) { 2070 data.attachment_id = attachmentId; 2071 } 2031 }); 2072 2032 2073 if (width) { 2074 data.width = width; 2075 } 2033 /** 2034 * @class 2035 * @augments wp.customize.Control 2036 * @augments wp.customize.Class 2037 */ 2038 api.HeaderControl = api.CroppedImageControl.extend({ 2076 2039 2077 if (height) {2078 data.height = height;2079 }2080 2081 choice = new api.HeaderTool.ImageModel({2082 header: data,2083 choice: url.split('/').pop()2084 });2085 api.HeaderTool.UploadsList.add(choice);2086 api.HeaderTool.currentHeader.set(choice.toJSON());2087 choice.save();2088 choice.importImage();2089 },2090 2091 /**2092 * Triggers the necessary events to deselect an image which was set as2093 * the currently selected one.2094 */2095 removeImage: function() {2096 api.HeaderTool.currentHeader.trigger('hide');2097 api.HeaderTool.CombinedList.trigger('control:removeImage');2098 }2099 2100 2040 }); 2101 2041 2102 2042 /** … … 2695 2635 }); 2696 2636 2697 2637 api.controlConstructor = { 2698 color: api.ColorControl, 2699 media: api.MediaControl, 2700 upload: api.UploadControl, 2701 image: api.ImageControl, 2702 header: api.HeaderControl, 2703 background: api.BackgroundControl, 2704 theme: api.ThemeControl 2638 color: api.ColorControl, 2639 media: api.MediaControl, 2640 upload: api.UploadControl, 2641 image: api.ImageControl, 2642 cropped_image: api.CroppedImageControl, 2643 header: api.HeaderControl, 2644 background: api.BackgroundControl, 2645 theme: api.ThemeControl 2705 2646 }; 2706 2647 api.panelConstructor = {}; 2707 2648 api.sectionConstructor = { -
src/wp-includes/class-wp-customize-ajax-actions.php
1 <?php 2 /** 3 * Ajax Actions for the Customizer. 4 * 5 * @package WordPress 6 * @subpackage Customize 7 */ 8 9 /** 10 * The custom header image class. 11 * 12 * @since 2.1.0 13 * @package WordPress 14 * @subpackage Administration 15 */ 16 class WP_Customize_Ajax_Actions { 17 public function __construct() { 18 add_action( 'wp_ajax_customize-image-crop', array( $this, 'ajax_image_crop' ) ); 19 } 20 21 /** 22 * Gets attachment uploaded by Media Manager, crops it, then saves it as a 23 * new object. Returns JSON-encoded object details. 24 */ 25 public function ajax_image_crop() { 26 check_ajax_referer( 'image_editor-' . $_POST['id'], 'nonce' ); 27 if ( ! current_user_can( 'customize' ) ) { 28 wp_send_json_error(); 29 } 30 $crop_details = $_POST['cropDetails']; 31 $attachment_id = absint( $_POST['id'] ); 32 $cropped = wp_crop_image( 33 $attachment_id, 34 (int) $crop_details['x1'], 35 (int) $crop_details['y1'], 36 (int) $crop_details['width'], 37 (int) $crop_details['height'], 38 (int) $crop_details['dst_width'], 39 (int) $crop_details['dst_height'] 40 ); 41 if ( ! $cropped || is_wp_error( $cropped ) ) { 42 wp_send_json_error( array( 'message' => __( 'Image could not be processed. Please go back and try again.' ) ) ); 43 } 44 /** This filter is documented in wp-admin/custom-header.php */ 45 $cropped = apply_filters( 'wp_create_file_in_uploads', $cropped, $attachment_id ); // For replication 46 $object = $this->create_attachment_object( $cropped, $attachment_id ); 47 unset( $object['ID'] ); 48 $new_attachment_id = $this->insert_attachment( $object, $cropped ); 49 // $object['attachment_id'] = $new_attachment_id; 50 // $object['width'] = $dimensions['dst_width']; 51 // $object['height'] = $dimensions['dst_height']; 52 wp_send_json_success( wp_prepare_attachment_for_js( $new_attachment_id ) ); // was object, no prepare attachment 53 } 54 55 /** 56 * Create an attachment 'object'. 57 * 58 * @param string $cropped Cropped image URL. 59 * @param int $parent_attachment_id Attachment ID of parent image. 60 * 61 * @return array Attachment object. 62 */ 63 final public function create_attachment_object( $cropped, $parent_attachment_id ) { 64 $parent = get_post( $parent_attachment_id ); 65 $parent_url = $parent->guid; 66 $url = str_replace( basename( $parent_url ), basename( $cropped ), $parent_url ); 67 $size = @getimagesize( $cropped ); 68 $image_type = ( $size ) ? $size['mime'] : 'image/jpeg'; 69 $object = array( 70 'ID' => $parent_attachment_id, 71 'post_title' => basename($cropped), 72 'post_content' => $url, 73 'post_mime_type' => $image_type, 74 'guid' => $url, 75 'context' => 'customize-cropped' 76 ); 77 return $object; 78 } 79 80 /** 81 * Insert an attachment and its metadata. 82 * 83 * @param array $object Attachment object. 84 * @param string $cropped Cropped image URL. 85 * 86 * @return int Attachment ID. 87 */ 88 final public function insert_attachment( $object, $cropped ) { 89 $attachment_id = wp_insert_attachment( $object, $cropped ); 90 $metadata = wp_generate_attachment_metadata( $attachment_id, $cropped ); 91 wp_update_attachment_metadata( $attachment_id, $metadata ); 92 return $attachment_id; 93 } 94 } -
src/wp-includes/class-wp-customize-control.php
1001 1001 } 1002 1002 1003 1003 /** 1004 * Customize HeaderImage Control class.1004 * Customize Cropped Image Control class. 1005 1005 * 1006 * @since 3.4.01006 * @since 4.3.0 1007 1007 * 1008 1008 * @see WP_Customize_Image_Control 1009 1009 */ 1010 class WP_Customize_Header_Image_Control extends WP_Customize_Image_Control { 1011 public $type = 'header'; 1012 public $uploaded_headers; 1013 public $default_headers; 1010 class WP_Customize_Cropped_Image_Control extends WP_Customize_Image_Control { 1011 public $type = 'cropped_image'; 1014 1012 1013 protected $width = 150; 1014 protected $height = 150; 1015 protected $flex_width = false; 1016 protected $flex_height = false; 1017 1015 1018 /** 1019 * Constructor. 1020 * 1021 * @since 4.3.0 1022 * @uses WP_Customize_Image_Control::__construct() 1023 * 1016 1024 * @param WP_Customize_Manager $manager 1017 1025 */ 1018 public function __construct( $manager ) { 1019 parent::__construct( $manager, 'header_image', array( 1020 'label' => __( 'Header Image' ), 1021 'settings' => array( 1022 'default' => 'header_image', 1023 'data' => 'header_image_data', 1024 ), 1025 'section' => 'header_image', 1026 'removed' => 'remove-header', 1027 'get_url' => 'get_header_image', 1028 ) ); 1029 1026 public function __construct( $manager, $id, $args ) { 1027 parent::__construct( $manager, $id, $args ); 1030 1028 } 1031 1029 1032 1030 /** … … 1033 1031 * @access public 1034 1032 */ 1035 1033 public function enqueue() { 1036 wp_enqueue_media();1037 1034 wp_enqueue_script( 'customize-views' ); 1038 1035 1039 $this->prepare_control(); 1036 parent::enqueue(); 1037 } 1040 1038 1041 wp_localize_script( 'customize-views', '_wpCustomizeHeader', array( 1042 'data' => array( 1043 'width' => absint( get_theme_support( 'custom-header', 'width' ) ), 1044 'height' => absint( get_theme_support( 'custom-header', 'height' ) ), 1045 'flex-width' => absint( get_theme_support( 'custom-header', 'flex-width' ) ), 1046 'flex-height' => absint( get_theme_support( 'custom-header', 'flex-height' ) ), 1047 'currentImgSrc' => $this->get_current_image_src(), 1039 /** 1040 * Refresh the parameters passed to the JavaScript via JSON. 1041 * 1042 * @since 4.3.0 1043 * @access public 1044 * @uses WP_Customize_Image_Control::to_json() 1045 * 1046 * @see WP_Customize_Control::to_json() 1047 */ 1048 public function to_json() { 1049 parent::to_json(); 1050 1051 $this->json['width'] = absint( $this->width ); 1052 $this->json['height'] = absint( $this->height ); 1053 $this->json['flex_width'] = absint( $this->flex_width ); 1054 $this->json['flex_height'] = absint( $this->flex_height ); 1055 } 1056 1057 } 1058 1059 /** 1060 * Customize Header Image Control class. 1061 * 1062 * @since 3.4.0 1063 * @since 4.3.0 extends WP_Customize_Cropped_Image_Control 1064 * 1065 * @see WP_Customize_Cropped_Image_Control 1066 */ 1067 class WP_Customize_Header_Image_Control extends WP_Customize_Cropped_Image_Control { 1068 public $type = 'header'; 1069 1070 /** 1071 * @param WP_Customize_Manager $manager 1072 */ 1073 public function __construct( $manager ) { 1074 parent::__construct( $manager, 'header_image', array( 1075 'label' => __( 'Header Image' ), 1076 'current_title' => __( 'Current header' ), 1077 'settings' => array( 1078 'default' => 'header_image', 1079 'data' => 'header_image_data', 1048 1080 ), 1049 'nonces' => array( 1050 'add' => wp_create_nonce( 'header-add' ), 1051 'remove' => wp_create_nonce( 'header-remove' ), 1052 ), 1053 'uploads' => $this->uploaded_headers, 1054 'defaults' => $this->default_headers 1081 'section' => 'header_image', 1082 'removed' => 'remove-header', 1055 1083 ) ); 1056 1084 1057 parent::enqueue(); 1085 $this->width = get_theme_support( 'custom-header', 'width' ); 1086 $this->height = get_theme_support( 'custom-header', 'height' ); 1087 $this->flex_width = get_theme_support( 'custom-header', 'flex-width' ); 1088 $this->flex_height = get_theme_support( 'custom-header', 'flex-height' ); 1089 $this->localized_name = '_wpCustomizeHeader'; 1058 1090 } 1059 1091 1060 1092 /** … … 1063 1095 */ 1064 1096 public function prepare_control() { 1065 1097 global $custom_image_header; 1098 1066 1099 if ( empty( $custom_image_header ) ) { 1067 1100 return; 1068 1101 } … … 1069 1102 1070 1103 // Process default headers and uploaded headers. 1071 1104 $custom_image_header->process_default_headers(); 1072 $this->default_ headers= $custom_image_header->get_default_header_images();1073 $this->uploaded_ headers = $custom_image_header->get_uploaded_header_images();1105 $this->default_images = $custom_image_header->get_default_header_images(); 1106 $this->uploaded_images = $custom_image_header->get_uploaded_header_images(); 1074 1107 } 1075 1108 1076 1109 /** -
src/wp-includes/class-wp-customize-manager.php
112 112 require_once( ABSPATH . WPINC . '/class-wp-customize-control.php' ); 113 113 require_once( ABSPATH . WPINC . '/class-wp-customize-widgets.php' ); 114 114 require_once( ABSPATH . WPINC . '/class-wp-customize-nav-menus.php' ); 115 require_once( ABSPATH . WPINC . '/class-wp-customize-ajax-actions.php' ); 115 116 116 117 $this->widgets = new WP_Customize_Widgets( $this ); 117 118 $this->nav_menus = new WP_Customize_Nav_Menus( $this ); 119 $this->ajax_actions = new WP_Customize_Ajax_Actions(); 118 120 119 121 add_filter( 'wp_die_handler', array( $this, 'wp_die_handler' ) ); 120 122 … … 1278 1280 $this->register_control_type( 'WP_Customize_Upload_Control' ); 1279 1281 $this->register_control_type( 'WP_Customize_Image_Control' ); 1280 1282 $this->register_control_type( 'WP_Customize_Background_Image_Control' ); 1283 $this->register_control_type( 'WP_Customize_Cropped_Image_Control' ); 1281 1284 $this->register_control_type( 'WP_Customize_Theme_Control' ); 1282 1285 1283 1286 /* Themes */ … … 1324 1327 ) ) ); 1325 1328 } 1326 1329 1327 /* Site Title & Tagline*/1330 /* Site Identity */ 1328 1331 1329 1332 $this->add_section( 'title_tagline', array( 1330 'title' => __( 'Site Title & Tagline' ),1333 'title' => __( 'Site Identity' ), 1331 1334 'priority' => 20, 1332 1335 ) ); 1333 1336 … … 1353 1356 'section' => 'title_tagline', 1354 1357 ) ); 1355 1358 1359 $this->add_setting( 'site_icon', array( 1360 'type' => 'option', 1361 'capability' => 'manage_options', 1362 ) ); 1363 1364 $this->add_control( new WP_Customize_Cropped_Image_Control( $this, 'site_icon', array( 1365 'label' => __( 'Site Icon' ), 1366 'description' => __( 'The site icon is used as the browser and device icon for your site. Your theme may also display the site icon. Icons must be square, and at least 512px wide and tall.' ), 1367 'section' => 'title_tagline', 1368 'priority' => 60, 1369 ) ) ); 1370 1356 1371 /* Colors */ 1357 1372 1358 1373 $this->add_section( 'colors', array( … … 1375 1390 'label' => __( 'Display Header Text' ), 1376 1391 'section' => 'title_tagline', 1377 1392 'type' => 'checkbox', 1393 'priority' => 40, 1378 1394 ) ); 1379 1395 1380 1396 $this->add_control( new WP_Customize_Color_Control( $this, 'header_textcolor', array( -
src/wp-includes/js/customize-views.js
3 3 if ( ! wp || ! wp.customize ) { return; } 4 4 var api = wp.customize; 5 5 6 /** 7 * Use a custom ajax action for cropped image controls 8 */ 9 wp.media.controller.customizeImageCropper = wp.media.controller.Cropper.extend( { 10 doCrop: function( attachment ) { 11 var cropDetails = attachment.get( 'cropDetails' ); 12 cropDetails.dst_height = this.collection.models[0].attributes.suggestedHeight; 13 cropDetails.dst_width = this.collection.models[0].attributes.suggestedWidth; 14 return wp.ajax.post( 'customize-image-crop', { 15 nonce: attachment.get( 'nonces' ).edit, 16 id: attachment.get( 'id' ), 17 cropDetails: cropDetails 18 } ); 19 } 20 } ); 6 21 7 22 /** 8 23 * wp.customize.HeaderTool.CurrentView … … 16 31 * @augments wp.Backbone.View 17 32 */ 18 33 api.HeaderTool.CurrentView = wp.Backbone.View.extend({ 19 template: wp.template(' header-current'),34 template: wp.template('cropped-current'), 20 35 21 36 initialize: function() { 22 37 this.listenTo(this.model, 'change', this.render); … … 86 101 * Represents a choosable header image, be it user-uploaded, 87 102 * theme-suggested or a special Randomize choice. 88 103 * 89 * Takes a wp.customize. HeaderTool.ImageModel.104 * Takes a wp.customize.CropTool.ImageModel. 90 105 * 91 106 * Manually changes model wp.customize.HeaderTool.currentHeader via the 92 107 * `select` method.