diff --git a/include/class.mailer.php b/include/class.mailer.php index c398df9f5ccf26f8bca4a8d16a21009fbc52cdf6..22d8eaf1ad306cffa710d3c71ac5d8924e3cf0be 100644 --- a/include/class.mailer.php +++ b/include/class.mailer.php @@ -386,6 +386,17 @@ class Mailer { } $mime = new Mail_mime($eol); + // Add in extra attachments, if any from template variables + if ($message instanceof TextWithExtras + && ($files = $message->getFiles()) + ) { + foreach ($files as $F) { + $file = $F->getFile(); + $mime->addAttachment($file->getData(), + $file->getType(), $file->getName(), false); + } + } + // If the message is not explicitly declared to be a text message, // then assume that it needs html processing to create a valid text // body diff --git a/include/class.thread.php b/include/class.thread.php index b5d8bdbd4ee23b81b7767274e42c9d46120e813f..9a2dde5b9223ba7cfa98eff0a779c7cff863d9bf 100644 --- a/include/class.thread.php +++ b/include/class.thread.php @@ -793,17 +793,6 @@ implements TemplateVariable { return $str; } - /* Returns file names with id as key */ - function getFiles() { - - $files = array(); - foreach($this->attachments as $attachment) - $files[$attachment->file_id] = $attachment->file->name; - - return $files; - } - - /* save email info * TODO: Refactor it to include outgoing emails on responses. */ @@ -851,17 +840,16 @@ implements TemplateVariable { } function getVar($tag) { - global $cfg; - - if($tag && is_callable(array($this, 'get'.ucfirst($tag)))) + if ($tag && is_callable(array($this, 'get'.ucfirst($tag)))) return call_user_func(array($this, 'get'.ucfirst($tag))); switch(strtolower($tag)) { case 'create_date': - // XXX: Consider preferences of receiving user - return Format::datetime($this->getCreateDate(), true, 'UTC'); + return new FormattedDate($this->getCreateDate()); case 'update_date': - return Format::datetime($this->getUpdateDate(), true, 'UTC'); + return new FormattedDate($this->getUpdateDate()); + case 'files': + throw new OOBContent(OOBContent::FILES, $this->attachments->all()); } return false; diff --git a/include/class.variable.php b/include/class.variable.php index e026800864645d5de2f9a688601650d5565b7bd8..a7fc036d1f13ee54be49c89e7ac0d4fd546a26c2 100644 --- a/include/class.variable.php +++ b/include/class.variable.php @@ -21,8 +21,9 @@ class VariableReplacer { var $start_delim; var $end_delim; - var $objects; - var $variables; + var $objects = array(); + var $variables = array(); + var $extras = array(); var $errors; @@ -30,9 +31,6 @@ class VariableReplacer { $this->start_delim = $start_delim; $this->end_delim = $end_delim; - - $this->objects = array(); - $this->variables = array(); } function setError($error) { @@ -97,13 +95,21 @@ class VariableReplacer { function replaceVars($input) { + // Preserve existing extras + if ($input instanceof TextWithExtras) + $this->extras = $input->extras; + if($input && is_array($input)) return array_map(array($this, 'replaceVars'), $input); if(!($vars=$this->_parse($input))) return $input; - return str_replace(array_keys($vars), array_values($vars), $input); + $text = str_replace(array_keys($vars), array_values($vars), $input); + if ($this->extras) { + return new TextWithExtras($text, $this->extras); + } + return $text; } function _resolveVar($var) { @@ -113,9 +119,18 @@ class VariableReplacer { return $this->variables[$var]; $parts = explode('.', $var, 2); - if($parts && ($obj=$this->getObj($parts[0]))) - return $this->getVar($obj, $parts[1]); - elseif($parts[0] && @isset($this->variables[$parts[0]])) { //root override + try { + if ($parts && ($obj=$this->getObj($parts[0]))) + return $this->getVar($obj, $parts[1]); + } + catch (OOBContent $content) { + $type = $content->getType(); + $existing = @$this->extras[$type] ?: array(); + $this->extras[$type] = array_merge($existing, $content->getContent()); + return ''; + } + + if ($parts[0] && @isset($this->variables[$parts[0]])) { //root override if (is_array($this->variables[$parts[0]]) && isset($this->variables[$parts[0]][$parts[1]])) return $this->variables[$parts[0]][$parts[1]]; @@ -299,6 +314,52 @@ class PlaceholderList } } +/** + * Exception used in the variable replacement process to indicate non text + * content (such as attachments) + */ +class OOBContent extends Exception { + var $type; + var $content; + + const FILES = 'files'; + + function __construct($type, $content) { + $this->type = $type; + $this->content = $content; + } + + function getType() { return $this->type; } + function getContent() { return $this->content; } +} + +class TextWithExtras { + var $text = ''; + var $extras; + + function __construct($text, array $extras) { + $this->setText($text); + $this->extras = $extras; + } + + function setText($text) { + try { + $this->text = (string) $text; + } + catch (Exception $e) { + throw new InvalidArgumentException('String type is required', 0, $e); + } + } + + function __toString() { + return $this->text; + } + + function getFiles() { + return $this->extras[OOBContent::FILES]; + } +} + interface TemplateVariable { // function asVar(); — not absolutely required // function getVar($name); — not absolutely required