/**
  * Render a message.
  *
  * @param string $name
  *   The name previously registered with addMessage().
  * @param TokenRow|int $row
  *   The object or ID for the row previously registered with addRow().
  * @return string
  *   Fully rendered message, with tokens merged.
  */
 public function render($name, $row)
 {
     if (!is_object($row)) {
         $row = $this->getRow($row);
     }
     $message = $this->getMessage($name);
     $row->fill($message['format']);
     $useSmarty = !empty($row->context['smarty']);
     // FIXME preg_callback.
     $tokens = $this->rowValues[$row->tokenRow][$message['format']];
     $flatTokens = array();
     \CRM_Utils_Array::flatten($tokens, $flatTokens, '', '.');
     $filteredTokens = array();
     foreach ($flatTokens as $k => $v) {
         $filteredTokens['{' . $k . '}'] = $useSmarty ? \CRM_Utils_Token::tokenEscapeSmarty($v) : $v;
     }
     $event = new TokenRenderEvent($this);
     $event->message = $message;
     $event->context = $row->context;
     $event->row = $row;
     $event->string = strtr($message['string'], $filteredTokens);
     $this->dispatcher->dispatch(Events::TOKEN_RENDER, $event);
     return $event->string;
 }