unsanitized_post_values() public method

The returned array consists of a merge of three sources: 1. If the theme is not currently active, then the base array is any stashed theme mods that were modified previously but never published. 2. The values from the current changeset, if it exists. 3. If the user can customize, the values parsed from the incoming $_POST['customized'] JSON data. 4. Any programmatically-set post values via WP_Customize_Manager::set_post_value(). The name "unsanitized_post_values" is a carry-over from when the customized state was exclusively sourced from $_POST['customized']. Nevertheless, the value returned will come from the current changeset post and from the incoming post data.
Since: 4.1.1
Since: 4.7.0 Added $args param and merging with changeset values and stashed theme mods.
public unsanitized_post_values ( array $args = [] ) : array
$args array { Args. @type bool $exclude_changeset Whether the changeset values should also be excluded. Defaults to false. @type bool $exclude_post_data Whether the post input values should also be excluded. Defaults to false when lacking the customize capability. }
return array
Ejemplo n.º 1
0
 /**
  * @ticket 34738
  * @see WP_Customize_Widgets::call_widget_update()
  */
 function test_call_widget_update()
 {
     $widget_number = 2;
     $widget_id = "search-{$widget_number}";
     $setting_id = "widget_search[{$widget_number}]";
     $instance = array('title' => 'Buscar');
     $_POST = wp_slash(array('action' => 'update-widget', 'wp_customize' => 'on', 'nonce' => wp_create_nonce('update-widget'), 'theme' => $this->manager->get_stylesheet(), 'customized' => '{}', 'widget-search' => array(2 => $instance), 'widget-id' => $widget_id, 'id_base' => 'search', 'widget-width' => '250', 'widget-height' => '200', 'widget_number' => strval($widget_number), 'multi_number' => '', 'add_new' => ''));
     $this->do_customize_boot_actions();
     $this->assertArrayNotHasKey($setting_id, $this->manager->unsanitized_post_values());
     $result = $this->manager->widgets->call_widget_update($widget_id);
     $this->assertInternalType('array', $result);
     $this->assertArrayHasKey('instance', $result);
     $this->assertArrayHasKey('form', $result);
     $this->assertEquals($instance, $result['instance']);
     $this->assertContains(sprintf('value="%s"', esc_attr($instance['title'])), $result['form']);
     $post_values = $this->manager->unsanitized_post_values();
     $this->assertArrayHasKey($setting_id, $post_values);
     $post_value = $post_values[$setting_id];
     $this->assertInternalType('array', $post_value);
     $this->assertArrayHasKey('title', $post_value);
     $this->assertArrayHasKey('encoded_serialized_instance', $post_value);
     $this->assertArrayHasKey('instance_hash_key', $post_value);
     $this->assertArrayHasKey('is_widget_customizer_js_value', $post_value);
     $this->assertEquals($post_value, $this->manager->widgets->sanitize_widget_js_instance($instance));
 }
	/**
	 * Inspect the incoming customized data for any widget settings, and dynamically add them up-front so widgets will be initialized properly.
	 *
	 * @since 4.2.0
	 * @access public
	 */
	public function register_settings() {
		$widget_setting_ids = array();
		$incoming_setting_ids = array_keys( $this->manager->unsanitized_post_values() );
		foreach ( $incoming_setting_ids as $setting_id ) {
			if ( ! is_null( $this->get_setting_type( $setting_id ) ) ) {
				$widget_setting_ids[] = $setting_id;
			}
		}
		if ( $this->manager->doing_ajax( 'update-widget' ) && isset( $_REQUEST['widget-id'] ) ) {
			$widget_setting_ids[] = $this->get_setting_id( wp_unslash( $_REQUEST['widget-id'] ) );
		}

		$settings = $this->manager->add_dynamic_settings( array_unique( $widget_setting_ids ) );

		/*
		 * Preview settings right away so that widgets and sidebars will get registered properly.
		 * But don't do this if a customize_save because this will cause WP to think there is nothing
		 * changed that needs to be saved.
		 */
		if ( ! $this->manager->doing_ajax( 'customize_save' ) ) {
			foreach ( $settings as $setting ) {
				$setting->preview();
			}
		}
	}
 private function _save()
 {
     $post_values = $this->_customize->unsanitized_post_values();
     $key = '_' . static::KEY;
     if (isset($post_values[$key])) {
         $this->_customize->add_dynamic_settings(array_map('sanitize_key', $post_values[$key]));
     }
 }
