Ticket #27419: 27419.2.patch
File 27419.2.patch, 9.7 KB (added by , 11 years ago) |
---|
-
src/wp-admin/js/customize-controls.js
853 853 } 854 854 855 855 if ( 'cheatin' === reason ) 856 self.cheatin() ;856 self.cheatin() 857 857 }); 858 858 }, 859 859 -
src/wp-admin/js/customize-widgets.js
16 16 save_btn_label: '', 17 17 save_btn_tooltip: '', 18 18 remove_btn_label: '', 19 remove_btn_tooltip: '' 19 remove_btn_tooltip: '', 20 error: '', 20 21 }, 21 22 available_widgets: [], // available widgets for instantiating 22 23 registered_widgets: [], // all widgets registered … … 1172 1173 1173 1174 widget_content = control.container.find( '.widget-content' ); 1174 1175 1176 // Remove a previous error message 1177 widget_content.find( '.widget-error' ).remove(); 1178 1175 1179 // @todo Support more selectors than IDs? 1176 1180 if ( $.contains( control.container[0], document.activeElement ) && $( document.activeElement ).is( '[id]' ) ) { 1177 1181 element_id_to_refocus = $( document.activeElement ).prop( 'id' ); … … 1219 1223 has_same_inputs_in_response, 1220 1224 is_instance_identical; 1221 1225 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 1222 1242 if ( r.success ) { 1223 1243 sanitized_form = $( '<div>' + r.data.form + '</div>' ); 1224 1244 … … 1274 1294 * preview finishing loading. 1275 1295 */ 1276 1296 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 ) { 1280 1298 control.is_widget_updating = true; // suppress triggering another updateWidget 1281 1299 control.setting( r.data.instance ); 1282 1300 control.is_widget_updating = false; … … 1286 1304 complete_callback.call( control, null, { no_change: is_instance_identical, ajax_finished: true } ); 1287 1305 } 1288 1306 } else { 1289 window.console && window.console.log( r ); 1290 message = 'FAIL'; 1307 message = self.i18n.error; 1291 1308 if ( r.data && r.data.message ) { 1292 1309 message = r.data.message; 1293 1310 } 1294 1311 if ( complete_callback ) { 1295 1312 complete_callback.call( control, message ); 1296 1313 } else { 1297 throw new Error( message);1314 widget_content.prepend( '<p class="widget-error"><strong>' + message + '</strong></p>' ); 1298 1315 } 1299 1316 } 1300 1317 } ); 1301 1318 jqxhr.fail( function ( jqXHR, textStatus ) { 1302 1319 if ( complete_callback ) { 1303 1320 complete_callback.call( control, textStatus ); 1304 } else {1305 throw new Error( textStatus );1306 1321 } 1307 1322 } ); 1308 1323 jqxhr.always( function () { 1324 control.container.removeClass( 'previewer-loading' ); 1309 1325 control.container.removeClass( 'widget-form-loading' ); 1310 1326 inputs.each( function () { 1311 1327 $( this ).removeData( 'state' + update_number ); -
src/wp-includes/class-wp-customize-widgets.php
424 424 /** 425 425 * Convert a widget setting ID (option path) to its id_base and number components 426 426 * 427 * @throws Widget_Customizer_Exception428 * @throws Exception429 *430 427 * @param string $setting_id 431 * @param array 432 * @return array 428 * @return WP_Error|array 433 429 */ 434 430 static function parse_widget_setting_id( $setting_id ) { 435 431 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' ); 437 433 } 434 438 435 $id_base = $matches[2]; 439 436 $number = isset( $matches[3] ) ? intval( $matches[3] ) : null; 440 437 return compact( 'id_base', 'number' ); … … 500 497 'save_btn_tooltip' => ( 'Save and preview changes before publishing them.' ), 501 498 'remove_btn_label' => __( 'Remove' ), 502 499 '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.'), 503 501 ), 504 502 'tpl' => array( 505 503 'widget_reorder_nav' => $widget_reorder_nav_tpl, … … 912 910 * Find and invoke the widget update and control callbacks. Requires that 913 911 * $_POST be populated with the instance data. 914 912 * 915 * @throws Widget_Customizer_Exception916 * @throws Exception917 *918 913 * @param string $widget_id 919 * @return array914 * @return WP_Error|array 920 915 */ 921 916 static function call_widget_update( $widget_id ) { 922 917 global $wp_registered_widget_updates, $wp_registered_widget_controls; 923 918 924 919 $options_transaction = new Options_Transaction(); 925 920 926 try {927 921 $options_transaction->start(); 928 922 $parsed_id = self::parse_widget_id( $widget_id ); 929 923 $option_name = 'widget_' . $parsed_id['id_base']; … … 936 930 if ( ! empty( $_POST['sanitized_widget_setting'] ) ) { 937 931 $sanitized_widget_setting = json_decode( self::get_post_value( 'sanitized_widget_setting' ), true ); 938 932 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' ); 940 935 } 936 941 937 $instance = self::sanitize_widget_instance( $sanitized_widget_setting ); 942 938 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' ); 944 941 } 942 945 943 if ( ! is_null( $parsed_id['number'] ) ) { 946 944 $value = array(); 947 945 $value[$parsed_id['number']] = $instance; … … 979 977 */ 980 978 if ( 0 !== $options_transaction->count() ) { 981 979 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.' ); 983 982 } 983 984 984 $updated_option_name = key( $options_transaction->options ); 985 985 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 ) ); 987 988 } 988 989 } 989 990 … … 1010 1011 $options_transaction->rollback(); 1011 1012 return compact( 'instance', 'form' ); 1012 1013 } 1013 catch ( Exception $e ) {1014 $options_transaction->rollback();1015 throw $e;1016 }1017 }1018 1014 1019 1015 /** 1020 1016 * Allow customizer to update a widget using its form, but return the new … … 1026 1022 * @action wp_ajax_update_widget 1027 1023 */ 1028 1024 static function wp_ajax_update_widget() { 1029 $generic_error = __( 'An error has occurred. Please reload the page and try again.' );1030 1025 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 ); 1034 1028 } 1029 1030 check_ajax_referer( self::UPDATE_WIDGET_AJAX_ACTION, self::UPDATE_WIDGET_NONCE_POST_KEY, false ); 1031 1035 1032 if ( ! current_user_can( 'edit_theme_options' ) ) { 1036 throw new Widget_Customizer_Exception( ( 'Current user cannot!' ) ); // @todo translate1033 wp_die( -1 ); 1037 1034 } 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(); 1040 1038 } 1041 1039 1042 1040 unset( $_POST[self::UPDATE_WIDGET_NONCE_POST_KEY], $_POST['action'] ); … … 1050 1048 $id_base = $parsed_id['id_base']; 1051 1049 1052 1050 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(); 1054 1052 } 1055 1053 1056 1054 $updated_widget = self::call_widget_update( $widget_id ); // => {instance,form} 1055 if ( is_wp_error( $updated_widget ) ) { 1056 wp_send_json_error(); 1057 } 1058 1057 1059 $form = $updated_widget['form']; 1058 1060 $instance = self::sanitize_widget_js_instance( $updated_widget['instance'] ); 1059 1061 1060 1062 wp_send_json_success( compact( 'form', 'instance' ) ); 1061 1063 } 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;1068 1064 } 1069 wp_send_json_error( compact( 'message' ) );1070 }1071 }1072 }1073 1065 1074 class Widget_Customizer_Exception extends Exception {}1075 1076 1066 class Options_Transaction { 1077 1067 1078 1068 /** … … 1204 1194 else if ( 'update' === $option_operation['operation'] ) { 1205 1195 update_option( $option_operation['option_name'], $option_operation['old_value'] ); 1206 1196 } 1207 else {1208 throw new Exception( 'Unexpected operation' );1209 1197 } 1210 }1211 1198 $this->_is_current = false; 1212 1199 } 1213 1200 }