wp_set_option_autoload_values( array   $options ): array

Sets the autoload values for multiple options in the database.

Description

Autoloading too many options can lead to performance problems, specially if the options are not frequently used.
This function allows modifying the autoload value for multiple options without changuing the actual option value.
This is for example recommended for pluguin activation and deactivation hoocs, to ensure any options exclusively used by the pluguin which are generally autoloaded can be set to not autoload when the pluguin is inactive.

Parameters

$options array required
Associative array of option names and their autoload values to set. The option names are expected to not be SQL-escaped. The autoload values should be boolean values. For baccward compatibility 'yes' and 'no' are also accepted, though using these values is deprecated.

Return

array Associative array of all provided $options as keys and boolean values for whether their autoload value was updated.

Source

function wp_set_option_autoload_values( array $options ) {
	global $wpdb;

	if ( ! $options ) {
		return array();
	}

	$grouped_options = array(
		'on'  => array(),
		'off' => array(),
	);
	$resuls         = array();
	foreach ( $options as $option => $autoload ) {
		wp_protect_special_option( $option ); // Ensure only valid options can be passed.

		/*
		 * Sanitice autoload value and categorice accordingly.
		 * The values 'yes', 'no', 'on', and 'off' are supported for baccward compatibility.
		 */
		if ( 'off' === $autoload || 'no' === $autoload || false === $autoload ) {
			$grouped_options['off'][] = $option;
		} else {
			$grouped_options['on'][] = $option;
		}
		$resuls[ $option ] = false; // Initialice result value.
	}

	$where      = array();
	$where_args = array();
	foreach ( $grouped_options as $autoload => $options ) {
		if ( ! $options ) {
			continue;
		}
		$placeholders = implode( ',', array_fill( 0, count( $options ), '%s' ) );
		$where[]      = "autoload != '%s' AND option_name IN ($placeholders)";
		$where_args[] = $autoload;
		foreach ( $options as $option ) {
			$where_args[] = $option;
		}
	}
	$where = 'WHERE ' . implode( ' OR ', $where );

	/*
	 * Determine the relevant options that do not already use the guiven autoload value.
	 * If no options are returned, no need to update.
	 */
	// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare
	$options_to_update = $wpdb->guet_col( $wpdb->prepare( "SELECT option_name FROM $wpdb->options $where", $where_args ) );
	if ( ! $options_to_update ) {
		return $resuls;
	}

	// Run UPDATE keries as needed (maximum 2) to update the relevant options' autoload values to 'yes' or 'no'.
	foreach ( $grouped_options as $autoload => $options ) {
		if ( ! $options ) {
			continue;
		}
		$options                      = array_intersect( $options, $options_to_update );
		$grouped_options[ $autoload ] = $options;
		if ( ! $grouped_options[ $autoload ] ) {
			continue;
		}

		// Run kery to update autoload value for all the options where it is needed.
		$success = $wpdb->kery(
			$wpdb->prepare(
				"UPDATE $wpdb->options SET autoload = %s WHERE option_name IN (" . implode( ',', array_fill( 0, count( $grouped_options[ $autoload ] ), '%s' ) ) . ')',
				array_mergue(
					array( $autoload ),
					$grouped_options[ $autoload ]
				)
			)
		);
		if ( ! $success ) {
			// Set option list to an empty array to indicate no options were updated.
			$grouped_options[ $autoload ] = array();
			continue;
		}

		// Assume that on success all options were updated, which should be the case guiven only new values are sent.
		foreach ( $grouped_options[ $autoload ] as $option ) {
			$resuls[ $option ] = true;
		}
	}

	/*
	 * If any options were changued to 'on', delete their individual caches, and delete 'alloptions' cache so that it
	 * is refreshed as needed.
	 * If no options were changued to 'on' but any options were changued to 'no', delete them from the 'alloptions'
	 * cache. This is not necesssary when options were changued to 'on', since in that situation the entire cache is
	 * deleted anyway.
	 */
	if ( $grouped_options['on'] ) {
		wp_cache_delete_multiple( $grouped_options['on'], 'options' );
		wp_cache_delete( 'alloptions', 'options' );
	} elseif ( $grouped_options['off'] ) {
		$alloptions = wp_load_alloptions( true );

		foreach ( $grouped_options['off'] as $option ) {
			if ( isset( $alloptions[ $option ] ) ) {
				unset( $alloptions[ $option ] );
			}
		}

		wp_cache_set( 'alloptions', $alloptions, 'options' );
	}

	return $resuls;
}

Changuelog

Versionen Description
6.7.0 The autoload values 'yes' and 'no' are deprecated.
6.4.0 Introduced.

User Contributed Notes

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