WP_Customize_Manager::_publish_changeset_values( int $changeset_post_id ): true|WP_Error

Publishes the values of a changeset.

Description

This will publish the values contained in a changeset, even changesets that do not correspond to current manager instance. This is called by _wp_customize_publish_changeset() when a customize_changeset post is transitioned to the publish status. As such, this method should not be called directly and instead wp_publish_post() should be used.

Please note that if the settings in the changeset are for a non-activated theme, the theme must first be switched to (via switch_theme()) before invoking this method.

See also

Parameters

$changeset_post_idintrequired
ID for customize_changeset post. Defaults to the changeset for the current manager instance.

Return

true|WP_Error True or error info.

Source

public function _publish_changeset_values( $changeset_post_id ) {
	global $wpdb;

	$publishing_changeset_data = $this->get_changeset_post_data( $changeset_post_id );
	if ( is_wp_error( $publishing_changeset_data ) ) {
		return $publishing_changeset_data;
	}

	$changeset_post = get_post( $changeset_post_id );

	/*
	 * Temporarily override the changeset context so that it will be read
	 * in calls to unsanitized_post_values() and so that it will be available
	 * on the $wp_customize object passed to hooks during the save logic.
	 */
	$previous_changeset_post_id = $this->_changeset_post_id;
	$this->_changeset_post_id   = $changeset_post_id;
	$previous_changeset_uuid    = $this->_changeset_uuid;
	$this->_changeset_uuid      = $changeset_post->post_name;
	$previous_changeset_data    = $this->_changeset_data;
	$this->_changeset_data      = $publishing_changeset_data;

	// Parse changeset data to identify theme mod settings and user IDs associated with settings to be saved.
	$setting_user_ids   = array();
	$theme_mod_settings = array();
	$namespace_pattern  = '/^(?P<stylesheet>.+?)::(?P<setting_id>.+)$/';
	$matches            = array();
	foreach ( $this->_changeset_data as $raw_setting_id => $setting_params ) {
		$actual_setting_id    = null;
		$is_theme_mod_setting = (
			isset( $setting_params['value'] )
			&&
			isset( $setting_params['type'] )
			&&
			'theme_mod' === $setting_params['type']
			&&
			preg_match( $namespace_pattern, $raw_setting_id, $matches )
		);
		if ( $is_theme_mod_setting ) {
			if ( ! isset( $theme_mod_settings[ $matches['stylesheet'] ] ) ) {
				$theme_mod_settings[ $matches['stylesheet'] ] = array();
			}
			$theme_mod_settings[ $matches['stylesheet'] ][ $matches['setting_id'] ] = $setting_params;

			if ( $this->get_stylesheet() === $matches['stylesheet'] ) {
				$actual_setting_id = $matches['setting_id'];
			}
		} else {
			$actual_setting_id = $raw_setting_id;
		}

		// Keep track of the user IDs for settings actually for this theme.
		if ( $actual_setting_id && isset( $setting_params['user_id'] ) ) {
			$setting_user_ids[ $actual_setting_id ] = $setting_params['user_id'];
		}
	}

	$changeset_setting_values = $this->unsanitized_post_values(
		array(
			'exclude_post_data' => true,
			'exclude_changeset' => false,
		)
	);
	$changeset_setting_ids    = array_keys( $changeset_setting_values );
	$this->add_dynamic_settings( $changeset_setting_ids );

	/**
	 * Fires once the theme has switched in the Customizer, but before settings
	 * have been saved.
	 *
	 * @since 3.4.0
	 *
	 * @param WP_Customize_Manager $manager WP_Customize_Manager instance.
	 */
	do_action( 'customize_save', $this );

	/*
	 * Ensure that all settings will allow themselves to be saved. Note that
	 * this is safe because the setting would have checked the capability
	 * when the setting value was written into the changeset. So this is why
	 * an additional capability check is not required here.
	 */
	$original_setting_capabilities = array();
	foreach ( $changeset_setting_ids as $setting_id ) {
		$setting = $this->get_setting( $setting_id );
		if ( $setting && ! isset( $setting_user_ids[ $setting_id ] ) ) {
			$original_setting_capabilities[ $setting->id ] = $setting->capability;
			$setting->capability                           = 'exist';
		}
	}

	$original_user_id = get_current_user_id();
	foreach ( $changeset_setting_ids as $setting_id ) {
		$setting = $this->get_setting( $setting_id );
		if ( $setting ) {
			/*
			 * Set the current user to match the user who saved the value into
			 * the changeset so that any filters that apply during the save
			 * process will respect the original user's capabilities. This
			 * will ensure, for example, that KSES won't strip unsafe HTML
			 * when a scheduled changeset publishes via WP Cron.
			 */
			if ( isset( $setting_user_ids[ $setting_id ] ) ) {
				wp_set_current_user( $setting_user_ids[ $setting_id ] );
			} else {
				wp_set_current_user( $original_user_id );
			}

			$setting->save();
		}
	}
	wp_set_current_user( $original_user_id );

	// Update the stashed theme mod settings, removing the active theme's stashed settings, if activated.
	if ( did_action( 'switch_theme' ) ) {
		$other_theme_mod_settings = $theme_mod_settings;
		unset( $other_theme_mod_settings[ $this->get_stylesheet() ] );
		$this->update_stashed_theme_mod_settings( $other_theme_mod_settings );
	}

	/**
	 * Fires after Customize settings have been saved.
	 *
	 * @since 3.6.0
	 *
	 * @param WP_Customize_Manager $manager WP_Customize_Manager instance.
	 */
	do_action( 'customize_save_after', $this );

	// Restore original capabilities.
	foreach ( $original_setting_capabilities as $setting_id => $capability ) {
		$setting = $this->get_setting( $setting_id );
		if ( $setting ) {
			$setting->capability = $capability;
		}
	}

	// Restore original changeset data.
	$this->_changeset_data    = $previous_changeset_data;
	$this->_changeset_post_id = $previous_changeset_post_id;
	$this->_changeset_uuid    = $previous_changeset_uuid;

	/*
	 * Convert all autosave revisions into their own auto-drafts so that users can be prompted to
	 * restore them when a changeset is published, but they had been locked out from including
	 * their changes in the changeset.
	 */
	$revisions = wp_get_post_revisions( $changeset_post_id, array( 'check_enabled' => false ) );
	foreach ( $revisions as $revision ) {
		if ( str_contains( $revision->post_name, "{$changeset_post_id}-autosave" ) ) {
			$wpdb->update(
				$wpdb->posts,
				array(
					'post_status' => 'auto-draft',
					'post_type'   => 'customize_changeset',
					'post_name'   => wp_generate_uuid4(),
					'post_parent' => 0,
				),
				array(
					'ID' => $revision->ID,
				)
			);
			clean_post_cache( $revision->ID );
		}
	}

	return true;
}

Hooks

do_action( ‘customize_save’, WP_Customize_Manager $manager )

Fires once the theme has switched in the Customizer, but before settings have been saved.

do_action( ‘customize_save_after’, WP_Customize_Manager $manager )

Fires after Customize settings have been saved.

Changelog

VersionDescription
4.7.0Introduced.

User Contributed Notes

You must log in before being able to contribute a note or feedback.