26 private static $encoders = [];
38 public function __construct($body, ?
string $charset =
'utf-8', $subtype =
'plain',
string $encoding =
null)
40 parent::__construct();
42 if (!\is_string($body) && !\is_resource($body)) {
43 throw new \TypeError(sprintf(
'The body of "%s" must be a string or a resource (got "%s").', self::class, \is_object($body) ? \get_class($body) : \gettype($body)));
47 $this->charset = $charset;
48 $this->subtype = $subtype;
50 if (
null === $encoding) {
51 $this->encoding = $this->chooseEncoding();
53 if (
'quoted-printable' !== $encoding &&
'base64' !== $encoding &&
'8bit' !== $encoding) {
54 throw new InvalidArgumentException(sprintf(
'The encoding must be one of "quoted-printable", "base64", or "8bit" ("%s" given).', $encoding));
56 $this->encoding = $encoding;
67 return $this->subtype;
77 $this->disposition = $disposition;
96 if (!\is_resource($this->body)) {
100 if (stream_get_meta_data($this->body)[
'seekable'] ??
false) {
104 return stream_get_contents($this->body) ?:
'';
109 return $this->getEncoder()->encodeString($this->
getBody(), $this->charset);
114 if (\is_resource($this->body)) {
115 if (stream_get_meta_data($this->body)[
'seekable'] ??
false) {
118 yield from $this->getEncoder()->encodeByteStream($this->body);
120 yield $this->getEncoder()->encodeString($this->body);
126 $headers = parent::getPreparedHeaders();
129 if ($this->charset) {
130 $headers->setHeaderParameter(
'Content-Type',
'charset', $this->charset);
133 $headers->setHeaderParameter(
'Content-Type',
'name', $this->name);
135 $headers->setHeaderBody(
'Text',
'Content-Transfer-Encoding', $this->encoding);
137 if (!$headers->has(
'Content-Disposition') &&
null !== $this->disposition) {
138 $headers->setHeaderBody(
'Parameterized',
'Content-Disposition', $this->disposition);
140 $headers->setHeaderParameter(
'Content-Disposition',
'name', $this->name);
149 $str = parent::asDebugString();
150 if (
null !== $this->charset) {
151 $str .=
' charset: '.$this->charset;
153 if (
null !== $this->disposition) {
154 $str .=
' disposition: '.$this->disposition;
162 if (
'8bit' === $this->encoding) {
163 return self::$encoders[$this->encoding] ?? (self::$encoders[$this->encoding] =
new EightBitContentEncoder());
166 if (
'quoted-printable' === $this->encoding) {
167 return self::$encoders[$this->encoding] ?? (self::$encoders[$this->encoding] =
new QpContentEncoder());
170 return self::$encoders[$this->encoding] ?? (self::$encoders[$this->encoding] =
new Base64ContentEncoder());
173 private function chooseEncoding(): string
175 if (
null === $this->charset) {
179 return 'quoted-printable';
188 if (\is_resource($this->body)) {
189 $this->body = $this->
getBody();
194 return [
'_headers',
'body',
'charset',
'subtype',
'disposition',
'name',
'encoding'];
199 $r = new \ReflectionProperty(AbstractPart::class,
'headers');
200 $r->setAccessible(
true);
201 $r->setValue($this, $this->_headers);
202 unset($this->_headers);