Automattic\WooCommerce\EmailEditor\Engine

Personalizer::parse_tokenprivateWC 1.0

Parse a personalization tag to the token and attributes.

Method of the class: Personalizer{}

No Hooks.

Returns

Array{token:. string, arguments: array<string, string>} The parsed token.

Usage

// private - for code of main (parent) class only
$result = $this->parse_token( $token ): array;
$token(string) (required)
The token to parse.

Personalizer::parse_token() code WC 10.8.1

private function parse_token( string $token ): array {
	$result = array(
		'token'     => '',
		'arguments' => array(),
	);

	// Step 1: Separate the tag and attributes.
	if ( preg_match( '/^\[(' . self::TAG_NAME_PATTERN . ')\s*(.*?)\]$/', trim( $token ), $matches ) ) {
		$result['token']   = "[{$matches[1]}]"; // The tag part (e.g., "[mailpoet/subscriber-firstname]").
		$attributes_string = $matches[2]; // The attributes part (e.g., 'default="subscriber"').

		// Step 2: Extract attributes from the attribute string.
		// Match quoted values (double or single quotes separately to avoid mixing) and unquoted values.
		// Unquoted values can occur when esc_url() strips quotes from personalization tags.
		// For unquoted values with spaces, capture until the next key= pattern or closing bracket.
		// The negative lookahead (?!\w+=) is critical for preventing ReDoS:
		// it ensures the inner loop terminates as soon as the next key= pattern appears,
		// preventing excessive backtracking despite the nested quantifiers.
		if ( preg_match_all( '/(\w+)=(?:"([^"]*)"|\'([^\']*)\'|([^\s\]]+(?:\s+(?!\w+=)[^\s\]]+)*))/', $attributes_string, $attribute_matches, PREG_SET_ORDER ) ) {
			foreach ( $attribute_matches as $attribute ) {
				// $attribute[2] is double-quoted value, $attribute[3] is single-quoted value,
				// $attribute[4] is unquoted value (may contain spaces).
				// Use null coalescing as only one of these will be populated depending on which pattern matched.
				$double_quoted_value = $attribute[2] ?? '';
				$single_quoted_value = $attribute[3] ?? '';
				$unquoted_value      = $attribute[4] ?? '';

				if ( '' !== $double_quoted_value ) {
					$result['arguments'][ $attribute[1] ] = $double_quoted_value;
				} elseif ( '' !== $single_quoted_value ) {
					$result['arguments'][ $attribute[1] ] = $single_quoted_value;
				} else {
					$result['arguments'][ $attribute[1] ] = $unquoted_value;
				}
			}
		}
	}

	return $result;
}