1<?php
2
3/*
4 * This file is part of SwiftMailer.
5 * (c) 2004-2009 Chris Corbyn
6 *
7 * For the full copyright and license information, please view the LICENSE
8 * file that was distributed with this source code.
9 */
10
11/**
12 * A MIME part, in a multipart message.
13 *
14 * @author Chris Corbyn
15 */
16class Swift_Mime_MimePart extends Swift_Mime_SimpleMimeEntity
17{
18    /** The format parameter last specified by the user */
19    protected $userFormat;
20
21    /** The charset last specified by the user */
22    protected $userCharset;
23
24    /** The delsp parameter last specified by the user */
25    protected $userDelSp;
26
27    /** The nesting level of this MimePart */
28    private $nestingLevel = self::LEVEL_ALTERNATIVE;
29
30    /**
31     * Create a new MimePart with $headers, $encoder and $cache.
32     *
33     * @param Swift_Mime_SimpleHeaderSet $headers
34     * @param Swift_Mime_ContentEncoder  $encoder
35     * @param Swift_KeyCache             $cache
36     * @param Swift_IdGenerator          $idGenerator
37     * @param string                     $charset
38     */
39    public function __construct(Swift_Mime_SimpleHeaderSet $headers, Swift_Mime_ContentEncoder $encoder, Swift_KeyCache $cache, Swift_IdGenerator $idGenerator, $charset = null)
40    {
41        parent::__construct($headers, $encoder, $cache, $idGenerator);
42        $this->setContentType('text/plain');
43        if (null !== $charset) {
44            $this->setCharset($charset);
45        }
46    }
47
48    /**
49     * Set the body of this entity, either as a string, or as an instance of
50     * {@link Swift_OutputByteStream}.
51     *
52     * @param mixed  $body
53     * @param string $contentType optional
54     * @param string $charset     optional
55     *
56     * @return $this
57     */
58    public function setBody($body, $contentType = null, $charset = null)
59    {
60        if (isset($charset)) {
61            $this->setCharset($charset);
62        }
63        $body = $this->convertString($body);
64
65        parent::setBody($body, $contentType);
66
67        return $this;
68    }
69
70    /**
71     * Get the character set of this entity.
72     *
73     * @return string
74     */
75    public function getCharset()
76    {
77        return $this->getHeaderParameter('Content-Type', 'charset');
78    }
79
80    /**
81     * Set the character set of this entity.
82     *
83     * @param string $charset
84     *
85     * @return $this
86     */
87    public function setCharset($charset)
88    {
89        $this->setHeaderParameter('Content-Type', 'charset', $charset);
90        if ($charset !== $this->userCharset) {
91            $this->clearCache();
92        }
93        $this->userCharset = $charset;
94        parent::charsetChanged($charset);
95
96        return $this;
97    }
98
99    /**
100     * Get the format of this entity (i.e. flowed or fixed).
101     *
102     * @return string
103     */
104    public function getFormat()
105    {
106        return $this->getHeaderParameter('Content-Type', 'format');
107    }
108
109    /**
110     * Set the format of this entity (flowed or fixed).
111     *
112     * @param string $format
113     *
114     * @return $this
115     */
116    public function setFormat($format)
117    {
118        $this->setHeaderParameter('Content-Type', 'format', $format);
119        $this->userFormat = $format;
120
121        return $this;
122    }
123
124    /**
125     * Test if delsp is being used for this entity.
126     *
127     * @return bool
128     */
129    public function getDelSp()
130    {
131        return 'yes' === $this->getHeaderParameter('Content-Type', 'delsp');
132    }
133
134    /**
135     * Turn delsp on or off for this entity.
136     *
137     * @param bool $delsp
138     *
139     * @return $this
140     */
141    public function setDelSp($delsp = true)
142    {
143        $this->setHeaderParameter('Content-Type', 'delsp', $delsp ? 'yes' : null);
144        $this->userDelSp = $delsp;
145
146        return $this;
147    }
148
149    /**
150     * Get the nesting level of this entity.
151     *
152     * @see LEVEL_TOP, LEVEL_ALTERNATIVE, LEVEL_MIXED, LEVEL_RELATED
153     *
154     * @return int
155     */
156    public function getNestingLevel()
157    {
158        return $this->nestingLevel;
159    }
160
161    /**
162     * Receive notification that the charset has changed on this document, or a
163     * parent document.
164     *
165     * @param string $charset
166     */
167    public function charsetChanged($charset)
168    {
169        $this->setCharset($charset);
170    }
171
172    /** Fix the content-type and encoding of this entity */
173    protected function fixHeaders()
174    {
175        parent::fixHeaders();
176        if (count($this->getChildren())) {
177            $this->setHeaderParameter('Content-Type', 'charset', null);
178            $this->setHeaderParameter('Content-Type', 'format', null);
179            $this->setHeaderParameter('Content-Type', 'delsp', null);
180        } else {
181            $this->setCharset($this->userCharset);
182            $this->setFormat($this->userFormat);
183            $this->setDelSp($this->userDelSp);
184        }
185    }
186
187    /** Set the nesting level of this entity */
188    protected function setNestingLevel($level)
189    {
190        $this->nestingLevel = $level;
191    }
192
193    /** Encode charset when charset is not utf-8 */
194    protected function convertString($string)
195    {
196        $charset = strtolower($this->getCharset());
197        if (!in_array($charset, array('utf-8', 'iso-8859-1', 'iso-8859-15', ''))) {
198            // mb_convert_encoding must be the first one to check, since iconv cannot convert some words.
199            if (function_exists('mb_convert_encoding')) {
200                $string = mb_convert_encoding($string, $charset, 'utf-8');
201            } elseif (function_exists('iconv')) {
202                $string = iconv('utf-8//TRANSLIT//IGNORE', $charset, $string);
203            } else {
204                throw new Swift_SwiftException('No suitable convert encoding function (use UTF-8 as your charset or install the mbstring or iconv extension).');
205            }
206
207            return $string;
208        }
209
210        return $string;
211    }
212}
213