Skip to content

Instantly share code, notes, and snippets.

@wpeasy
Created September 2, 2025 19:55
Show Gist options
  • Select an option

  • Save wpeasy/62d4e145a9e8f8ab301330c63315f1d4 to your computer and use it in GitHub Desktop.

Select an option

Save wpeasy/62d4e145a9e8f8ab301330c63315f1d4 to your computer and use it in GitHub Desktop.
ATF Custom Brand Colors
<?php
/**
* WPE Brand bootstrap (users_brand → Brand post → CSS vars)
*
* Rules:
* - Post Type: "Brand"
* - User profile meta: users_brand (int Brand post ID)
* - Brand meta:
* - brand_primary_color -> --brand-primary
* - brand_secondary_color -> --brand-secondary
* - brand_tertiary_color -> --brand-tertiary
*/
add_action( 'init', 'wpe_brand_load_users_brand_global' );
/**
* Load the current user's Brand (by users_brand post ID) into $wpe_brand and emit CSS vars.
*
* @param int $user_id Optional specific user ID; defaults to current user.
* @return array|null
*/
function wpe_brand_load_users_brand_global( $user_id = 0 ) {
global $wpe_brand;
$wpe_brand = null;
// Resolve user
if ( ! $user_id ) {
$user_id = get_current_user_id();
}
if ( ! $user_id ) {
return null;
}
// Read the Brand post ID from user meta (users_brand)
$brand_id = get_user_meta( $user_id, 'users_brand', true );
if ( $brand_id === '' || $brand_id === null ) {
return null;
}
$brand_id = absint( $brand_id );
if ( ! $brand_id ) {
return null;
}
// Load the Brand post (micro-cached)
$brand_post = wpe_brand_find_brand_by_id( $brand_id );
if ( ! ( $brand_post instanceof WP_Post ) ) {
return null;
}
// Core info
$core = array(
'ID' => $brand_post->ID,
'post_type' => $brand_post->post_type,
'status' => $brand_post->post_status,
'slug' => $brand_post->post_name,
'title' => get_the_title( $brand_post ),
'permalink' => get_permalink( $brand_post ),
);
// Post meta (normalized to key => value/array)
$raw_meta = get_post_meta( $brand_post->ID );
$meta = array();
foreach ( $raw_meta as $key => $vals ) {
$meta[ $key ] = count( $vals ) === 1 ? maybe_unserialize( $vals[0] ) : array_map( 'maybe_unserialize', $vals );
}
// Optional: ACF can be heavy; only load if you need it somewhere else.
$acf_fields = array(); // intentionally empty to avoid overhead
$wpe_brand = array(
'core' => $core,
'acf' => $acf_fields,
'meta' => $meta,
'post' => $brand_post,
);
// Emit CSS vars from Brand colors
if ( function_exists( 'wpe_brand_parse_users_brand' ) ) {
wpe_brand_parse_users_brand( $wpe_brand );
} else {
wpe_brand_print_brand_colors_head( $meta );
}
return $wpe_brand;
}
/**
* Find a Brand post by ID, ensuring correct post_type/status.
* Micro-cached per request.
*/
function wpe_brand_find_brand_by_id( int $brand_id ): ?WP_Post {
static $cache = array();
if ( isset( $cache[ $brand_id ] ) ) {
return $cache[ $brand_id ];
}
$post = get_post( $brand_id );
if ( ! ( $post instanceof WP_Post ) ) {
return $cache[ $brand_id ] = null;
}
// Ensure it is a published Brand
if ( $post->post_type !== 'brand' || $post->post_status !== 'publish' ) {
return $cache[ $brand_id ] = null;
}
return $cache[ $brand_id ] = $post;
}
/**
* Hook point to parse the user's Brand structure and print CSS.
*/
function wpe_brand_parse_users_brand( array $wpe_brand ) {
$meta = $wpe_brand['meta'] ?? array();
if ( empty( $meta ) ) {
return;
}
wpe_brand_print_brand_colors_head( $meta );
}
/** Normalize a HEX color (#RGB or #RRGGBB). */
function wpe_brand_normalize_hex_color( $color ): ?string {
if ( function_exists( 'sanitize_hex_color' ) ) {
return sanitize_hex_color( $color ) ?: null;
}
$color = trim( (string) $color );
if ( $color === '' ) return null;
if ( $color[0] !== '#' ) $color = '#' . $color;
if ( preg_match( '/^#([A-Fa-f0-9]{3}|[A-Fa-f0-9]{6})$/', $color ) !== 1 ) {
return null;
}
return strtolower( $color );
}
/** Detect Bricks editor contexts to optionally add !important. */
function wpe_brand_is_bricks_editor(): bool {
if ( function_exists( 'bricks_is_builder' ) && bricks_is_builder() ) {
return true;
}
if ( isset( $_GET['bricks'] ) ) {
$val = strtolower( (string) wp_unslash( $_GET['bricks'] ) );
if ( in_array( $val, array( 'run', 'builder', 'preview' ), true ) ) {
return true;
}
}
return false;
}
/**
* Build a :root CSS block from Brand color meta.
*
* Maps:
* - brand_primary_color -> --brand-primary
* - brand_secondary_color -> --brand-secondary
* - brand_tertiary_color -> --brand-tertiary
*
* Generates exactly 3 steps for -d-, -l-, and -t- series using color-mix in oklch.
* Also emits --brand-*-text as either #000000 or #ffffff (higher WCAG contrast).
* If $important is true, appends !important to each assignment (used in Bricks editor).
*/
function wpe_brand_parse_brand_colors( array $meta, bool $important = false ): string {
$map = array(
'brand_primary_color' => 'primary',
'brand_secondary_color' => 'secondary',
'brand_tertiary_color' => 'tertiary',
);
$var_prefix = apply_filters( 'wpe_brand/brand_color_prefix', '--brand-' );
$steps = apply_filters( 'wpe_brand/brand_color_steps', array( '95', '50', '5' ) ); // exactly 3 steps
$imp = $important ? ' !important' : '';
$lines = array();
foreach ( $map as $meta_key => $slug ) {
if ( empty( $meta[ $meta_key ] ) ) {
continue;
}
$raw = $meta[ $meta_key ];
$val = is_array( $raw ) ? reset( $raw ) : $raw; // meta may be array from get_post_meta()
$hex = wpe_brand_normalize_hex_color( $val );
if ( ! $hex ) {
continue;
}
$base_var = $var_prefix . $slug;
$lines[] = sprintf( '%s: %s%s;', $base_var, $hex, $imp );
// Decide best text color (#000000 or #ffffff) by contrast ratio
$text_hex = wpe_brand_best_text_color_for_bg( $hex );
$lines[] = sprintf( '%s-text: %s%s;', $base_var, $text_hex, $imp );
// Derived series (dark, light, transparent)
$idx = 1;
foreach ( $steps as $keep ) {
$keep = preg_replace( '/[^0-9.]/', '', (string) $keep );
if ( $keep === '' ) {
continue;
}
$lines[] = sprintf(
'%1$s-d-%2$d: color-mix(in oklch, var(%1$s) %3$s%%, black)%4$s;',
$base_var, $idx, $keep, $imp
);
$lines[] = sprintf(
'%1$s-l-%2$d: color-mix(in oklch, var(%1$s) %3$s%%, white)%4$s;',
$base_var, $idx, $keep, $imp
);
$lines[] = sprintf(
'%1$s-t-%2$d: color-mix(in oklch, var(%1$s) %3$s%%, transparent)%4$s;',
$base_var, $idx, $keep, $imp
);
$idx++;
}
}
if ( empty( $lines ) ) return '';
return ":root{\n " . implode( "\n ", $lines ) . "\n}\n";
}
/** Print the :root CSS inside <head> as the last wp_head action. */
function wpe_brand_print_brand_colors_head( array $meta ): void {
$important = wpe_brand_is_bricks_editor();
$css = wpe_brand_parse_brand_colors( $meta, $important );
if ( $css === '' ) return;
add_action(
'wp_head',
static function () use ( $css ) {
echo "\n<style id=\"wpe-brand-colors\">\n" . $css . "</style>\n";
},
PHP_INT_MAX
);
}
/** ---------- Contrast helpers (WCAG 2.x relative luminance) ---------- */
/** Expand #rgb or #rrggbb to [r,g,b] 0–255. */
function wpe_brand_hex_to_rgb( string $hex ): ?array {
$hex = ltrim( strtolower( $hex ), '#' );
if ( strlen( $hex ) === 3 ) {
$r = hexdec( str_repeat( $hex[0], 2 ) );
$g = hexdec( str_repeat( $hex[1], 2 ) );
$b = hexdec( str_repeat( $hex[2], 2 ) );
return array( $r, $g, $b );
}
if ( strlen( $hex ) === 6 ) {
$r = hexdec( substr( $hex, 0, 2 ) );
$g = hexdec( substr( $hex, 2, 2 ) );
$b = hexdec( substr( $hex, 4, 2 ) );
return array( $r, $g, $b );
}
return null;
}
/** Convert 0–255 sRGB to linear (per WCAG). */
function wpe_brand_srgb_to_linear( float $c ): float {
$c = $c / 255;
return ( $c <= 0.03928 ) ? ( $c / 12.92 ) : pow( ( $c + 0.055 ) / 1.055, 2.4 );
}
/** Relative luminance (0..1). */
function wpe_brand_relative_luminance( string $hex ): ?float {
$rgb = wpe_brand_hex_to_rgb( $hex );
if ( ! $rgb ) return null;
list( $r, $g, $b ) = $rgb;
$R = wpe_brand_srgb_to_linear( $r );
$G = wpe_brand_srgb_to_linear( $g );
$B = wpe_brand_srgb_to_linear( $b );
return 0.2126 * $R + 0.7152 * $G + 0.0722 * $B;
}
/** Contrast ratio between two colors (>=1). */
function wpe_brand_contrast_ratio( string $hex1, string $hex2 ): ?float {
$L1 = wpe_brand_relative_luminance( $hex1 );
$L2 = wpe_brand_relative_luminance( $hex2 );
if ( $L1 === null || $L2 === null ) return null;
$light = max( $L1, $L2 );
$dark = min( $L1, $L2 );
return ( $light + 0.05 ) / ( $dark + 0.05 );
}
/** Choose #000000 or #ffffff for best contrast on a background color. */
function wpe_brand_best_text_color_for_bg( string $bg_hex ): string {
$bg_hex = wpe_brand_normalize_hex_color( $bg_hex ) ?: $bg_hex;
$black = '#000000';
$white = '#ffffff';
$c_black = wpe_brand_contrast_ratio( $bg_hex, $black );
$c_white = wpe_brand_contrast_ratio( $bg_hex, $white );
// Default to black if equal or any nulls
if ( $c_white !== null && $c_black !== null ) {
return ( $c_white > $c_black ) ? $white : $black;
}
return $black;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment