Allow filtering globalVariables just-in-time

This might only apply to inlined styles.

Was making an attempt defining global variables and conditionally overloading them via ACF fields when set.

Currently this is hit/miss.

  1. They are loaded directly via get_option( … ) in multiple places separately, at different points in the WP load process. We tried overloading Database::$global_data['globalVariables'] directly in wp action, but this fails because of direct get_option usage elsewhere.
  2. They are initialized on theme load via Database::__construct(), which is too soon to be able to utilize any ACF variables or query conditionals for a given post. We tried filtering option_bricks_global_variables, doesn’t work for this reason.

Proper solution might be to add an official getter method somewhere (in Database?) for those variables which pulls from the Database::$global_data['globalVariables'] and runs it through a new filter such as bricks/get_global_variables.

Any time the globalVariables are to be used, such as rendering inline or to CSS, the new getter should be called, as late as possible (after wp and query setup), so that conditionals and ACF get_field can work.

Will post the code we dabbled with in follow up comment.

Temporary solution, in leue of being able to properly filter them: Allow filtering globalVariables just-in-time - #3 by danieliser

Methods used to get overloads if exist:

/**
 * Get the current post ID.
 *
 * @return int|null
 */
function pm_bricks_get_current_post_id() {
	global $post;

	$post_id = isset( $post ) ? $post->ID : null;

	if ( ( bricks_is_builder_iframe() || isset( $_GET['bricks_preview'] ) ) && class_exists( '\Bricks\Helpers' ) ) {
		$preview_post_id = \Bricks\Helpers::get_template_setting( 'templatePreviewPostId', $post_id );

		if ( $preview_post_id ) {
			$post_id = $preview_post_id;
		}
	}

	return $post_id;
}


/**
 * Retrieve custom header variables based on ACF fields.
 *
 * @return array<string,string>
 */
function pm_get_template_header_variables() {
	if ( ! function_exists( 'get_field' ) ) {
		return [];
	}

	// Ensure we're on a single post or page
	$post_id = pm_bricks_get_current_post_id();

	if ( ! $post_id ) {
		return [];
	}

	// Retrieve the color scheme field
	$color_scheme = get_field( 'header_color_scheme', $post_id );

	$variables = [];

	// Proceed only if the color scheme is set to 'custom'
	// Adjust the condition if your 'custom' value differs
	if ( '' === $color_scheme ) {
		// Retrieve individual color fields
		$header_background_color  = get_field( 'header_background_color', $post_id );
		$header_text_color        = get_field( 'header_text_color', $post_id );
		$header_accent_color      = get_field( 'header_accent_color', $post_id );
		$header_accent_text_color = get_field( 'header_accent_text_color', $post_id );

		$variables = [
			// Foreach if its falsy, set to null.
			'header-background-color'  => $header_background_color ? $header_background_color : null,
			'header-text-color'        => $header_text_color ? $header_text_color : null,
			'header-accent-color'      => $header_accent_color ? $header_accent_color : null,
			'header-accent-text-color' => $header_accent_text_color ? $header_accent_text_color : null,
		];
	}

	return array_filter( $variables );
}

Modify Database::$global_data

add_action('wp', 'pm_modify_bricks_css_global_variables', 0);
/**
 * Modify the global variables used in the Bricks CSS.
 *
 * @return void
 */
function pm_modify_bricks_css_global_variables() {
	if ( class_exists( '\Bricks\Database' ) ) {
		$overrides = pm_get_template_header_variables();

		if ( ! empty( $overrides ) ) {
			/**
			 * Global variables.
			 *
			 * @var array{
			 *  id: string,
			 *  name: string,
			 *  value: string,
			 * }[] $globalVariables
			 */
			$global_variables = \Bricks\Database::$global_data['globalVariables'];

			foreach ( $global_variables as $key => $val ) {
				$name = $val['name'];

				if ( array_key_exists( $name, $overrides ) ) {
					$global_variables[ $key ]['value'] = $overrides[ $name ];
				}
			}

			\Bricks\Database::$global_data['globalVariables'] = $global_variables;
		}
	}
}

Filter WP Option

add_filter( 'option_bricks_global_variables', 'pm_bricks_filter_global_variables_option' );

/**
 * Add custom global variables to the Bricks global variables option.
 *
 * @param array{
 *  id: string,
 *  name: string,
 *  value: string,
 * }[] $value The global variables.
 *
 * @return array{
 *  id: string,
 *  name: string,
 *  value: string,
 * }[]
 */
function pm_bricks_filter_global_variables_option( $value ) {
	if ( ! $value ) {
		return $value;
	}

	if ( ! is_array( $value ) ) {
		$value = [];
	}

	if ( ! did_action( 'wp' ) ) {
		return $value;
	}

	$overrides = pm_get_template_header_variables();

	if ( ! empty( $overrides ) ) {
		foreach ( $value as $key => $val ) {
			$name = $val['name'];

			if ( array_key_exists( $name, $overrides ) ) {
				$value[ $key ]['value'] = $overrides[ $name ];
			}
		}
	}

	return $value;
}

Temporary workaround solution

Absent a proper filter the best way I came up with was to set the global variables to look for an override in their assignments. So in the global variable panel I set them like

header-background-color

var( --header-background-color-override, var(--base) )

header-text-color

var( --header-text-color-override, var(--white) )

Rendering Overrides

add_action( 'wp_head', 'pm_render_custom_css_variables', 2 );

/**
 * Outputs custom header styles based on ACF fields.
 *
 * @return void
 */
function pm_render_custom_css_variables() {
	if ( is_admin() ) {
		return;
	}

	$overrides = pm_get_template_header_variables();

	// Check if at least one custom color field is set
	if ( ! empty( $overrides ) ) {
		// Start building the CSS output
		$custom_css = "<style id=\"custom-header-stylings\" type=\"text/css\">\n:root {\n";

		$custom_css .= "/* Custom Stylings Based on ACF Template Fields */ \n";

		// Loop through each variable and append it
		foreach ( $overrides as $name => $value ) {
			// Set the override variable
			$safe_value  = esc_attr( $value );
			$custom_css .= "    --$name-override: {$safe_value};\n";
		}

		$custom_css .= "}\n</style>\n";

		// Output the custom CSS
		echo $custom_css;
	}
}

This will render out the overloads needed on a per post basis. This should even work with file based assets rather than inline.