Changeset 27652
- Timestamp:
- 03/22/2014 08:54:17 PM (10 years ago)
- Location:
- trunk/src
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-admin/js/customize-widgets.js
r27650 r27652 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 … … 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]' ) ) { … … 1219 1223 has_same_inputs_in_response, 1220 1224 is_instance_identical; 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 } 1221 1241 1222 1242 if ( r.success ) { … … 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 ); … … 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; … … 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 } … … 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 () { -
trunk/src/wp-includes/class-wp-customize-widgets.php
r27620 r27652 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 ) ); 437 } 432 return new WP_Error( 'invalid_setting_id', 'Invalid widget setting ID' ); 433 } 434 438 435 $id_base = $matches[2]; 439 436 $number = isset( $matches[3] ) ? intval( $matches[3] ) : null; … … 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( … … 913 911 * $_POST be populated with the instance data. 914 912 * 915 * @throws Widget_Customizer_Exception 916 * @throws Exception 917 * 918 * @param string $widget_id 919 * @return array 913 * @param string $widget_id 914 * @return WP_Error|array 920 915 */ 921 916 static function call_widget_update( $widget_id ) { … … 924 919 $options_transaction = new Options_Transaction(); 925 920 926 try { 927 $options_transaction->start(); 928 $parsed_id = self::parse_widget_id( $widget_id ); 929 $option_name = 'widget_' . $parsed_id['id_base']; 930 931 /** 932 * If a previously-sanitized instance is provided, populate the input vars 933 * with its values so that the widget update callback will read this instance 934 */ 935 $added_input_vars = array(); 936 if ( ! empty( $_POST['sanitized_widget_setting'] ) ) { 937 $sanitized_widget_setting = json_decode( self::get_post_value( 'sanitized_widget_setting' ), true ); 938 if ( empty( $sanitized_widget_setting ) ) { 939 throw new Widget_Customizer_Exception( 'Malformed sanitized_widget_setting' ); 940 } 941 $instance = self::sanitize_widget_instance( $sanitized_widget_setting ); 942 if ( is_null( $instance ) ) { 943 throw new Widget_Customizer_Exception( 'Unsanitary sanitized_widget_setting' ); 944 } 945 if ( ! is_null( $parsed_id['number'] ) ) { 946 $value = array(); 947 $value[$parsed_id['number']] = $instance; 948 $key = 'widget-' . $parsed_id['id_base']; 921 $options_transaction->start(); 922 $parsed_id = self::parse_widget_id( $widget_id ); 923 $option_name = 'widget_' . $parsed_id['id_base']; 924 925 /** 926 * If a previously-sanitized instance is provided, populate the input vars 927 * with its values so that the widget update callback will read this instance 928 */ 929 $added_input_vars = array(); 930 if ( ! empty( $_POST['sanitized_widget_setting'] ) ) { 931 $sanitized_widget_setting = json_decode( self::get_post_value( 'sanitized_widget_setting' ), true ); 932 if ( empty( $sanitized_widget_setting ) ) { 933 $options_transaction->rollback(); 934 return new WP_Error( 'malformed_data', 'Malformed sanitized_widget_setting' ); 935 } 936 937 $instance = self::sanitize_widget_instance( $sanitized_widget_setting ); 938 if ( is_null( $instance ) ) { 939 $options_transaction->rollback(); 940 return new WP_Error( 'unsanitary_data', 'Unsanitary sanitized_widget_setting' ); 941 } 942 943 if ( ! is_null( $parsed_id['number'] ) ) { 944 $value = array(); 945 $value[$parsed_id['number']] = $instance; 946 $key = 'widget-' . $parsed_id['id_base']; 947 $_REQUEST[$key] = $_POST[$key] = wp_slash( $value ); 948 $added_input_vars[] = $key; 949 } else { 950 foreach ( $instance as $key => $value ) { 949 951 $_REQUEST[$key] = $_POST[$key] = wp_slash( $value ); 950 952 $added_input_vars[] = $key; 951 } else {952 foreach ( $instance as $key => $value ) {953 $_REQUEST[$key] = $_POST[$key] = wp_slash( $value );954 $added_input_vars[] = $key;955 }956 953 } 957 954 } 958 959 /** 960 * Invoke the widget update callback 961 */ 962 foreach ( (array) $wp_registered_widget_updates as $name => $control ) { 963 if ( $name === $parsed_id['id_base'] && is_callable( $control['callback'] ) ) { 964 ob_start(); 965 call_user_func_array( $control['callback'], $control['params'] ); 966 ob_end_clean(); 967 break; 968 } 969 } 970 971 // Clean up any input vars that were manually added 972 foreach ( $added_input_vars as $key ) { 973 unset( $_POST[$key] ); 974 unset( $_REQUEST[$key] ); 975 } 976 977 /** 978 * Make sure the expected option was updated 979 */ 980 if ( 0 !== $options_transaction->count() ) { 981 if ( count( $options_transaction->options ) > 1 ) { 982 throw new Widget_Customizer_Exception( sprintf( 'Widget %1$s unexpectedly updated more than one option.', $widget_id ) ); 983 } 984 $updated_option_name = key( $options_transaction->options ); 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 ) ); 987 } 988 } 989 990 /** 991 * Obtain the widget control with the updated instance in place 992 */ 993 ob_start(); 994 $form = $wp_registered_widget_controls[$widget_id]; 995 if ( $form ) { 996 call_user_func_array( $form['callback'], $form['params'] ); 997 } 998 $form = ob_get_clean(); 999 1000 /** 1001 * Obtain the widget instance 1002 */ 1003 $option = get_option( $option_name ); 1004 if ( null !== $parsed_id['number'] ) { 1005 $instance = $option[$parsed_id['number']]; 1006 } else { 1007 $instance = $option; 1008 } 1009 1010 $options_transaction->rollback(); 1011 return compact( 'instance', 'form' ); 1012 } 1013 catch ( Exception $e ) { 1014 $options_transaction->rollback(); 1015 throw $e; 1016 } 955 } 956 957 /** 958 * Invoke the widget update callback 959 */ 960 foreach ( (array) $wp_registered_widget_updates as $name => $control ) { 961 if ( $name === $parsed_id['id_base'] && is_callable( $control['callback'] ) ) { 962 ob_start(); 963 call_user_func_array( $control['callback'], $control['params'] ); 964 ob_end_clean(); 965 break; 966 } 967 } 968 969 // Clean up any input vars that were manually added 970 foreach ( $added_input_vars as $key ) { 971 unset( $_POST[$key] ); 972 unset( $_REQUEST[$key] ); 973 } 974 975 /** 976 * Make sure the expected option was updated 977 */ 978 if ( 0 !== $options_transaction->count() ) { 979 if ( count( $options_transaction->options ) > 1 ) { 980 $options_transaction->rollback(); 981 return new WP_Error( 'unexpected_update', 'Widget unexpectedly updated more than one option.' ); 982 } 983 984 $updated_option_name = key( $options_transaction->options ); 985 if ( $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 ) ); 988 } 989 } 990 991 /** 992 * Obtain the widget control with the updated instance in place 993 */ 994 ob_start(); 995 $form = $wp_registered_widget_controls[$widget_id]; 996 if ( $form ) { 997 call_user_func_array( $form['callback'], $form['params'] ); 998 } 999 $form = ob_get_clean(); 1000 1001 /** 1002 * Obtain the widget instance 1003 */ 1004 $option = get_option( $option_name ); 1005 if ( null !== $parsed_id['number'] ) { 1006 $instance = $option[$parsed_id['number']]; 1007 } else { 1008 $instance = $option; 1009 } 1010 1011 $options_transaction->rollback(); 1012 return compact( 'instance', 'form' ); 1017 1013 } 1018 1014 … … 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 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?' ) ); 1034 } 1035 if ( ! current_user_can( 'edit_theme_options' ) ) { 1036 throw new Widget_Customizer_Exception( ( 'Current user cannot!' ) ); // @todo translate 1037 } 1038 if ( ! isset( $_POST['widget-id'] ) ) { 1039 throw new Widget_Customizer_Exception( ( 'Incomplete request' ) ); // @todo translate 1040 } 1041 1042 unset( $_POST[self::UPDATE_WIDGET_NONCE_POST_KEY], $_POST['action'] ); 1043 1044 do_action( 'load-widgets.php' ); 1045 do_action( 'widgets.php' ); 1046 do_action( 'sidebar_admin_setup' ); 1047 1048 $widget_id = self::get_post_value( 'widget-id' ); 1049 $parsed_id = self::parse_widget_id( $widget_id ); 1050 $id_base = $parsed_id['id_base']; 1051 1052 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' ); 1054 } 1055 1056 $updated_widget = self::call_widget_update( $widget_id ); // => {instance,form} 1057 $form = $updated_widget['form']; 1058 $instance = self::sanitize_widget_js_instance( $updated_widget['instance'] ); 1059 1060 wp_send_json_success( compact( 'form', 'instance' ) ); 1061 } 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 } 1069 wp_send_json_error( compact( 'message' ) ); 1070 } 1025 1026 if ( ! is_user_logged_in() ) { 1027 wp_die( 0 ); 1028 } 1029 1030 check_ajax_referer( self::UPDATE_WIDGET_AJAX_ACTION, self::UPDATE_WIDGET_NONCE_POST_KEY ); 1031 1032 if ( ! current_user_can( 'edit_theme_options' ) ) { 1033 wp_die( -1 ); 1034 } 1035 1036 if ( ! isset( $_POST['widget-id'] ) ) { 1037 wp_send_json_error(); 1038 } 1039 1040 unset( $_POST[self::UPDATE_WIDGET_NONCE_POST_KEY], $_POST['action'] ); 1041 1042 do_action( 'load-widgets.php' ); 1043 do_action( 'widgets.php' ); 1044 do_action( 'sidebar_admin_setup' ); 1045 1046 $widget_id = self::get_post_value( 'widget-id' ); 1047 $parsed_id = self::parse_widget_id( $widget_id ); 1048 $id_base = $parsed_id['id_base']; 1049 1050 if ( isset( $_POST['widget-' . $id_base] ) && is_array( $_POST['widget-' . $id_base] ) && preg_match( '/__i__|%i%/', key( $_POST['widget-' . $id_base] ) ) ) { 1051 wp_send_json_error(); 1052 } 1053 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 1059 $form = $updated_widget['form']; 1060 $instance = self::sanitize_widget_js_instance( $updated_widget['instance'] ); 1061 1062 wp_send_json_success( compact( 'form', 'instance' ) ); 1071 1063 } 1072 1064 } 1073 1074 class Widget_Customizer_Exception extends Exception {}1075 1065 1076 1066 class Options_Transaction { … … 1205 1195 update_option( $option_operation['option_name'], $option_operation['old_value'] ); 1206 1196 } 1207 else {1208 throw new Exception( 'Unexpected operation' );1209 }1210 1197 } 1211 1198 $this->_is_current = false;
Note: See TracChangeset
for help on using the changeset viewer.