Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
/*
4
 * This file is part of the Symfony package.
5
 *
6
 * (c) Fabien Potencier <fabien@symfony.com>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
 
12
namespace Symfony\Component\Mime\Part;
13
 
14
use Symfony\Component\Mime\Encoder\Base64ContentEncoder;
15
use Symfony\Component\Mime\Encoder\ContentEncoderInterface;
16
use Symfony\Component\Mime\Encoder\EightBitContentEncoder;
17
use Symfony\Component\Mime\Encoder\QpContentEncoder;
18
use Symfony\Component\Mime\Exception\InvalidArgumentException;
19
use Symfony\Component\Mime\Header\Headers;
20
 
21
/**
22
 * @author Fabien Potencier <fabien@symfony.com>
23
 */
24
class TextPart extends AbstractPart
25
{
26
    /** @internal */
27
    protected $_headers;
28
 
29
    private static $encoders = [];
30
 
31
    private $body;
32
    private $charset;
33
    private $subtype;
34
    /**
35
     * @var ?string
36
     */
37
    private $disposition;
38
    private $name;
39
    private $encoding;
40
    private $seekable;
41
 
42
    /**
43
     * @param resource|string|File $body Use a File instance to defer loading the file until rendering
44
     */
45
    public function __construct($body, ?string $charset = 'utf-8', string $subtype = 'plain', string $encoding = null)
46
    {
47
        unset($this->_headers);
48
 
49
        parent::__construct();
50
 
51
        if (!\is_string($body) && !\is_resource($body) && !$body instanceof File) {
52
            throw new \TypeError(sprintf('The body of "%s" must be a string, a resource, or an instance of "%s" (got "%s").', self::class, File::class, get_debug_type($body)));
53
        }
54
 
55
        if ($body instanceof File) {
56
            $path = $body->getPath();
57
            if ((is_file($path) && !is_readable($path)) || is_dir($path)) {
58
                throw new InvalidArgumentException(sprintf('Path "%s" is not readable.', $path));
59
            }
60
        }
61
 
62
        $this->body = $body;
63
        $this->charset = $charset;
64
        $this->subtype = $subtype;
65
        $this->seekable = \is_resource($body) ? stream_get_meta_data($body)['seekable'] && 0 === fseek($body, 0, \SEEK_CUR) : null;
66
 
67
        if (null === $encoding) {
68
            $this->encoding = $this->chooseEncoding();
69
        } else {
70
            if ('quoted-printable' !== $encoding && 'base64' !== $encoding && '8bit' !== $encoding) {
71
                throw new InvalidArgumentException(sprintf('The encoding must be one of "quoted-printable", "base64", or "8bit" ("%s" given).', $encoding));
72
            }
73
            $this->encoding = $encoding;
74
        }
75
    }
76
 
77
    public function getMediaType(): string
78
    {
79
        return 'text';
80
    }
81
 
82
    public function getMediaSubtype(): string
83
    {
84
        return $this->subtype;
85
    }
86
 
87
    /**
88
     * @param string $disposition one of attachment, inline, or form-data
89
     *
90
     * @return $this
91
     */
92
    public function setDisposition(string $disposition): static
93
    {
94
        $this->disposition = $disposition;
95
 
96
        return $this;
97
    }
98
 
99
    /**
100
     * Sets the name of the file (used by FormDataPart).
101
     *
102
     * @return $this
103
     */
104
    public function setName(string $name): static
105
    {
106
        $this->name = $name;
107
 
108
        return $this;
109
    }
110
 
111
    /**
112
     * Gets the name of the file.
113
     */
114
    public function getName(): ?string
115
    {
116
        return $this->name;
117
    }
118
 
119
    public function getBody(): string
120
    {
121
        if ($this->body instanceof File) {
122
            return file_get_contents($this->body->getPath());
123
        }
124
 
125
        if (null === $this->seekable) {
126
            return $this->body;
127
        }
128
 
129
        if ($this->seekable) {
130
            rewind($this->body);
131
        }
132
 
133
        return stream_get_contents($this->body) ?: '';
134
    }
135
 
136
    public function bodyToString(): string
137
    {
138
        return $this->getEncoder()->encodeString($this->getBody(), $this->charset);
139
    }
140
 
141
    public function bodyToIterable(): iterable
142
    {
143
        if ($this->body instanceof File) {
144
            $path = $this->body->getPath();
145
            if (false === $handle = @fopen($path, 'r', false)) {
146
                throw new InvalidArgumentException(sprintf('Unable to open path "%s".', $path));
147
            }
148
 
149
            yield from $this->getEncoder()->encodeByteStream($handle);
150
        } elseif (null !== $this->seekable) {
151
            if ($this->seekable) {
152
                rewind($this->body);
153
            }
154
            yield from $this->getEncoder()->encodeByteStream($this->body);
155
        } else {
156
            yield $this->getEncoder()->encodeString($this->body);
157
        }
158
    }
159
 
160
    public function getPreparedHeaders(): Headers
161
    {
162
        $headers = parent::getPreparedHeaders();
163
 
164
        $headers->setHeaderBody('Parameterized', 'Content-Type', $this->getMediaType().'/'.$this->getMediaSubtype());
165
        if ($this->charset) {
166
            $headers->setHeaderParameter('Content-Type', 'charset', $this->charset);
167
        }
168
        if ($this->name && 'form-data' !== $this->disposition) {
169
            $headers->setHeaderParameter('Content-Type', 'name', $this->name);
170
        }
171
        $headers->setHeaderBody('Text', 'Content-Transfer-Encoding', $this->encoding);
172
 
173
        if (!$headers->has('Content-Disposition') && null !== $this->disposition) {
174
            $headers->setHeaderBody('Parameterized', 'Content-Disposition', $this->disposition);
175
            if ($this->name) {
176
                $headers->setHeaderParameter('Content-Disposition', 'name', $this->name);
177
            }
178
        }
179
 
180
        return $headers;
181
    }
182
 
183
    public function asDebugString(): string
184
    {
185
        $str = parent::asDebugString();
186
        if (null !== $this->charset) {
187
            $str .= ' charset: '.$this->charset;
188
        }
189
        if (null !== $this->disposition) {
190
            $str .= ' disposition: '.$this->disposition;
191
        }
192
 
193
        return $str;
194
    }
195
 
196
    private function getEncoder(): ContentEncoderInterface
197
    {
198
        if ('8bit' === $this->encoding) {
199
            return self::$encoders[$this->encoding] ??= new EightBitContentEncoder();
200
        }
201
 
202
        if ('quoted-printable' === $this->encoding) {
203
            return self::$encoders[$this->encoding] ??= new QpContentEncoder();
204
        }
205
 
206
        return self::$encoders[$this->encoding] ??= new Base64ContentEncoder();
207
    }
208
 
209
    private function chooseEncoding(): string
210
    {
211
        if (null === $this->charset) {
212
            return 'base64';
213
        }
214
 
215
        return 'quoted-printable';
216
    }
217
 
218
    public function __sleep(): array
219
    {
220
        // convert resources to strings for serialization
221
        if (null !== $this->seekable || $this->body instanceof File) {
222
            $this->body = $this->getBody();
223
            $this->seekable = null;
224
        }
225
 
226
        $this->_headers = $this->getHeaders();
227
 
228
        return ['_headers', 'body', 'charset', 'subtype', 'disposition', 'name', 'encoding'];
229
    }
230
 
231
    public function __wakeup()
232
    {
233
        $r = new \ReflectionProperty(AbstractPart::class, 'headers');
234
        $r->setValue($this, $this->_headers);
235
        unset($this->_headers);
236
    }
237
}