user_email ) || ! Preferences::wants_email( $user->ID, $row['action'] ) ) { return false; } $item = Notifications::format( $row ); $community = Settings::get( 'community_name' ); $subject = sprintf( /* translators: 1: Community name, 2: Notification text. */ __( '[%1$s] %2$s', 'spacebay' ), wp_specialchars_decode( $community, ENT_QUOTES ), $item['text'] ); $html = self::render( array( 'community_name' => $community, 'text' => $item['text'], 'excerpt' => $item['excerpt'], 'url' => $item['url'], 'button' => __( 'Open in the community', 'spacebay' ), 'settings_url' => Portal::link( 'account/notifications' ), 'brand_color' => self::readable_color( (string) Settings::get( 'brand_color', '#3f22ff' ) ), 'recipient' => $user->display_name, 'logo_url' => Settings::get( 'logo_id' ) ? (string) wp_get_attachment_image_url( (int) Settings::get( 'logo_id' ), 'medium' ) : '', ) ); $headers = array( 'Content-Type: text/html; charset=UTF-8' ); $from = sanitize_email( (string) Settings::get( 'email_from_address', '' ) ); if ( $from ) { $name = str_replace( array( "\r", "\n", '"' ), '', (string) Settings::get( 'email_from_name', $community ) ); $headers[] = sprintf( 'From: "%s" <%s>', $name, $from ); } /** * Filters a notification email before it is sent. * * @since 1.0.0 * * @param array $email { * Email parts. * * @type string $to Recipient address. * @type string $subject Subject. * @type string $message HTML body. * @type string[] $headers Headers. * } * @param array $row Notification row. */ $email = apply_filters( 'spacebay_notification_email', array( 'to' => $user->user_email, 'subject' => $subject, 'message' => $html, 'headers' => $headers, ), $row ); return (bool) wp_mail( $email['to'], $email['subject'], $email['message'], $email['headers'] ); } /** * Darkens a colour until white text on it has a contrast of at least 4.5:1, * so the email button stays readable with a very light brand colour. * * @param string $hex Hex colour. * @return string Hex colour. */ public static function readable_color( $hex ) { $hex = sanitize_hex_color( $hex ); if ( ! $hex ) { return '#3f22ff'; } $value = ltrim( $hex, '#' ); if ( 3 === strlen( $value ) ) { $value = $value[0] . $value[0] . $value[1] . $value[1] . $value[2] . $value[2]; } $rgb = array_map( 'hexdec', str_split( $value, 2 ) ); $step = 0; while ( $step < 20 && self::contrast_with_white( $rgb ) < 4.5 ) { ++$step; $rgb = array_map( static function ( $channel ) { return (int) round( $channel * 0.94 ); }, $rgb ); } return sprintf( '#%02x%02x%02x', $rgb[0], $rgb[1], $rgb[2] ); } /** * WCAG contrast ratio of white against a colour. * * @param int[] $rgb Red, green and blue from 0 to 255. * @return float */ private static function contrast_with_white( array $rgb ) { $linear = array_map( static function ( $channel ) { $c = $channel / 255; return $c <= 0.03928 ? $c / 12.92 : pow( ( $c + 0.055 ) / 1.055, 2.4 ); }, $rgb ); $luminance = 0.2126 * $linear[0] + 0.7152 * $linear[1] + 0.0722 * $linear[2]; return 1.05 / ( $luminance + 0.05 ); } /** * Renders the email template. Themes can override it by copying * templates/emails/notification.php to your-theme/spacebay/emails/. * * @param array $vars Template variables. * @return string */ public static function render( array $vars ) { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.Found -- $vars is used by the included template. $template = locate_template( array( 'spacebay/emails/notification.php' ) ); $template = $template ? $template : SPACEBAY_PATH . 'templates/emails/notification.php'; ob_start(); include $template; return (string) ob_get_clean(); } }