Make WordPress Core

Ticket #27419: 27419.2.patch

File 27419.2.patch, 9.7 KB (added by ocean90, 11 years ago)
  • src/wp-admin/js/customize-controls.js

     
    853853                                }
    854854
    855855                                if ( 'cheatin' === reason )
    856                                         self.cheatin();
     856                                        self.cheatin()
    857857                        });
    858858                },
    859859
  • src/wp-admin/js/customize-widgets.js

     
    1616                        save_btn_label: '',
    1717                        save_btn_tooltip: '',
    1818                        remove_btn_label: '',
    19                         remove_btn_tooltip: ''
     19                        remove_btn_tooltip: '',
     20                        error: '',
    2021                },
    2122                available_widgets: [], // available widgets for instantiating
    2223                registered_widgets: [], // all widgets registered
     
    11721173
    11731174                        widget_content = control.container.find( '.widget-content' );
    11741175
     1176                        // Remove a previous error message
     1177                        widget_content.find( '.widget-error' ).remove();
     1178
    11751179                        // @todo Support more selectors than IDs?
    11761180                        if ( $.contains( control.container[0], document.activeElement ) && $( document.activeElement ).is( '[id]' ) ) {
    11771181                                element_id_to_refocus = $( document.activeElement ).prop( 'id' );
     
    12191223                                        has_same_inputs_in_response,
    12201224                                        is_instance_identical;
    12211225
     1226                                // Check if the user is logged out.
     1227                                if ( '0' === r ) {
     1228                                        self.previewer.preview.iframe.hide();
     1229                                        self.previewer.login().done( function() {
     1230                                                control.updateWidget( args );
     1231                                                self.previewer.preview.iframe.show();
     1232                                        } );
     1233                                        return;
     1234                                }
     1235
     1236                                // Check for cheaters.
     1237                                if ( '-1' === r ) {
     1238                                        self.previewer.cheatin();
     1239                                        return;
     1240                                }
     1241
    12221242                                if ( r.success ) {
    12231243                                        sanitized_form = $( '<div>' + r.data.form + '</div>' );
    12241244
     
    12741294                                         * preview finishing loading.
    12751295                                         */
    12761296                                        is_instance_identical = _( control.setting() ).isEqual( r.data.instance );
    1277                                         if ( is_instance_identical ) {
    1278                                                 control.container.removeClass( 'previewer-loading' );
    1279                                         } else {
     1297                                        if ( ! is_instance_identical ) {
    12801298                                                control.is_widget_updating = true; // suppress triggering another updateWidget
    12811299                                                control.setting( r.data.instance );
    12821300                                                control.is_widget_updating = false;
     
    12861304                                                complete_callback.call( control, null, { no_change: is_instance_identical, ajax_finished: true } );
    12871305                                        }
    12881306                                } else {
    1289                                         window.console && window.console.log( r );
    1290                                         message = 'FAIL';
     1307                                        message = self.i18n.error;
    12911308                                        if ( r.data && r.data.message ) {
    12921309                                                message = r.data.message;
    12931310                                        }
    12941311                                        if ( complete_callback ) {
    12951312                                                complete_callback.call( control, message );
    12961313                                        } else {
    1297                                                 throw new Error( message );
     1314                                                widget_content.prepend( '<p class="widget-error"><strong>' + message + '</strong></p>' );
    12981315                                        }
    12991316                                }
    13001317                        } );
    13011318                        jqxhr.fail( function ( jqXHR, textStatus ) {
    13021319                                if ( complete_callback ) {
    13031320                                        complete_callback.call( control, textStatus );
    1304                                 } else {
    1305                                         throw new Error( textStatus );
    13061321                                }
    13071322                        } );
    13081323                        jqxhr.always( function () {
     1324                                control.container.removeClass( 'previewer-loading' );
    13091325                                control.container.removeClass( 'widget-form-loading' );
    13101326                                inputs.each( function () {
    13111327                                        $( this ).removeData( 'state' + update_number );
  • src/wp-includes/class-wp-customize-widgets.php

     
    424424        /**
    425425         * Convert a widget setting ID (option path) to its id_base and number components
    426426         *
    427          * @throws Widget_Customizer_Exception
    428          * @throws Exception
    429          *
    430427         * @param string $setting_id
    431          * @param array
    432          * @return array
     428         * @return WP_Error|array
    433429         */
    434430        static function parse_widget_setting_id( $setting_id ) {
    435431                if ( ! preg_match( '/^(widget_(.+?))(?:\[(\d+)\])?$/', $setting_id, $matches ) ) {
    436                         throw new Widget_Customizer_Exception( sprintf( 'Invalid widget setting ID: %s', $setting_id ) );
     432                        return new WP_Error( 'invalid_setting_id', 'Invalid widget setting ID' );
    437433                }
     434
    438435                $id_base = $matches[2];
    439436                $number  = isset( $matches[3] ) ? intval( $matches[3] ) : null;
    440437                return compact( 'id_base', 'number' );
     
    500497                                'save_btn_tooltip' => ( 'Save and preview changes before publishing them.' ),
    501498                                'remove_btn_label' => __( 'Remove' ),
    502499                                'remove_btn_tooltip' => ( 'Trash widget by moving it to the inactive widgets sidebar.' ),
     500                                'error' => __('An error has occurred. Please reload the page and try again.'),
    503501                        ),
    504502                        'tpl' => array(
    505503                                'widget_reorder_nav' => $widget_reorder_nav_tpl,
     
    912910         * Find and invoke the widget update and control callbacks. Requires that
    913911         * $_POST be populated with the instance data.
    914912         *
    915          * @throws Widget_Customizer_Exception
    916          * @throws Exception
    917          *
    918913         * @param string $widget_id
    919          * @return array
     914         * @return WP_Error|array
    920915         */
    921916        static function call_widget_update( $widget_id ) {
    922917                global $wp_registered_widget_updates, $wp_registered_widget_controls;
    923918
    924919                $options_transaction = new Options_Transaction();
    925920
    926                 try {
    927921                        $options_transaction->start();
    928922                        $parsed_id   = self::parse_widget_id( $widget_id );
    929923                        $option_name = 'widget_' . $parsed_id['id_base'];
     
    936930                        if ( ! empty( $_POST['sanitized_widget_setting'] ) ) {
    937931                                $sanitized_widget_setting = json_decode( self::get_post_value( 'sanitized_widget_setting' ), true );
    938932                                if ( empty( $sanitized_widget_setting ) ) {
    939                                         throw new Widget_Customizer_Exception( 'Malformed sanitized_widget_setting' );
     933                                $options_transaction->rollback();
     934                                return new WP_Error( 'malformed_data', 'Malformed sanitized_widget_setting' );
    940935                                }
     936
    941937                                $instance = self::sanitize_widget_instance( $sanitized_widget_setting );
    942938                                if ( is_null( $instance ) ) {
    943                                         throw new Widget_Customizer_Exception( 'Unsanitary sanitized_widget_setting' );
     939                                $options_transaction->rollback();
     940                                return new WP_Error( 'unsanitary_data', 'Unsanitary sanitized_widget_setting' );
    944941                                }
     942
    945943                                if ( ! is_null( $parsed_id['number'] ) ) {
    946944                                        $value = array();
    947945                                        $value[$parsed_id['number']] = $instance;
     
    979977                         */
    980978                        if ( 0 !== $options_transaction->count() ) {
    981979                                if ( count( $options_transaction->options ) > 1 ) {
    982                                         throw new Widget_Customizer_Exception( sprintf( 'Widget %1$s unexpectedly updated more than one option.', $widget_id ) );
     980                                $options_transaction->rollback();
     981                                return new WP_Error( 'unexpected_update', 'Widget unexpectedly updated more than one option.' );
    983982                                }
     983
    984984                                $updated_option_name = key( $options_transaction->options );
    985985                                if ( $updated_option_name !== $option_name ) {
    986                                         throw new Widget_Customizer_Exception( sprintf( 'Widget %1$s updated option "%2$s", but expected "%3$s".', $widget_id, $updated_option_name, $option_name ) );
     986                                $options_transaction->rollback();
     987                                return new WP_Error( 'wrong_option', sprintf( 'Widget updated option "%1$s", but expected "%2$s".', $updated_option_name, $option_name ) );
    987988                                }
    988989                        }
    989990
     
    10101011                        $options_transaction->rollback();
    10111012                        return compact( 'instance', 'form' );
    10121013                }
    1013                 catch ( Exception $e ) {
    1014                         $options_transaction->rollback();
    1015                         throw $e;
    1016                 }
    1017         }
    10181014
    10191015        /**
    10201016         * Allow customizer to update a widget using its form, but return the new
     
    10261022         * @action wp_ajax_update_widget
    10271023         */
    10281024        static function wp_ajax_update_widget() {
    1029                 $generic_error = __( 'An error has occurred. Please reload the page and try again.' );
    10301025
    1031                 try {
    1032                         if ( ! check_ajax_referer( self::UPDATE_WIDGET_AJAX_ACTION, self::UPDATE_WIDGET_NONCE_POST_KEY, false ) ) {
    1033                                 throw new Widget_Customizer_Exception( ( 'Nonce check failed. Reload and try again?' ) );
     1026                if ( ! is_user_logged_in() ) {
     1027                        wp_die( 0 );
    10341028                        }
     1029
     1030                check_ajax_referer( self::UPDATE_WIDGET_AJAX_ACTION, self::UPDATE_WIDGET_NONCE_POST_KEY, false );
     1031
    10351032                        if ( ! current_user_can( 'edit_theme_options' ) ) {
    1036                                 throw new Widget_Customizer_Exception( ( 'Current user cannot!' ) ); // @todo translate
     1033                        wp_die( -1 );
    10371034                        }
    1038                         if ( ! isset( $_POST['widget-id'] ) ) {
    1039                                 throw new Widget_Customizer_Exception( ( 'Incomplete request' ) ); // @todo translate
     1035
     1036                if ( isset( $_POST['widget-id'] ) ) {
     1037                        wp_send_json_error();
    10401038                        }
    10411039
    10421040                        unset( $_POST[self::UPDATE_WIDGET_NONCE_POST_KEY], $_POST['action'] );
     
    10501048                        $id_base   = $parsed_id['id_base'];
    10511049
    10521050                        if ( isset( $_POST['widget-' . $id_base] ) && is_array( $_POST['widget-' . $id_base] ) && preg_match( '/__i__|%i%/', key( $_POST['widget-' . $id_base] ) ) ) {
    1053                                 throw new Widget_Customizer_Exception( 'Cannot pass widget templates to create new instances; apply template vars in JS' );
     1051                        wp_send_json_error();
    10541052                        }
    10551053
    10561054                        $updated_widget = self::call_widget_update( $widget_id ); // => {instance,form}
     1055                if ( is_wp_error( $updated_widget ) ) {
     1056                        wp_send_json_error();
     1057                }
     1058
    10571059                        $form = $updated_widget['form'];
    10581060                        $instance = self::sanitize_widget_js_instance( $updated_widget['instance'] );
    10591061
    10601062                        wp_send_json_success( compact( 'form', 'instance' ) );
    10611063                }
    1062                 catch( Exception $e ) {
    1063                         if ( $e instanceof Widget_Customizer_Exception ) {
    1064                                 $message = $e->getMessage();
    1065                         } else {
    1066                                 error_log( sprintf( '%s in %s: %s', get_class( $e ), __FUNCTION__, $e->getMessage() ) );
    1067                                 $message = $generic_error;
    10681064                        }
    1069                         wp_send_json_error( compact( 'message' ) );
    1070                 }
    1071         }
    1072 }
    10731065
    1074 class Widget_Customizer_Exception extends Exception {}
    1075 
    10761066class Options_Transaction {
    10771067
    10781068        /**
     
    12041194                        else if ( 'update' === $option_operation['operation'] ) {
    12051195                                update_option( $option_operation['option_name'], $option_operation['old_value'] );
    12061196                        }
    1207                         else {
    1208                                 throw new Exception( 'Unexpected operation' );
    12091197                        }
    1210                 }
    12111198                $this->_is_current = false;
    12121199        }
    12131200}