Make WordPress Core

Changeset 39209


Ignore:
Timestamp:
11/13/2016 02:42:04 AM (8 years ago)
Author:
westonruter
Message:

Customize: Improve extensibility of Custom CSS.

  • Add customize_value_custom_css filter to WP_Customize_Custom_CSS::value() method.
  • Introduce customize_update_custom_css_post_content_args filter in WP_Customize_Custom_CSS::update() method.
  • Make clear that wp_get_custom_css() and wp_get_custom_css filter are specifically for obtaining the value to render/display. Eliminate use of wp_get_custom_css() when getting the setting value. Use the underlying post_value directly when is_previewed.
  • Move anonymous functions handing JS previewing for custom_logo, custom_css, and background into named functions on the wp.customize.settingPreviewHandlers to allow plugins to override/extend preview logic.
  • Update _custom_background_cb to always print a style tag wen in the customizer preview, and update background preview logic to replace existing style element instead of appending a new style to the head so that background changes don't unexpectedly override any Custom CSS in the preview's stylesheet cascade.

Props westonruter, georgestephanis.
See #22058.
Fixes #38672.

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/customize/class-wp-customize-custom-css-setting.php

    r39185 r39209  
    101101
    102102    /**
    103      * Filter wp_get_custom_css for applying customized value to return value.
     103     * Filter `wp_get_custom_css` for applying the customized value.
     104     *
     105     * This is used in the preview when `wp_get_custom_css()` is called for rendering the styles.
    104106     *
    105107     * @since 4.7.0
    106108     * @access private
     109     * @see wp_get_custom_css()
    107110     *
    108111     * @param string $css        Original CSS.
     
    121124
    122125    /**
    123      * Fetch the value of the setting.
    124      *
    125      * @since 4.7.0
    126      * @access public
     126     * Fetch the value of the setting. Will return the previewed value when `preview()` is called.
     127     *
     128     * @since 4.7.0
     129     * @access public
     130     * @see WP_Customize_Setting::value()
    127131     *
    128132     * @return string
    129133     */
    130134    public function value() {
    131         $value = wp_get_custom_css( $this->stylesheet );
     135        $id_base = $this->id_data['base'];
     136        if ( $this->is_previewed && null !== $this->post_value( null ) ) {
     137            return $this->post_value();
     138        }
     139        $value = '';
     140        $post = wp_get_custom_css_post( $this->stylesheet );
     141        if ( $post ) {
     142            $value = $post->post_content;
     143        }
    132144        if ( empty( $value ) ) {
    133145            $value = $this->default;
    134146        }
     147
     148        /** This filter is documented in wp-includes/class-wp-customize-setting.php */
     149        $value = apply_filters( "customize_value_{$id_base}", $value, $this );
     150
    135151        return $value;
    136152    }
     
    227243     */
    228244    public function update( $css ) {
     245        $setting = $this;
     246
     247        if ( empty( $css ) ) {
     248            $css = '';
     249        }
    229250
    230251        $args = array(
    231             'post_content' => $css ? $css : '',
    232             'post_title' => $this->stylesheet,
    233             'post_name' => sanitize_title( $this->stylesheet ),
    234             'post_type' => 'custom_css',
    235             'post_status' => 'publish',
     252            'post_content' => $css,
     253            'post_content_filtered' => '',
     254        );
     255
     256        /**
     257         * Filters the `post_content` and `post_content_filtered` args for a `custom_css` post being updated.
     258         *
     259         * This filter can be used by plugin that offer CSS pre-processors, to store the original
     260         * pre-processed CSS in `post_content_filtered` and then store processed CSS in `post_content`.
     261         * When used in this way, the `post_content_filtered` should be supplied as the setting value
     262         * instead of `post_content` via a the `customize_value_custom_css` filter, for example:
     263         *
     264         * <code>
     265         * add_filter( 'customize_value_custom_css', function( $value, $setting ) {
     266         *     $post = wp_get_custom_css_post( $setting->stylesheet );
     267         *     if ( $post && ! empty( $post->post_content_filtered ) ) {
     268         *         $css = $post->post_content_filtered;
     269         *     }
     270         *     return $css;
     271         * }, 10, 2 );
     272         * </code>
     273         *
     274         * @since 4.7.0
     275         * @param array  $args {
     276         *     Content post args (unslashed) for `wp_update_post()`/`wp_insert_post()`.
     277         *
     278         *     @type string $post_content          CSS.
     279         *     @type string $post_content_filtered Pre-processed CSS. Normally empty string.
     280         * }
     281         * @param string                          $css     Original CSS being updated.
     282         * @param WP_Customize_Custom_CSS_Setting $setting Custom CSS Setting.
     283         */
     284        $args = apply_filters( 'customize_update_custom_css_post_content_args', $args, $css, $setting );
     285        $args = wp_array_slice_assoc( $args, array( 'post_content', 'post_content_filtered' ) );
     286
     287        $args = array_merge(
     288            $args,
     289            array(
     290                'post_title' => $this->stylesheet,
     291                'post_name' => sanitize_title( $this->stylesheet ),
     292                'post_type' => 'custom_css',
     293                'post_status' => 'publish',
     294            )
    236295        );
    237296
  • trunk/src/wp-includes/js/customize-preview.js

    r39112 r39209  
    595595    } )();
    596596
     597    api.settingPreviewHandlers = {
     598
     599        /**
     600         * Preview changes to custom logo.
     601         *
     602         * @param {number} attachmentId Attachment ID for custom logo.
     603         * @returns {void}
     604         */
     605        custom_logo: function( attachmentId ) {
     606            $( 'body' ).toggleClass( 'wp-custom-logo', !! attachmentId );
     607        },
     608
     609        /**
     610         * Preview changes to custom css.
     611         *
     612         * @param {string} value Custom CSS..
     613         * @returns {void}
     614         */
     615        custom_css: function( value ) {
     616            $( '#wp-custom-css' ).text( value );
     617        },
     618
     619        /**
     620         * Preview changes to any of the background settings.
     621         *
     622         * @returns {void}
     623         */
     624        background: function() {
     625            var css = '', settings = {};
     626
     627            _.each( ['color', 'image', 'preset', 'position_x', 'position_y', 'size', 'repeat', 'attachment'], function( prop ) {
     628                settings[ prop ] = api( 'background_' + prop );
     629            } );
     630
     631            /*
     632             * The body will support custom backgrounds if either the color or image are set.
     633             *
     634             * See get_body_class() in /wp-includes/post-template.php
     635             */
     636            $( document.body ).toggleClass( 'custom-background', !! ( settings.color() || settings.image() ) );
     637
     638            if ( settings.color() ) {
     639                css += 'background-color: ' + settings.color() + ';';
     640            }
     641
     642            if ( settings.image() ) {
     643                css += 'background-image: url("' + settings.image() + '");';
     644                css += 'background-size: ' + settings.size() + ';';
     645                css += 'background-position: ' + settings.position_x() + ' ' + settings.position_y() + ';';
     646                css += 'background-repeat: ' + settings.repeat() + ';';
     647                css += 'background-attachment: ' + settings.attachment() + ';';
     648            }
     649
     650            $( '#custom-background-css' ).text( 'body.custom-background { ' + css + ' }' );
     651        }
     652    };
     653
    597654    $( function() {
    598655        var bg, setValue;
     
    760817        } );
    761818
    762         api.when.apply( api, bg ).done( function( color, image, preset, positionX, positionY, size, repeat, attachment ) {
    763             var body = $(document.body),
    764                 head = $('head'),
    765                 style = $('#custom-background-css'),
    766                 update;
    767 
    768             update = function() {
    769                 var css = '';
    770 
    771                 // The body will support custom backgrounds if either
    772                 // the color or image are set.
    773                 //
    774                 // See get_body_class() in /wp-includes/post-template.php
    775                 body.toggleClass( 'custom-background', !! ( color() || image() ) );
    776 
    777                 if ( color() )
    778                     css += 'background-color: ' + color() + ';';
    779 
    780                 if ( image() ) {
    781                     css += 'background-image: url("' + image() + '");';
    782                     css += 'background-size: ' + size() + ';';
    783                     css += 'background-position: ' + positionX() + ' ' + positionY() + ';';
    784                     css += 'background-repeat: ' + repeat() + ';';
    785                     css += 'background-attachment: ' + attachment() + ';';
    786                 }
    787 
    788                 // Refresh the stylesheet by removing and recreating it.
    789                 style.remove();
    790                 style = $('<style type="text/css" id="custom-background-css">body.custom-background { ' + css + ' }</style>').appendTo( head );
    791             };
    792 
     819        api.when.apply( api, bg ).done( function() {
    793820            $.each( arguments, function() {
    794                 this.bind( update );
     821                this.bind( api.settingPreviewHandlers.background );
    795822            });
    796823        });
     
    803830         * @since 4.5.0
    804831         */
    805         api( 'custom_logo', function( setting ) {
    806             $( 'body' ).toggleClass( 'wp-custom-logo', !! setting.get() );
    807             setting.bind( function( attachmentId ) {
    808                 $( 'body' ).toggleClass( 'wp-custom-logo', !! attachmentId );
    809             });
    810         });
    811 
    812         api( 'custom_css[' + api.settings.theme.stylesheet + ']', function( value ) {
    813             value.bind( function( to ) {
    814                 $( '#wp-custom-css' ).text( to );
    815             } );
     832        api( 'custom_logo', function ( setting ) {
     833            api.settingPreviewHandlers.custom_logo.call( setting, setting.get() );
     834            setting.bind( api.settingPreviewHandlers.custom_logo );
     835        } );
     836
     837        api( 'custom_css[' + api.settings.theme.stylesheet + ']', function( setting ) {
     838            setting.bind( api.settingPreviewHandlers.custom_css );
    816839        } );
    817840
  • trunk/src/wp-includes/theme.php

    r39185 r39209  
    15011501    }
    15021502
    1503     if ( ! $background && ! $color )
     1503    if ( ! $background && ! $color ) {
     1504        if ( is_customize_preview() ) {
     1505            echo '<style type="text/css" id="custom-background-css"></style>';
     1506        }
    15041507        return;
     1508    }
    15051509
    15061510    $style = $color ? "background-color: #$color;" : '';
     
    16221626
    16231627/**
    1624  * Fetch the saved Custom CSS content.
     1628 * Fetch the saved Custom CSS content for rendering.
    16251629 *
    16261630 * @since 4.7.0
  • trunk/tests/phpunit/tests/customize/custom-css-setting.php

    r39185 r39209  
    169169
    170170    /**
     171     * Test crud methods on WP_Customize_Custom_CSS_Setting.
     172     *
     173     * @covers WP_Customize_Custom_CSS_Setting::value()
     174     */
     175    function test_value_filter() {
     176        add_filter( 'customize_value_custom_css', array( $this, 'filter_value' ), 10, 2 );
     177        $this->setting->default = '/*default*/';
     178        $this->assertEquals( '/*default*//*filtered*/', $this->setting->value() );
     179
     180        $this->factory()->post->create( array(
     181            'post_title' => $this->setting->stylesheet,
     182            'post_name' => $this->setting->stylesheet,
     183            'post_content' => '/*custom*/',
     184            'post_status' => 'publish',
     185            'post_type' => 'custom_css',
     186        ) );
     187        $this->assertEquals( '/*custom*//*filtered*/', $this->setting->value() );
     188
     189        $this->wp_customize->set_post_value( $this->setting->id, '/*overridden*/' );
     190        $this->setting->preview();
     191        $this->assertEquals( '/*overridden*/', $this->setting->value(), 'Expected value to not be filtered since post value is present.' );
     192    }
     193
     194    /**
     195     * Filter value.
     196     *
     197     * @param string $value                 Value.
     198     * @param WP_Customize_Setting $setting Setting.
     199     * @return string
     200     */
     201    function filter_value( $value, $setting ) {
     202        $this->assertInstanceOf( 'WP_Customize_Custom_CSS_Setting', $setting );
     203        $value .= '/*filtered*/';
     204        return $value;
     205    }
     206
     207    /**
     208     * Test update filter on WP_Customize_Custom_CSS_Setting.
     209     *
     210     * @covers WP_Customize_Custom_CSS_Setting::update()
     211     */
     212    function test_update_filter() {
     213        $original_css = 'body { color:red; }';
     214        $post_id = $this->factory()->post->create( array(
     215            'post_title' => $this->setting->stylesheet,
     216            'post_name' => $this->setting->stylesheet,
     217            'post_content' => $original_css,
     218            'post_status' => 'publish',
     219            'post_type' => 'custom_css',
     220        ) );
     221
     222        $overridden_css = 'body { color:green; }';
     223        $this->wp_customize->set_post_value( $this->setting->id, $overridden_css );
     224
     225        $post = get_post( $post_id );
     226        $original_title = $post->post_title;
     227
     228        add_filter( 'customize_update_custom_css_post_content_args', array( $this, 'filter_update_post_content_args' ), 10, 3 );
     229        $this->setting->save();
     230
     231        $post = get_post( $post_id );
     232        $this->assertEquals( $original_title, $post->post_title );
     233        $this->assertContains( $overridden_css, $post->post_content );
     234        $this->assertContains( '/* filtered post_content */', $post->post_content );
     235        $this->assertContains( '/* filtered post_content_filtered */', $post->post_content_filtered );
     236    }
     237
     238    /**
     239     * Filter `customize_update_custom_css_post_content_args`.
     240     *
     241     * @param array                $args    Post array.
     242     * @param string               $css     CSS.
     243     * @param WP_Customize_Setting $setting Setting.
     244     * @return array Args.
     245     */
     246    function filter_update_post_content_args( $args, $css, $setting ) {
     247        $this->assertInternalType( 'array', $args );
     248        $this->assertEqualSets( array( 'post_content', 'post_content_filtered' ), array_keys( $args ) );
     249        $this->assertEquals( $css, $args['post_content'] );
     250        $this->assertEquals( '', $args['post_content_filtered'] );
     251        $this->assertInstanceOf( 'WP_Customize_Custom_CSS_Setting', $setting );
     252
     253        $args['post_content'] .= '/* filtered post_content */';
     254        $args['post_content_filtered'] = '/* filtered post_content_filtered */';
     255        $args['post_title'] = 'Ignored';
     256        return $args;
     257    }
     258
     259    /**
    171260     * Tests that validation errors are caught appropriately.
    172261     *
Note: See TracChangeset for help on using the changeset viewer.