Changeset 27652 for trunk/src/wp-includes/class-wp-customize-widgets.php
- Timestamp:
- 03/22/2014 08:54:17 PM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
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.