39 'multipart/mixed' => array(self::LEVEL_TOP, self::LEVEL_MIXED),
40 'multipart/alternative' => array(self::LEVEL_MIXED, self::LEVEL_ALTERNATIVE),
41 'multipart/related' => array(self::LEVEL_ALTERNATIVE, self::LEVEL_RELATED)
66 'multipart/related' => 3
86 $this->_cacheKey = uniqid();
87 $this->_cache = $cache;
88 $this->_headers = $headers;
90 $this->_headers->defineOrdering(
91 array(
'Content-Type',
'Content-Transfer-Encoding')
107 $this->_compoundLevelFilters = array(
108 (self::LEVEL_ALTERNATIVE + self::LEVEL_RELATED) => array(
109 self::LEVEL_ALTERNATIVE => array(
110 'text/plain' => self::LEVEL_ALTERNATIVE,
111 'text/html' => self::LEVEL_RELATED
166 $this->_userContentType =
$type;
215 $this->_headers->addTextHeader(
'Content-Description', $description);
236 $this->_maxLineLength = $length;
254 public function setChildren(array $children, $compoundLevel = null)
258 $compoundLevel = isset($compoundLevel)
263 $immediateChildren = array();
264 $grandchildren = array();
267 foreach ($children as $child)
270 if (empty($immediateChildren))
272 $immediateChildren = array($child);
277 if ($nextLevel == $level)
279 $immediateChildren[] = $child;
281 elseif ($level < $nextLevel)
284 $grandchildren = array_merge($grandchildren, $immediateChildren);
286 $immediateChildren = array($child);
290 $grandchildren[] = $child;
295 if (!empty($immediateChildren))
301 foreach ($this->_compositeRanges as $mediaType => $range)
303 if ($lowestLevel > $range[0]
304 && $lowestLevel <= $range[1])
306 $newContentType = $mediaType;
312 if (!empty($grandchildren))
315 $subentity->_setNestingLevel($lowestLevel);
316 $subentity->setChildren($grandchildren, $compoundLevel);
317 array_unshift($immediateChildren, $subentity);
321 $this->_immediateChildren = $immediateChildren;
322 $this->_children = $children;
347 public function setBody($body, $contentType = null)
349 if ($body !== $this->_body)
354 $this->_body = $body;
355 if (isset($contentType))
377 if ($encoder !== $this->_encoder)
382 $this->_encoder = $encoder;
394 if (!isset($this->_boundary))
396 $this->_boundary =
'_=_swift_v4_' . time() . uniqid() .
'_=_';
409 $this->_boundary = $boundary;
439 $string = $this->_headers->toString();
440 if (isset($this->_body) && empty($this->_immediateChildren))
442 if ($this->_cache->hasKey($this->_cacheKey,
'body'))
444 $body = $this->_cache->getString($this->_cacheKey,
'body');
448 $body =
"\r\n" . $this->_encoder->encodeString($this->
getBody(), 0,
451 $this->_cache->setString($this->_cacheKey,
'body', $body,
458 if (!empty($this->_immediateChildren))
460 foreach ($this->_immediateChildren as $child)
462 $string .=
"\r\n\r\n--" . $this->
getBoundary() .
"\r\n";
463 $string .= $child->toString();
465 $string .=
"\r\n\r\n--" . $this->
getBoundary() .
"--\r\n";
489 $is->
write($this->_headers->toString());
492 if (empty($this->_immediateChildren))
494 if (isset($this->_body))
496 if ($this->_cache->hasKey($this->_cacheKey,
'body'))
498 $this->_cache->exportToByteStream($this->_cacheKey,
'body', $is);
502 $cacheIs = $this->_cache->getInputByteStream($this->_cacheKey,
'body');
512 $this->_body->setReadPointer(0);
514 $this->_encoder->encodeByteStream($this->_body, $is, 0,
520 $is->
write($this->_encoder->encodeString(
533 if (!empty($this->_immediateChildren))
535 foreach ($this->_immediateChildren as $child)
538 $child->toByteStream($is);
558 if ($this->_headers->has(
$field))
560 return $this->_headers->get(
$field)->getFieldBodyModel();
569 if ($this->_headers->has(
$field))
571 $this->_headers->get(
$field)->setFieldBodyModel($model);
585 if ($this->_headers->has(
$field))
587 return $this->_headers->get(
$field)->getParameter($parameter);
596 if ($this->_headers->has(
$field))
598 $this->_headers->get(
$field)->setParameter($parameter, $value);
612 if (count($this->_immediateChildren))
617 $this->_headers->remove(
'Content-Transfer-Encoding');
639 $this->_cache->clearKey($this->_cacheKey,
'body');
648 $idLeft = time() .
'.' . uniqid();
649 $idRight = !empty($_SERVER[
'SERVER_NAME'])
650 ? $_SERVER[
'SERVER_NAME']
652 return $idLeft .
'@' . $idRight;
660 while (
false !== $bytes = $os->
read(8192))
671 $this->_headers->addTextHeader(
'Content-Transfer-Encoding', $encoding);
678 '/^[a-z0-9\'\(\)\+_\-,\.\/:=\?\ ]{0,69}[a-z0-9\'\(\)\+_\-,\.\/:=\?]$/Di',
689 $this->_headers->addParameterizedHeader(
'Content-Type',
$type);
695 $this->_nestingLevel = $level;
701 foreach ($children as $child)
703 $level |= $child->getNestingLevel();
711 foreach ($this->_compoundLevelFilters as $bitmask => $rules)
713 if (($compoundLevel & $bitmask) === $bitmask)
715 $filter = $rules + $filter;
719 $realLevel = $child->getNestingLevel();
720 $lowercaseType = strtolower($child->getContentType());
722 if (isset($filter[$realLevel])
723 && isset($filter[$realLevel][$lowercaseType]))
725 return $filter[$realLevel][$lowercaseType];
735 return new self($this->_headers->newInstance(),
741 foreach ($this->_immediateChildren as $child)
743 $child->encoderChanged($encoder);
749 $this->_encoder->charsetChanged($charset);
750 $this->_headers->charsetChanged($charset);
751 foreach ($this->_immediateChildren as $child)
753 $child->charsetChanged($charset);
760 foreach ($this->_immediateChildren as $child)
763 if ($child->getNestingLevel() == self::LEVEL_ALTERNATIVE)
773 usort($this->_immediateChildren, array($this,
'_childSortAlgorithm'));
779 $typePrefs = array();
781 strtolower($a->getContentType()),
782 strtolower($b->getContentType())
784 foreach ($types as
$type)
786 $typePrefs[] = (array_key_exists($type, $this->_alternativePartOrder))
787 ? $this->_alternativePartOrder[$type]
788 : (max($this->_alternativePartOrder) + 1);
790 return ($typePrefs[0] >= $typePrefs[1]) ? 1 : -1;
800 $this->_cache->clearAll($this->_cacheKey);