Completed
Push — 5.x ( 546220...bd8586 )
by Lars
16:02
created

Swift_Mime_Headers_ParameterizedHeader::toTokens()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 18
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 9
nc 3
nop 1
dl 0
loc 18
ccs 8
cts 8
cp 1
crap 3
rs 9.4285
c 0
b 0
f 0
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
 * An abstract base MIME Header.
13
 *
14
 * @author Chris Corbyn
15
 */
16
class Swift_Mime_Headers_ParameterizedHeader extends Swift_Mime_Headers_UnstructuredHeader implements Swift_Mime_ParameterizedHeader
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
17
{
18
    /**
19
     * RFC 2231's definition of a token.
20
     *
21
     * @var string
22
     */
23
    const TOKEN_REGEX = '(?:[\x21\x23-\x27\x2A\x2B\x2D\x2E\x30-\x39\x41-\x5A\x5E-\x7E]+)';
24
25
    /**
26
     * The Encoder used to encode the parameters.
27
     *
28
     * @var Swift_Encoder
29
     */
30
    private $_paramEncoder;
31
32
    /**
33
     * The parameters as an associative array.
34
     *
35
     * @var string[]
36
     */
37
    private $_params = array();
38
39
    /**
40
     * Creates a new ParameterizedHeader with $name.
41
     *
42
     * @param string                   $name
43
     * @param Swift_Mime_HeaderEncoder $encoder
44
     * @param Swift_Encoder            $paramEncoder, optional
0 ignored issues
show
Documentation introduced by
There is no parameter named $paramEncoder,. Did you maybe mean $encoder?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
45
     */
46 163
    public function __construct($name, Swift_Mime_HeaderEncoder $encoder, Swift_Encoder $paramEncoder = null)
47
    {
48 163
        parent::__construct($name, $encoder);
49 163
        $this->_paramEncoder = $paramEncoder;
50 163
    }
51
52
    /**
53
     * Get the type of Header that this instance represents.
54
     *
55
     * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX
56
     * @see TYPE_DATE, TYPE_ID, TYPE_PATH
57
     *
58
     * @return int
59
     */
60 1
    public function getFieldType()
61
    {
62 1
        return self::TYPE_PARAMETERIZED;
63
    }
64
65
    /**
66
     * Set the character set used in this Header.
67
     *
68
     * @param string $charset
69
     */
70 145
    public function setCharset($charset)
71
    {
72 145
        parent::setCharset($charset);
73 145
        if (null !== $this->_paramEncoder) {
74 41
            $this->_paramEncoder->charsetChanged($charset);
75
        }
76 145
    }
77
78
    /**
79
     * Set the value of $parameter.
80
     *
81
     * @param string $parameter
82
     * @param string $value
83
     */
84 141
    public function setParameter($parameter, $value)
85
    {
86 141
        $this->setParameters(array_merge($this->getParameters(), array($parameter => $value)));
87 141
    }
88
89
    /**
90
     * Get the value of $parameter.
91
     *
92
     * @param string $parameter
93
     *
94
     * @return string
95
     */
96 120
    public function getParameter($parameter)
97
    {
98 120
        $params = $this->getParameters();
99
100 120
        return isset($params[$parameter]) ? $params[$parameter] : null;
101
    }
102
103
    /**
104
     * Set an associative array of parameter names mapped to values.
105
     *
106
     * @param string[] $parameters
107
     */
108 152
    public function setParameters(array $parameters)
109
    {
110 152
        $this->clearCachedValueIf($this->_params != $parameters);
111 152
        $this->_params = $parameters;
112 152
    }
113
114
    /**
115
     * Returns an associative array of parameter names mapped to values.
116
     *
117
     * @return string[]
118
     */
119 142
    public function getParameters()
120
    {
121 142
        return $this->_params;
122
    }
123
124
    /**
125
     * Get the value of this header prepared for rendering.
126
     *
127
     * @return string
128
     */
129 135
    public function getFieldBody() //TODO: Check caching here
130
    {
131 135
        $body = parent::getFieldBody();
132 135
        foreach ($this->_params as $name => $value) {
133 131
            if (null !== $value) {
134
                // Add the parameter
135 131
                $body .= '; ' . $this->_createParameter($name, $value);
136
            }
137
        }
138
139 135
        return $body;
140
    }
141
142
    /**
143
     * Generate a list of all tokens in the final header.
144
     *
145
     * This doesn't need to be overridden in theory, but it is for implementation
146
     * reasons to prevent potential breakage of attributes.
147
     *
148
     * @param string $string The string to tokenize
149
     *
150
     * @return array An array of tokens as strings
151
     */
152 135
    protected function toTokens($string = null)
153
    {
154 135
        $tokens = parent::toTokens(parent::getFieldBody());
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (getFieldBody() instead of toTokens()). Are you sure this is correct? If so, you might want to change this to $this->getFieldBody().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
155
156
        // Try creating any parameters
157 135
        foreach ($this->_params as $name => $value) {
158 131
            if (null !== $value) {
159
                // Add the semi-colon separator
160 77
                $tokens[count($tokens) - 1] .= ';';
161 77
                $tokens = array_merge(
162
                    $tokens,
163 131
                    $this->generateTokenLines(' ' . $this->_createParameter($name, $value))
164
                );
165
            }
166
        }
167
168 135
        return $tokens;
169
    }
170
171
    /**
172
     * Render a RFC 2047 compliant header parameter from the $name and $value.
173
     *
174
     * @param string $name
175
     * @param string $value
176
     *
177
     * @return string
178
     */
179 82
    private function _createParameter($name, $value)
180
    {
181 82
        $origValue = $value;
182
183 82
        $encoded = false;
184
        // Allow room for parameter name, indices, "=" and DQUOTEs
185 82
        $maxValueLength = $this->getMaxLineLength() - strlen($name . '=*N"";') - 1;
186 82
        $firstLineOffset = 0;
187
188
        // If it's not already a valid parameter value ...
189 82
        if (!preg_match('/^' . self::TOKEN_REGEX . '$/D', $value)) {
190
            // TODO: text, or something else??
0 ignored issues
show
Unused Code Comprehensibility introduced by
39% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
191
            // ... and it's not ascii
192 39
            if (!preg_match('/^[\x00-\x08\x0B\x0C\x0E-\x7F]*$/D', $value)) {
193 6
                $encoded = true;
194
195 6
                // Allow space for the indices, charset and language.
196 6
                $maxValueLength = $this->getMaxLineLength() - strlen($name . '*N*="";') - 1;
197
                $firstLineOffset = strlen($this->getCharset() . "'" . $this->getLanguage() . "'");
198
            }
199
        }
200
201 82
        // Encode if we need to ...
202 7
        if ($encoded || strlen($value) > $maxValueLength) {
203 6
            if (null !== $this->_paramEncoder) {
204
                $value = $this->_paramEncoder->encodeString(
205
                    $origValue,
206
                    $firstLineOffset,
207 6
                    $maxValueLength,
208
                    $this->getCharset()
0 ignored issues
show
Unused Code introduced by
The call to Swift_Encoder::encodeString() has too many arguments starting with $this->getCharset().

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
209
                );
210
            } else {
211 2
                // We have to go against RFC 2183/2231 in some areas for interoperability.
212 2
                $value = $this->getTokenAsEncodedWord($origValue);
213
                $encoded = false;
214
            }
215
        }
216 82
217
        if (null !== $this->_paramEncoder) {
218
            $valueLines = explode("\r\n", $value);
219 82
        } else {
220 3
            $valueLines = array($value);
221 3
        }
222 3
223
        // Need to add indices.
224
        if (count($valueLines) > 1) {
225 3
            $paramLines = array();
226
            foreach ($valueLines as $i => $line) {
227 80
                $paramLines[] = $name . '*' . $i . $this->_getEndOfParameterValue($line, true, $i === 0);
228 80
            }
229
230 80
            return implode(";\r\n ", $paramLines);
231
        }
232
233
        return $name . $this->_getEndOfParameterValue(
234
            $valueLines[0],
235
            $encoded,
236
            true
237
        );
238
    }
239
240
    /**
241
     * Returns the parameter value from the "=" and beyond.
242
     *
243
     * @param string $value     to append
244 82
     * @param bool   $encoded
245
     * @param bool   $firstLine
246 82
     *
247 35
     * @return string
248
     */
249
    private function _getEndOfParameterValue($value, $encoded = false, $firstLine = false)
250 82
    {
251 82
        if (!preg_match('/^' . self::TOKEN_REGEX . '$/D', $value)) {
252 6
            $value = '"' . $value . '"';
253 6
        }
254 6
255
        $prepend = '=';
256
        if ($encoded) {
257
            $prepend = '*=';
258 82
            if ($firstLine) {
259
                $prepend = '*=' . $this->getCharset() . "'" . $this->getLanguage() . "'";
260
            }
261
        }
262
263
        return $prepend . $value;
264
    }
265
}
266