Ejemplo n.º 4
0
 /**
  * Test WP_Customize_Manager::set_post_value().
  *
  * @see WP_Customize_Manager::set_post_value()
  */
 function test_set_post_value()
 {
     $this->manager->add_setting('foo', array('sanitize_callback' => array($this, 'sanitize_foo_for_test_set_post_value')));
     $setting = $this->manager->get_setting('foo');
     $this->assertEmpty($this->captured_customize_post_value_set_actions);
     add_action('customize_post_value_set', array($this, 'capture_customize_post_value_set_actions'), 10, 3);
     add_action('customize_post_value_set_foo', array($this, 'capture_customize_post_value_set_actions'), 10, 2);
     $this->manager->set_post_value($setting->id, '123abc');
     $this->assertCount(2, $this->captured_customize_post_value_set_actions);
     $this->assertEquals('customize_post_value_set_foo', $this->captured_customize_post_value_set_actions[0]['action']);
     $this->assertEquals('customize_post_value_set', $this->captured_customize_post_value_set_actions[1]['action']);
     $this->assertEquals(array('123abc', $this->manager), $this->captured_customize_post_value_set_actions[0]['args']);
     $this->assertEquals(array($setting->id, '123abc', $this->manager), $this->captured_customize_post_value_set_actions[1]['args']);
     $unsanitized = $this->manager->unsanitized_post_values();
     $this->assertArrayHasKey($setting->id, $unsanitized);
     $this->assertEquals('123abc', $unsanitized[$setting->id]);
     $this->assertEquals(123, $setting->post_value());
 }
 /**
  * Update saved previewed settings with a publish status.
  *
  * This results in the setting value being pushed out to other user sessions
  * and the settings being unlocked.
  */
 public function customize_save_after()
 {
     $customized = $this->customize_manager->unsanitized_post_values();
     /**
      * Filters which settings have been saved.
      *
      * @param array $customized Unsanitized post values.
      * @return array
      */
     $customized = apply_filters('customize_concurrency_settings', $customized);
     $concurrency_save_results = array();
     foreach (array_keys($customized) as $setting_id) {
         $setting = $this->customize_manager->get_setting($setting_id);
         if (!$setting) {
             continue;
         }
         $concurrency_save_results[$setting_id] = $this->save_previewed_setting($setting_id, array('sanitized_value' => $setting->value(), 'post_status' => 'publish'));
     }
     add_filter('customize_save_response', function ($results) use($concurrency_save_results) {
         $results['concurrency_save_results'] = $concurrency_save_results;
         return $results;
     });
 }
 /**
  * Handles the Ajax request to return the rendered partials for the requested placements.
  *
  * @since 4.5.0
  * @access public
  */
 public function handle_render_partials_request()
 {
     if (!$this->is_render_partials_request()) {
         return;
     }
     /*
      * Note that is_customize_preview() returning true will entail that the
      * user passed the 'customize' capability check and the nonce check, since
      * WP_Customize_Manager::setup_theme() is where the previewing flag is set.
      */
     if (!is_customize_preview()) {
         wp_send_json_error('expected_customize_preview', 403);
     } else {
         if (!isset($_POST['partials'])) {
             wp_send_json_error('missing_partials', 400);
         }
     }
     $partials = json_decode(wp_unslash($_POST['partials']), true);
     if (!is_array($partials)) {
         wp_send_json_error('malformed_partials');
     }
     $this->add_dynamic_partials(array_keys($partials));
     /**
      * Fires immediately before partials are rendered.
      *
      * Plugins may do things like call wp_enqueue_scripts() and gather a list of the scripts
      * and styles which may get enqueued in the response.
      *
      * @since 4.5.0
      *
      * @param WP_Customize_Selective_Refresh $this     Selective refresh component.
      * @param array                          $partials Placements' context data for the partials rendered in the request.
      *                                                 The array is keyed by partial ID, with each item being an array of
      *                                                 the placements' context data.
      */
     do_action('customize_render_partials_before', $this, $partials);
     set_error_handler(array($this, 'handle_error'), error_reporting());
     $contents = array();
     foreach ($partials as $partial_id => $container_contexts) {
         $this->current_partial_id = $partial_id;
         if (!is_array($container_contexts)) {
             wp_send_json_error('malformed_container_contexts');
         }
         $partial = $this->get_partial($partial_id);
         if (!$partial || !$partial->check_capabilities()) {
             $contents[$partial_id] = null;
             continue;
         }
         $contents[$partial_id] = array();
         // @todo The array should include not only the contents, but also whether the container is included?
         if (empty($container_contexts)) {
             // Since there are no container contexts, render just once.
             $contents[$partial_id][] = $partial->render(null);
         } else {
             foreach ($container_contexts as $container_context) {
                 $contents[$partial_id][] = $partial->render($container_context);
             }
         }
     }
     $this->current_partial_id = null;
     restore_error_handler();
     /**
      * Fires immediately after partials are rendered.
      *
      * Plugins may do things like call wp_footer() to scrape scripts output and return them
      * via the {@see 'customize_render_partials_response'} filter.
      *
      * @since 4.5.0
      *
      * @param WP_Customize_Selective_Refresh $this     Selective refresh component.
      * @param array                          $partials Placements' context data for the partials rendered in the request.
      *                                                 The array is keyed by partial ID, with each item being an array of
      *                                                 the placements' context data.
      */
     do_action('customize_render_partials_after', $this, $partials);
     $response = array('contents' => $contents);
     if (defined('WP_DEBUG_DISPLAY') && WP_DEBUG_DISPLAY) {
         $response['errors'] = $this->triggered_errors;
     }
     $setting_validities = $this->manager->validate_setting_values($this->manager->unsanitized_post_values());
     $exported_setting_validities = array_map(array($this->manager, 'prepare_setting_validity_for_js'), $setting_validities);
     $response['setting_validities'] = $exported_setting_validities;
     /**
      * Filters the response from rendering the partials.
      *
      * Plugins may use this filter to inject `$scripts` and `$styles`, which are dependencies
      * for the partials being rendered. The response data will be available to the client via
      * the `render-partials-response` JS event, so the client can then inject the scripts and
      * styles into the DOM if they have not already been enqueued there.
      *
      * If plugins do this, they'll need to take care for any scripts that do `document.write()`
      * and make sure that these are not injected, or else to override the function to no-op,
      * or else the page will be destroyed.
      *
      * Plugins should be aware that `$scripts` and `$styles` may eventually be included by
      * default in the response.
      *
      * @since 4.5.0
      *
      * @param array $response {
      *     Response.
      *
      *     @type array $contents Associative array mapping a partial ID its corresponding array of contents
      *                           for the containers requested.
      *     @type array $errors   List of errors triggered during rendering of partials, if `WP_DEBUG_DISPLAY`
      *                           is enabled.
      * }
      * @param WP_Customize_Selective_Refresh $this     Selective refresh component.
      * @param array                          $partials Placements' context data for the partials rendered in the request.
      *                                                 The array is keyed by partial ID, with each item being an array of
      *                                                 the placements' context data.
      */
     $response = apply_filters('customize_render_partials_response', $response, $this, $partials);
     wp_send_json_success($response);
 }
 /**
  * Update snapshots via AJAX.
  */
 public function handle_update_snapshot_request()
 {
     if (!check_ajax_referer(self::AJAX_ACTION, 'nonce', false)) {
         status_header(400);
         wp_send_json_error('bad_nonce');
     } elseif (!current_user_can('customize')) {
         status_header(403);
         wp_send_json_error('customize_not_allowed');
     } elseif (!isset($_SERVER['REQUEST_METHOD']) || 'POST' !== $_SERVER['REQUEST_METHOD']) {
         // WPCS: input var ok.
         status_header(405);
         wp_send_json_error('bad_method');
     } elseif (empty($this->current_snapshot_uuid)) {
         status_header(400);
         wp_send_json_error('invalid_customize_snapshot_uuid');
     } elseif (0 === count($this->customize_manager->unsanitized_post_values())) {
         status_header(400);
         wp_send_json_error('missing_snapshot_customized');
     }
     if (isset($_POST['status'])) {
         // WPCS: input var ok.
         $status = sanitize_key($_POST['status']);
     } else {
         $status = 'draft';
     }
     if (!in_array($status, array('draft', 'pending', 'future'), true)) {
         status_header(400);
         wp_send_json_error('bad_status');
     }
     if ('future' === $status && !current_user_can('customize_publish')) {
         status_header(400);
         wp_send_json_error('customize_not_allowed');
     }
     $publish_date = isset($_POST['publish_date']) ? $_POST['publish_date'] : '';
     if ('future' === $status) {
         $publish_date_obj = new \DateTime($publish_date);
         $current_date = new \DateTime();
         if (empty($publish_date) || !$publish_date_obj || $publish_date > $current_date) {
             status_header(400);
             wp_send_json_error('bad_schedule_time');
         }
     }
     // Prevent attempting to modify a "locked" snapshot (a published one).
     $post = $this->snapshot->post();
     if ($post && 'publish' === $post->post_status) {
         wp_send_json_error(array('errors' => array('already_published' => array('message' => __('The snapshot has already published so it is locked.', 'customize-snapshots')))));
     }
     // Set the snapshot UUID.
     $post_type = get_post_type_object(Post_Type::SLUG);
     $authorized = $post ? current_user_can($post_type->cap->edit_post, $post->ID) : current_user_can('customize');
     if (!$authorized) {
         status_header(403);
         wp_send_json_error('unauthorized');
     }
     $data = array('errors' => null);
     $settings_data = array_map(function ($value) {
         return compact('value');
     }, $this->customize_manager->unsanitized_post_values());
     $r = $this->snapshot->set($settings_data);
     if (method_exists($this->customize_manager, 'prepare_setting_validity_for_js')) {
         $data['setting_validities'] = array_map(array($this->customize_manager, 'prepare_setting_validity_for_js'), $r['validities']);
     }
     if ($r['errors']) {
         $data['errors'] = $this->prepare_errors_for_response($r['errors']);
         wp_send_json_error($data);
     }
     $args = array('status' => $status);
     $args['edit_date'] = current_time('mysql');
     if (isset($publish_date_obj) && 'future' === $status) {
         $args['post_date'] = $publish_date_obj->format('Y-m-d H:i:s');
         $args['post_date_gmt'] = '0000-00-00 00:00:00';
     } else {
         $args['post_date_gmt'] = $args['post_date'] = '0000-00-00 00:00:00';
     }
     $r = $this->snapshot->save($args);
     $post = $this->snapshot->post();
     if ($post) {
         $data['edit_link'] = get_edit_post_link($post, 'raw');
         $data['snapshot_publish_date'] = $post->post_date;
     }
     if (is_wp_error($r)) {
         $data['errors'] = $this->prepare_errors_for_response($r);
         wp_send_json_error($data);
     }
     wp_send_json_success($data);
 }
 /**
  * Early at the customize_save action, iterate over all settings and check for any that are invalid.
  *
  * If any of the settings are invalid, short-circuit the WP_Customize_Manager::save() call with a
  * call to wp_send_json_error() sending back the invalid_settings.
  *
  * @access public
  * @action customize_save
  *
  * @param \WP_Customize_Manager $wp_customize Customizer manager.
  */
 public function validate_settings(\WP_Customize_Manager $wp_customize)
 {
     global $wp_registered_widget_updates;
     $sanitized_value = null;
     /*
      * Check to see if any of the registered settings are invalid, and for
      * those that are invalid, build an array of the invalid messages.
      */
     $unsanitized_post_values = $wp_customize->unsanitized_post_values();
     foreach ($unsanitized_post_values as $setting_id => $unsanitized_value) {
         $sanitized_value = null;
         $setting = $wp_customize->get_setting($setting_id);
         if (!$setting) {
             continue;
         }
         if (is_null($unsanitized_value)) {
             continue;
         }
         $parsed_widget_id = $wp_customize->widgets->parse_widget_setting_id($setting_id);
         $is_empty_widget_instance = !is_wp_error($parsed_widget_id) && is_array($unsanitized_value) && empty($unsanitized_value) && !empty($wp_customize->widgets);
         if ($is_empty_widget_instance) {
             $instance = null;
             foreach ((array) $wp_registered_widget_updates as $name => $control) {
                 $is_wp_widget = $name === $parsed_widget_id['id_base'] && is_callable($control['callback']) && is_array($control['callback']) && $control['callback'][0] instanceof \WP_Widget;
                 if ($is_wp_widget) {
                     // Note that error suppression is needed because a widget update() callback may have default values.
                     // @todo All Core widgets should have proper defaults if the incoming array is empty.
                     $instance = @call_user_func(array($control['callback'][0], 'update'), array(), array());
                     $sanitized_value = $wp_customize->widgets->sanitize_widget_js_instance($instance);
                     if (!is_null($sanitized_value) && !is_wp_error($sanitized_value)) {
                         $wp_customize->set_post_value($setting_id, $sanitized_value);
                     }
                     break;
                 }
             }
         }
         if (!isset($sanitized_value)) {
             $sanitized_value = $setting->sanitize($unsanitized_value);
         }
         if (is_null($sanitized_value)) {
             $sanitized_value = new \WP_Error('invalid_value', __('Invalid value.', 'customize-setting-validation'));
         }
         if (is_wp_error($sanitized_value)) {
             $this->invalid_settings[$setting_id] = $sanitized_value->get_error_message();
         }
     }
     $invalid_count = count($this->invalid_settings);
     // No invalid settings, do not short-circuit.
     if (0 === $invalid_count) {
         return;
     }
     $response = array('message' => sprintf(_n('There is %d invalid setting.', 'There are %d invalid settings.', $invalid_count, 'customize-setting-validation'), $invalid_count), 'invalid_settings' => $this->invalid_settings);
     /** This filter is documented in wp-includes/class-wp-customize-manager.php */
     $response = apply_filters('customize_save_response', $response, $wp_customize);
     /*
      * This assumes that the method is being called in the context of
      * WP_Customize_Manager::save(), which calls wp_json_send_success()
      * at the end.
      */
     wp_send_json_error($response);
 }
 /**
  * Add the customizer settings and controls.
  *
  * @since 4.3.0
  * @access public
  */
 public function customize_register()
 {
     // Preview settings for nav menus early so that the sections and controls will be added properly.
     $nav_menus_setting_ids = array();
     foreach (array_keys($this->manager->unsanitized_post_values()) as $setting_id) {
         if (preg_match('/^(nav_menu_locations|nav_menu|nav_menu_item)\\[/', $setting_id)) {
             $nav_menus_setting_ids[] = $setting_id;
         }
     }
     $this->manager->add_dynamic_settings($nav_menus_setting_ids);
     if (!$this->manager->doing_ajax('customize_save')) {
         foreach ($nav_menus_setting_ids as $setting_id) {
             $setting = $this->manager->get_setting($setting_id);
             if ($setting) {
                 $setting->preview();
             }
         }
     }
     // Require JS-rendered control types.
     $this->manager->register_panel_type('WP_Customize_Nav_Menus_Panel');
     $this->manager->register_control_type('WP_Customize_Nav_Menu_Control');
     $this->manager->register_control_type('WP_Customize_Nav_Menu_Name_Control');
     $this->manager->register_control_type('WP_Customize_Nav_Menu_Auto_Add_Control');
     $this->manager->register_control_type('WP_Customize_Nav_Menu_Item_Control');
     // Create a panel for Menus.
     $description = '<p>' . __('This panel is used for managing navigation menus for content you have already published on your site. You can create menus and add items for existing content such as pages, posts, categories, tags, formats, or custom links.') . '</p>';
     if (current_theme_supports('widgets')) {
         /* translators: URL to the widgets panel of the customizer */
         $description .= '<p>' . sprintf(__('Menus can be displayed in locations defined by your theme or in <a href="%s">widget areas</a> by adding a &#8220;Custom Menu&#8221; widget.'), "javascript:wp.customize.panel( 'widgets' ).focus();") . '</p>';
     } else {
         $description .= '<p>' . __('Menus can be displayed in locations defined by your theme.') . '</p>';
     }
     $this->manager->add_panel(new WP_Customize_Nav_Menus_Panel($this->manager, 'nav_menus', array('title' => __('Menus'), 'description' => $description, 'priority' => 100)));
     $menus = wp_get_nav_menus();
     // Menu locations.
     $locations = get_registered_nav_menus();
     $num_locations = count(array_keys($locations));
     if (1 == $num_locations) {
         $description = '<p>' . __('Your theme supports one menu. Select which menu you would like to use.') . '</p>';
     } else {
         /* translators: %s: number of menu locations */
         $description = '<p>' . sprintf(_n('Your theme supports %s menu. Select which menu appears in each location.', 'Your theme supports %s menus. Select which menu appears in each location.', $num_locations), number_format_i18n($num_locations)) . '</p>';
     }
     if (current_theme_supports('widgets')) {
         /* translators: URL to the widgets panel of the customizer */
         $description .= '<p>' . sprintf(__('You can also place menus in <a href="%s">widget areas</a> with the &#8220;Custom Menu&#8221; widget.'), "javascript:wp.customize.panel( 'widgets' ).focus();") . '</p>';
     }
     $this->manager->add_section('menu_locations', array('title' => __('Menu Locations'), 'panel' => 'nav_menus', 'priority' => 5, 'description' => $description));
     $choices = array('0' => __('&mdash; Select &mdash;'));
     foreach ($menus as $menu) {
         $choices[$menu->term_id] = wp_html_excerpt($menu->name, 40, '&hellip;');
     }
     foreach ($locations as $location => $description) {
         $setting_id = "nav_menu_locations[{$location}]";
         $setting = $this->manager->get_setting($setting_id);
         if ($setting) {
             $setting->transport = 'postMessage';
             remove_filter("customize_sanitize_{$setting_id}", 'absint');
             add_filter("customize_sanitize_{$setting_id}", array($this, 'intval_base10'));
         } else {
             $this->manager->add_setting($setting_id, array('sanitize_callback' => array($this, 'intval_base10'), 'theme_supports' => 'menus', 'type' => 'theme_mod', 'transport' => 'postMessage', 'default' => 0));
         }
         $this->manager->add_control(new WP_Customize_Nav_Menu_Location_Control($this->manager, $setting_id, array('label' => $description, 'location_id' => $location, 'section' => 'menu_locations', 'choices' => $choices)));
     }
     // Register each menu as a Customizer section, and add each menu item to each menu.
     foreach ($menus as $menu) {
         $menu_id = $menu->term_id;
         // Create a section for each menu.
         $section_id = 'nav_menu[' . $menu_id . ']';
         $this->manager->add_section(new WP_Customize_Nav_Menu_Section($this->manager, $section_id, array('title' => html_entity_decode($menu->name, ENT_QUOTES, get_bloginfo('charset')), 'priority' => 10, 'panel' => 'nav_menus')));
         $nav_menu_setting_id = 'nav_menu[' . $menu_id . ']';
         $this->manager->add_setting(new WP_Customize_Nav_Menu_Setting($this->manager, $nav_menu_setting_id, array('transport' => 'postMessage')));
         // Add the menu contents.
         $menu_items = (array) wp_get_nav_menu_items($menu_id);
         foreach (array_values($menu_items) as $i => $item) {
             // Create a setting for each menu item (which doesn't actually manage data, currently).
             $menu_item_setting_id = 'nav_menu_item[' . $item->ID . ']';
             $value = (array) $item;
             if (empty($value['post_title'])) {
                 $value['title'] = '';
             }
             $value['nav_menu_term_id'] = $menu_id;
             $this->manager->add_setting(new WP_Customize_Nav_Menu_Item_Setting($this->manager, $menu_item_setting_id, array('value' => $value, 'transport' => 'postMessage')));
             // Create a control for each menu item.
             $this->manager->add_control(new WP_Customize_Nav_Menu_Item_Control($this->manager, $menu_item_setting_id, array('label' => $item->title, 'section' => $section_id, 'priority' => 10 + $i)));
         }
         // Note: other controls inside of this section get added dynamically in JS via the MenuSection.ready() function.
     }
     // Add the add-new-menu section and controls.
     $this->manager->add_section(new WP_Customize_New_Menu_Section($this->manager, 'add_menu', array('title' => __('Add a Menu'), 'panel' => 'nav_menus', 'priority' => 999)));
     $this->manager->add_control('new_menu_name', array('label' => '', 'section' => 'add_menu', 'type' => 'text', 'settings' => array(), 'input_attrs' => array('class' => 'menu-name-field', 'placeholder' => __('New menu name'))));
     $this->manager->add_control(new WP_Customize_New_Menu_Control($this->manager, 'create_new_menu', array('section' => 'add_menu', 'settings' => array())));
     $this->manager->add_setting(new WP_Customize_Filter_Setting($this->manager, 'nav_menus_created_posts', array('transport' => 'postMessage', 'type' => 'option', 'default' => array(), 'sanitize_callback' => array($this, 'sanitize_nav_menus_created_posts'))));
 }