partStreamContainer = $streamContainer; $this->parent = $parent; $this->observers = new SplObjectStorage(); } public function attach(SplObserver $observer) : void { $this->observers->offsetSet($observer); } public function detach(SplObserver $observer) : void { $this->observers->offsetUnset($observer); } public function notify() : void { foreach ($this->observers as $observer) { $observer->update($this); } if ($this->parent !== null) { $this->parent->notify(); } } public function getParent() : ?IMimePart { return $this->parent; } public function hasContent() : bool { return $this->partStreamContainer->hasContent(); } public function getFilename() : ?string { return null; } public function setCharsetOverride(string $charsetOverride, bool $onlyIfNoCharset = false) : static { if (!$onlyIfNoCharset || $this->getCharset() === null) { $this->charsetOverride = $charsetOverride; } return $this; } public function getContentStream(string $charset = MailMimeParser::DEFAULT_CHARSET) : ?MessagePartStreamDecorator { if ($this->hasContent()) { $tr = ($this->ignoreTransferEncoding) ? '' : $this->getContentTransferEncoding(); $ch = $this->charsetOverride ?? $this->getCharset(); return $this->partStreamContainer->getContentStream( $this, $tr, $ch, $charset ); } return null; } public function getBinaryContentStream() : ?MessagePartStreamDecorator { if ($this->hasContent()) { $tr = ($this->ignoreTransferEncoding) ? '' : $this->getContentTransferEncoding(); return $this->partStreamContainer->getBinaryContentStream($this, $tr); } return null; } public function getBinaryContentResourceHandle() : mixed { $stream = $this->getBinaryContentStream(); if ($stream !== null) { return StreamWrapper::getResource($stream); } return null; } public function saveContent($filenameResourceOrStream) : static { $resourceOrStream = $filenameResourceOrStream; if (\is_string($filenameResourceOrStream)) { $resourceOrStream = \fopen($filenameResourceOrStream, 'w+'); } $stream = Utils::streamFor($resourceOrStream); Utils::copyToStream($this->getBinaryContentStream(), $stream); if (!\is_string($filenameResourceOrStream) && !($filenameResourceOrStream instanceof StreamInterface)) { // only detach if it wasn't a string or StreamInterface, so the // fopen call can be properly closed if it was $stream->detach(); } return $this; } public function getContent(string $charset = MailMimeParser::DEFAULT_CHARSET) : ?string { $stream = $this->getContentStream($charset); if ($stream !== null) { return $stream->getContents(); } return null; } public function attachContentStream(StreamInterface $stream, string $streamCharset = MailMimeParser::DEFAULT_CHARSET) : static { $ch = $this->charsetOverride ?? $this->getCharset(); if ($ch !== null && $streamCharset !== $ch) { $this->charsetOverride = $streamCharset; } $this->ignoreTransferEncoding = true; $this->partStreamContainer->setContentStream($stream); $this->notify(); return $this; } public function detachContentStream() : static { $this->partStreamContainer->setContentStream(null); $this->notify(); return $this; } public function setContent($resource, string $charset = MailMimeParser::DEFAULT_CHARSET) : static { $stream = Utils::streamFor($resource); $this->attachContentStream($stream, $charset); // this->notify() called in attachContentStream return $this; } public function getResourceHandle() : mixed { return StreamWrapper::getResource($this->getStream()); } public function getStream() : StreamInterface { return $this->partStreamContainer->getStream(); } public function save($filenameResourceOrStream, string $filemode = 'w+') : static { $resourceOrStream = $filenameResourceOrStream; if (\is_string($filenameResourceOrStream)) { $resourceOrStream = \fopen($filenameResourceOrStream, $filemode); } $partStream = $this->getStream(); $partStream->rewind(); $stream = Utils::streamFor($resourceOrStream); Utils::copyToStream($partStream, $stream); if (!\is_string($filenameResourceOrStream) && !($filenameResourceOrStream instanceof StreamInterface)) { // only detach if it wasn't a string or StreamInterface, so the // fopen call can be properly closed if it was $stream->detach(); } return $this; } public function __toString() : string { return $this->getStream()->getContents(); } public function getErrorLoggingContextName() : string { $params = ''; if (!empty($this->getContentId())) { $params .= ', content-id=' . $this->getContentId(); } $params .= ', content-type=' . $this->getContentType(); $nsClass = static::class; $class = \substr($nsClass, (\strrpos($nsClass, '\\') ?? -1) + 1); return $class . '(' . \spl_object_id($this) . $params . ')'; } protected function getErrorBagChildren() : array { return [ $this->partStreamContainer ]; } }