Referenced secret key names (unique, in order of appearance) */ public static function referencedKeys(?string $value): array { if (blank($value)) { return []; } preg_match_all(self::PATTERN, $value, $matches); return array_values(array_unique($matches[1])); } /** * Replace every reference with its value from the secrets map. * Keys missing from the map are left as-is — collect them first with * missingKeys() and fail before calling substitute(). * * @param array $secrets */ public static function substitute(string $value, array $secrets): string { return preg_replace_callback( self::PATTERN, fn (array $matches) => array_key_exists($matches[1], $secrets) ? $secrets[$matches[1]] : $matches[0], $value, ); } /** * @param array $secrets * @return list */ public static function missingKeys(?string $value, array $secrets): array { return array_values(array_filter( self::referencedKeys($value), fn (string $key) => ! array_key_exists($key, $secrets), )); } }