Make WordPress Core

Ticket #16434: 16434.customize.diff

File 16434.customize.diff, 24.1 KB (added by celloexpressions, 10 years ago)

First-pass at site icons and a cropped-image control in the Customizer.

  • src/wp-admin/css/customize-controls.css

     
    758758.customize-control-upload .current,
    759759.customize-control-image .current,
    760760.customize-control-background .current,
     761.customize-control-cropped_image .current,
     762.customize-control-site_icon .current,
    761763.customize-control-header .current {
    762764        margin-bottom: 8px;
    763765}
     
    793795.customize-control-background .remove-button,
    794796.customize-control-background .default-button,
    795797.customize-control-background .upload-button,
     798.customize-control-cropped_image .remove-button,
     799.customize-control-cropped_image .default-button,
     800.customize-control-cropped_image .upload-button,
     801.customize-control-site_icon .remove-button,
     802.customize-control-site_icon .default-button,
     803.customize-control-site_icon .upload-button,
    796804.customize-control-header button.new,
    797805.customize-control-header button.remove {
    798806        white-space: normal;
     
    804812.customize-control-upload .current .container,
    805813.customize-control-image .current .container,
    806814.customize-control-background .current .container,
     815.customize-control-cropped_image .current .container,
     816.customize-control-site_icon .current .container,
    807817.customize-control-header .current .container {
    808818        overflow: hidden;
    809819        -webkit-border-radius: 2px;
     
    815825.customize-control-media .current .container,
    816826.customize-control-upload .current .container,
    817827.customize-control-background .current .container,
     828.customize-control-cropped_image .current .container,
     829.customize-control-site_icon .current .container,
    818830.customize-control-image .current .container {
    819831        min-height: 40px;
    820832}
     
    823835.customize-control-upload .placeholder,
    824836.customize-control-image .placeholder,
    825837.customize-control-background .placeholder,
     838.customize-control-cropped_image .placeholder,
     839.customize-control-site_icon .placeholder,
    826840.customize-control-header .placeholder {
    827841        width: 100%;
    828842        position: relative;
     
    834848.customize-control-upload .inner,
    835849.customize-control-image .inner,
    836850.customize-control-background .inner,
     851.customize-control-cropped_image .inner,
     852.customize-control-site_icon .inner,
    837853.customize-control-header .inner {
    838854        display: none;
    839855        position: absolute;
     
    847863.customize-control-media .inner,
    848864.customize-control-upload .inner,
    849865.customize-control-background .inner,
     866.customize-control-cropped_image .inner,
     867.customize-control-site_icon .inner,
    850868.customize-control-image .inner {
    851869        display: block;
    852870        min-height: 40px;
     
    856874.customize-control-upload .inner,
    857875.customize-control-image .inner,
    858876.customize-control-background .inner,
     877.customize-control-cropped_image .inner,
     878.customize-control-site_icon .inner,
    859879.customize-control-header .inner,
    860880.customize-control-header .inner .dashicons {
    861881        line-height: 20px;
     
    959979.customize-control-upload .actions,
    960980.customize-control-image .actions,
    961981.customize-control-background .actions,
     982.customize-control-cropped_image .actions,
     983.customize-control-site_icon .actions,
    962984.customize-control-header .actions {
    963985        margin-bottom: 32px;
    964986}
     
    977999.customize-control-upload img,
    9781000.customize-control-image img,
    9791001.customize-control-background img,
     1002.customize-control-cropped_image img,
     1003.customize-control-site_icon img,
    9801004.customize-control-header img {
    9811005        width: 100%;
    9821006        -webkit-border-radius: 2px;
     
    9911015.customize-control-image .default-button,
    9921016.customize-control-background .remove-button,
    9931017.customize-control-background .default-button,
     1018.customize-control-cropped_image .remove-button,
     1019.customize-control-cropped_image .default-button,
     1020.customize-control-site_icon .remove-button,
     1021.customize-control-site_icon .default-button,
    9941022.customize-control-header .remove {
    9951023        float: left;
    9961024        margin-right: 3px;
     
    10001028.customize-control-upload .upload-button,
    10011029.customize-control-image .upload-button,
    10021030.customize-control-background .upload-button,
     1031.customize-control-cropped_image .upload-button,
     1032.customize-control-site_icon .upload-button,
    10031033.customize-control-header .new {
    10041034        float: right;
    10051035}
  • src/wp-admin/includes/class-wp-site-icon.php

     
    6565
    6666                add_action( 'delete_attachment', array( $this, 'delete_attachment_data' ), 10, 1 );
    6767                add_filter( 'get_post_metadata', array( $this, 'get_post_metadata' ), 10, 4 );
     68
     69                // Integrate with Ajax-cropped site icons from the Customizer.
     70                add_action( 'customize_pre_insert_attachment_site_icon', array( $this, 'customize_pre_insert_attachment_filters' ) );
     71                add_action( 'customize_post_insert_attachment_site_icon', array( $this, 'customize_post_insert_attachment_filters' ) );
    6872        }
    6973
    7074        /**
     
    619623
    620624                return array( $attachment_id, $url, $image_size );
    621625        }
     626
     627        /**
     628         * Add intermediate image sizes when inserting the attachment in the Customizer.
     629         *
     630         * @since 4.3.0
     631         */
     632        private function customize_pre_insert_attachment_filters() {
     633                add_filter( 'intermediate_image_sizes', array( $this, 'intermediate_image_sizes' ) );
     634        }
     635
     636        /**
     637         * Cleanup intermediate sizes.
     638         *
     639         * @since 4.3.0
     640         */
     641        private function customize_post_insert_attachment_filters() {
     642                remove_filter( 'intermediate_image_sizes', array( $this, 'intermediate_image_sizes' ) );
     643        }
    622644}
    623645
    624646/**
  • src/wp-admin/js/customize-controls.js

     
    18361836        });
    18371837
    18381838        /**
     1839         * A control for selecting and cropping an image.
     1840         *
    18391841         * @class
     1842         * @augments wp.customize.MediaControl
    18401843         * @augments wp.customize.Control
    18411844         * @augments wp.customize.Class
    18421845         */
     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                        }
     1854
     1855                        if ( this.frame ) {
     1856                                this.frame.setState( 'library' );
     1857                        }
     1858
     1859                        api.MediaControl.prototype.openFrame.call( this, event );
     1860                },
     1861
     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;
     1867
     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                                ]
     1888                        });
     1889
     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                },
     1894
     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' );
     1901                },
     1902
     1903                /**
     1904                 * After the image has been cropped, apply the cropped image data to the setting.
     1905                 *
     1906                 * @param {object} croppedImage Cropped attachment data.
     1907                 */
     1908                onCropped: function( croppedImage ) {
     1909                        this.setImageFromAttachment( croppedImage );
     1910                },
     1911
     1912                /**
     1913                 * Returns a set of options, computed from the attached image data and
     1914                 * control-specific data, to be fed to the imgAreaSelect plugin in
     1915                 * wp.media.view.Cropper.
     1916                 *
     1917                 * @param {wp.media.model.Attachment} attachment
     1918                 * @param {wp.media.controller.Cropper} controller
     1919                 * @returns {Object} Options
     1920                 */
     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;
     1929
     1930                        realWidth = attachment.get( 'width' );
     1931                        realHeight = attachment.get( 'height' );
     1932
     1933                        controller.set( 'canSkipCrop', ! control.mustBeCropped( flexWidth, flexHeight, xInit, yInit, realWidth, realHeight ) );
     1934
     1935                        ratio = xInit / yInit;
     1936                        xImg = realWidth;
     1937                        yImg = realHeight;
     1938
     1939                        if ( xImg / yImg > ratio ) {
     1940                                yInit = yImg;
     1941                                xInit = yInit * ratio;
     1942                        } else {
     1943                                xInit = xImg;
     1944                                yInit = xInit / ratio;
     1945                        }
     1946
     1947                        imgSelectOptions = {
     1948                                handles: true,
     1949                                keys: true,
     1950                                instance: true,
     1951                                persistent: true,
     1952                                imageWidth: realWidth,
     1953                                imageHeight: realHeight,
     1954                                x1: 0,
     1955                                y1: 0,
     1956                                x2: xInit,
     1957                                y2: yInit
     1958                        };
     1959
     1960                        if ( flexHeight === false && flexWidth === false ) {
     1961                                imgSelectOptions.aspectRatio = xInit + ':' + yInit;
     1962                        }
     1963                        if ( flexHeight === false ) {
     1964                                imgSelectOptions.maxHeight = yInit;
     1965                        }
     1966                        if ( flexWidth === false ) {
     1967                                imgSelectOptions.maxWidth = xInit;
     1968                        }
     1969
     1970                        return imgSelectOptions;
     1971                },
     1972
     1973                /**
     1974                 * Return whether the image must be cropped, based on required dimensions.
     1975                 */
     1976                mustBeCropped: function( flexW, flexH, dstW, dstH, imgW, imgH ) {
     1977                        if ( flexW === true && flexH === true ) {
     1978                                return false;
     1979                        }
     1980
     1981                        if ( flexW === true && dstH === imgH ) {
     1982                                return false;
     1983                        }
     1984
     1985                        if ( flexH === true && dstW === imgW ) {
     1986                                return false;
     1987                        }
     1988
     1989                        if ( dstW === imgW && dstH === imgH ) {
     1990                                return false;
     1991                        }
     1992
     1993                        if ( imgW <= dstW ) {
     1994                                return false;
     1995                        }
     1996
     1997                        return true;
     1998                },
     1999
     2000                /**
     2001                 * If cropping was skipped, apply the image data directly to the setting.
     2002                 */
     2003                onSkippedCrop: function() {
     2004                        var attachment = this.frame.state().get( 'selection' ).first().toJSON();
     2005                        this.setImageFromAttachment( attachment );
     2006                },
     2007
     2008                /**
     2009                 * Updates the setting and re-renders the control UI.
     2010                 *
     2011                 * @param {object} attachment
     2012                 */
     2013                setImageFromAttachment: function( attachment ) {
     2014                        this.params.attachment = attachment;
     2015
     2016                        // Set the Customizer setting; the callback takes care of rendering.
     2017                        this.setting( attachment.id );
     2018                },
     2019
     2020        });
     2021
     2022        /**
     2023         * A control for selecting and cropping an image.
     2024         *
     2025         * @class
     2026         * @augments wp.customize.CroppedImageControl
     2027         * @augments wp.customize.MediaControl
     2028         * @augments wp.customize.Control
     2029         * @augments wp.customize.Class
     2030         */
     2031        api.SiteIconControl = api.CroppedImageControl.extend({
     2032                /**
     2033                 * Updates the setting and re-renders the control UI.
     2034                 *
     2035                 * @param {object} attachment
     2036                 */
     2037                setImageFromAttachment: function( attachment ) {
     2038                        this.params.attachment = attachment;
     2039
     2040                        // Set the Customizer setting; the callback takes care of rendering.
     2041                        this.setting( attachment.id );
     2042
     2043                        // Update the icon in-browser.
     2044                        $( '#wp-site-icon-favicon' ).attr( 'href', attachment.sizes.thumbnail.url );
     2045                },
     2046
     2047                /**
     2048                 * Called when the "Remove" link is clicked. Empties the setting.
     2049                 *
     2050                 * @param {object} event jQuery Event object
     2051                 */
     2052                removeFile: function( event ) {
     2053                        if ( api.utils.isKeydownButNotEnterEvent( event ) ) {
     2054                                return;
     2055                        }
     2056                        event.preventDefault();
     2057
     2058                        this.params.attachment = {};
     2059                        this.setting( '' );
     2060                        this.renderContent(); // Not bound to setting change when emptying.
     2061                        $( '#wp-site-icon-favicon' ).attr( 'href', '' );
     2062                }
     2063        });
     2064
     2065        /**
     2066         * @class
     2067         * @augments wp.customize.Control
     2068         * @augments wp.customize.Class
     2069         */
    18432070        api.HeaderControl = api.Control.extend({
    18442071                ready: function() {
    18452072                        this.btnRemove = $('#customize-control-header_image .actions .remove');
     
    26952922        });
    26962923
    26972924        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
     2925                color:         api.ColorControl,
     2926                media:         api.MediaControl,
     2927                upload:        api.UploadControl,
     2928                image:         api.ImageControl,
     2929                cropped_image: api.CroppedImageControl,
     2930                site_icon:     api.SiteIconControl,
     2931                header:        api.HeaderControl,
     2932                background:    api.BackgroundControl,
     2933                theme:         api.ThemeControl
    27052934        };
    27062935        api.panelConstructor = {};
    27072936        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 * Ajax actions for Customizer controls.
     11 *
     12 * @since 4.3.0
     13 * @package WordPress
     14 * @subpackage Customize
     15 */
     16class 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-' . absint( $_POST['id'] ), 'nonce' );
     27                if ( ! current_user_can( 'customize' ) ) {
     28                        wp_send_json_error();
     29                }
     30                $crop_details = $_POST['cropDetails'];
     31                $context = $_POST['context'];
     32                $attachment_id = absint( $_POST['id'] );
     33                $cropped = wp_crop_image(
     34                        $attachment_id,
     35                        (int) $crop_details['x1'],
     36                        (int) $crop_details['y1'],
     37                        (int) $crop_details['width'],
     38                        (int) $crop_details['height'],
     39                        (int) $crop_details['dst_width'],
     40                        (int) $crop_details['dst_height']
     41                );
     42
     43                if ( ! $cropped || is_wp_error( $cropped ) ) {
     44                        wp_send_json_error( array( 'message' => __( 'Image could not be processed. Please go back and try again.' ) ) );
     45                }
     46
     47                /** This filter is documented in wp-admin/custom-header.php */
     48                $cropped = apply_filters( 'wp_create_file_in_uploads', $cropped, $attachment_id ); // For replication
     49                $object = $this->create_attachment_object( $cropped, $attachment_id, $context );
     50                unset( $object['ID'] );
     51
     52                require_once( ABSPATH . '/wp-admin/includes/class-wp-site-icon.php' );
     53                $site_icon = new WP_Site_Icon();
     54
     55                // Update the attachment.
     56                /**
     57                 * Action prior to inserting a cropped image from the Customizer.
     58                 *
     59                 * $context is the context argument of WP_Customize_Cropped_Image_Control.
     60                 *
     61                 * @since 4.3.0
     62                 */
     63                do_action( 'customize_pre_insert_attachment_' . $context );
     64                $attachment_id = $this->insert_attachment( $object, $cropped, $context );
     65                /**
     66                 * Action prior to inserting a cropped image from the Customizer.
     67                 *
     68                 * $context is the context argument of WP_Customize_Cropped_Image_Control.
     69                 *
     70                 * @since 4.3.0
     71                 */
     72                do_action( 'customize_post_insert_attachment_' . $context );
     73
     74                wp_send_json_success( wp_prepare_attachment_for_js( $attachment_id ) );
     75        }
     76
     77        /**
     78         * Create an attachment 'object'.
     79         *
     80         * @param string $cropped              Cropped image URL.
     81         * @param int    $parent_attachment_id Attachment ID of parent image.
     82         * @param string $context              Context of the attachment object.
     83         *
     84         * @return array Attachment object.
     85         */
     86        final public function create_attachment_object( $cropped, $parent_attachment_id, $context ) {
     87                $parent = get_post( $parent_attachment_id );
     88                $parent_url = $parent->guid;
     89                $url = str_replace( basename( $parent_url ), basename( $cropped ), $parent_url );
     90                $size = @getimagesize( $cropped );
     91                $image_type = ( $size ) ? $size['mime'] : 'image/jpeg';
     92                $object = array(
     93                        'ID' => $parent_attachment_id,
     94                        'post_title' => basename($cropped),
     95                        'post_content' => $url,
     96                        'post_mime_type' => $image_type,
     97                        'guid' => $url,
     98                        'context' => $context,
     99                );
     100                return $object;
     101        }
     102
     103        /**
     104         * Insert an attachment and its metadata.
     105         *
     106         * @param array  $object  Attachment object.
     107         * @param string $cropped Cropped image URL.
     108         *
     109         * @return int Attachment ID.
     110         */
     111        final public function insert_attachment( $object, $cropped, $context ) {
     112                $attachment_id = wp_insert_attachment( $object, $cropped );
     113                $metadata = wp_generate_attachment_metadata( $attachment_id, $cropped );
     114
     115                /**
     116                 * Filter the attachment metadata for an image cropped in the Customizer.
     117                 *
     118                 * @since 4.3.0
     119                 *
     120                 * @see wp_generate_attachment_metadata()
     121                 *
     122                 * @param array $metadata Attachment metadata.
     123                 */
     124                $metadata = apply_filters( $context . '_customize_attachment_metadata', $metadata );
     125                wp_update_attachment_metadata( $attachment_id, $metadata );
     126
     127                return $attachment_id;
     128        }
     129}
  • src/wp-includes/class-wp-customize-control.php

     
    10011001}
    10021002
    10031003/**
     1004 * Customize Cropped Image Control class.
     1005 *
     1006 * @since 4.3.0
     1007 *
     1008 * @see WP_Customize_Image_Control
     1009 */
     1010class WP_Customize_Cropped_Image_Control extends WP_Customize_Image_Control {
     1011        public $type = 'cropped_image';
     1012
     1013        public $width  = 150;
     1014        public $height = 150;
     1015        public $flex_width  = false;
     1016        public $flex_height = false;
     1017        public $context = 'customize_crop_image';
     1018
     1019        /**
     1020         * Constructor.
     1021         *
     1022         * @since 4.3.0
     1023         * @uses WP_Customize_Image_Control::__construct()
     1024         *
     1025         * @param WP_Customize_Manager $manager
     1026         */
     1027        public function __construct( $manager, $id, $args ) {
     1028                parent::__construct( $manager, $id, $args );
     1029        }
     1030
     1031        /**
     1032         * @access public
     1033         */
     1034        public function enqueue() {
     1035                wp_enqueue_script( 'customize-views' );
     1036
     1037                parent::enqueue();
     1038        }
     1039
     1040        /**
     1041         * Refresh the parameters passed to the JavaScript via JSON.
     1042         *
     1043         * @since 4.3.0
     1044         * @access public
     1045         * @uses WP_Customize_Image_Control::to_json()
     1046         *
     1047         * @see WP_Customize_Control::to_json()
     1048         */
     1049        public function to_json() {
     1050                parent::to_json();
     1051
     1052                $this->json['width']       = absint( $this->width );
     1053                $this->json['height']      = absint( $this->height );
     1054                $this->json['flex_width']  = absint( $this->flex_width );
     1055                $this->json['flex_height'] = absint( $this->flex_height );
     1056                $this->json['context']     = $this->context;
     1057        }
     1058
     1059}
     1060
     1061/**
     1062 * Customize Site Icon control class.
     1063 *
     1064 * Used only for custom functionality in JavaScript.
     1065 *
     1066 * @since 4.3.0
     1067 *
     1068 * @see WP_Customize_Cropped_Image_Control
     1069 */
     1070class WP_Customize_Site_Icon_Control extends WP_Customize_Cropped_Image_Control {
     1071        public $type = 'site_icon';
     1072}
     1073
     1074/**
    10041075 * Customize Header Image Control class.
    10051076 *
    10061077 * @since 3.4.0
  • src/wp-includes/class-wp-customize-manager.php

     
    112112                require_once( ABSPATH . WPINC . '/class-wp-customize-control.php' );
    113113                require_once( ABSPATH . WPINC . '/class-wp-customize-widgets.php' );
    114114                require_once( ABSPATH . WPINC . '/class-wp-customize-nav-menus.php' );
     115                require_once( ABSPATH . WPINC . '/class-wp-customize-ajax-actions.php' );
    115116
    116117                $this->widgets = new WP_Customize_Widgets( $this );
    117118                $this->nav_menus = new WP_Customize_Nav_Menus( $this );
     119                $this->ajax_actions = new WP_Customize_Ajax_Actions();
    118120
    119121                add_filter( 'wp_die_handler', array( $this, 'wp_die_handler' ) );
    120122
     
    12781280                $this->register_control_type( 'WP_Customize_Upload_Control' );
    12791281                $this->register_control_type( 'WP_Customize_Image_Control' );
    12801282                $this->register_control_type( 'WP_Customize_Background_Image_Control' );
     1283                $this->register_control_type( 'WP_Customize_Cropped_Image_Control' );
     1284                $this->register_control_type( 'WP_Customize_Site_Icon_Control' );
    12811285                $this->register_control_type( 'WP_Customize_Theme_Control' );
    12821286
    12831287                /* Themes */
     
    13241328                        ) ) );
    13251329                }
    13261330
    1327                 /* Site Title & Tagline */
     1331                /* Site Identity */
    13281332
    13291333                $this->add_section( 'title_tagline', array(
    1330                         'title'    => __( 'Site Title & Tagline' ),
     1334                        'title'    => __( 'Site Identity' ),
    13311335                        'priority' => 20,
    13321336                ) );
    13331337
     
    13531357                        'section'    => 'title_tagline',
    13541358                ) );
    13551359
     1360                $icon = wp_get_attachment_image_src( absint( get_option( 'site_icon', 0 ) ), 'full' )[0];
     1361                $this->add_setting( 'site_icon', array(
     1362                        'default'    => ( $icon ) ? $icon[0] : '',
     1363                        'type'       => 'option',
     1364                        'capability' => 'manage_options',
     1365                        'transport'  => 'postMessage', // Previewed with JS in the Customizer controls window.
     1366                ) );
     1367
     1368                $this->add_control( new WP_Customize_Site_Icon_Control( $this, 'site_icon', array(
     1369                        'label'       => __( 'Site Icon' ),
     1370                        '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.' ),
     1371                        'section'     => 'title_tagline',
     1372                        'priority'    => 60,
     1373                        'context'     => 'site-icon',
     1374                        'height'      => 512,
     1375                        'width'       => 512,
     1376                ) ) );
     1377
    13561378                /* Colors */
    13571379
    13581380                $this->add_section( 'colors', array(
     
    13751397                        'label'    => __( 'Display Header Text' ),
    13761398                        'section'  => 'title_tagline',
    13771399                        'type'     => 'checkbox',
     1400                        'priority' => 40,
    13781401                ) );
    13791402
    13801403                $this->add_control( new WP_Customize_Color_Control( $this, 'header_textcolor', array(
  • src/wp-includes/default-filters.php

     
    224224add_action( 'wp_head',             'rel_canonical'                          );
    225225add_action( 'wp_head',             'wp_shortlink_wp_head',            10, 0 );
    226226add_action( 'wp_head',             'wp_site_icon',                    99    );
     227add_action( 'customize_controls_print_styles', 'wp_site_icon',        99    );
    227228add_action( 'wp_footer',           'wp_print_footer_scripts',         20    );
    228229add_action( 'template_redirect',   'wp_shortlink_header',             11, 0 );
    229230add_action( 'wp_print_footer_scripts', '_wp_footer_scripts'                 );
  • src/wp-includes/general-template.php

     
    24502450        }
    24512451
    24522452        $meta_tags = array(
    2453                 sprintf( '<link rel="icon" href="%s" sizes="32x32" />', esc_url( get_site_icon_url( null, 32 ) ) ),
     2453                sprintf( '<link rel="icon" href="%s" sizes="32x32" id="wp-site-icon-favicon" />', esc_url( get_site_icon_url( null, 32 ) ) ),
    24542454                sprintf( '<link rel="apple-touch-icon-precomposed" href="%s">', esc_url( get_site_icon_url( null, 180 ) ) ),
    24552455                sprintf( '<meta name="msapplication-TileImage" content="%s">', esc_url( get_site_icon_url( null, 270 ) ) ),
    24562456        );
  • src/wp-includes/js/customize-views.js

     
    33        if ( ! wp || ! wp.customize ) { return; }
    44        var api = wp.customize;
    55
     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                            control = this.get( 'control' );
     13                        cropDetails.dst_height = control.params.height;
     14                        cropDetails.dst_width = control.params.width;
     15                        return wp.ajax.post( 'customize-image-crop', {
     16                                wp_customize: 'on',
     17                                nonce: attachment.get( 'nonces' ).edit,
     18                                id: attachment.get( 'id' ),
     19                                context: control.params.context,
     20                                cropDetails: cropDetails
     21                        } );
     22                }
     23        } );
    624
    725        /**
    826         * wp.customize.HeaderTool.CurrentView