Test Failed
Push — master ( e258e4...a626ba )
by Zaahid
15:25
created

combineAdjacentUnencodedParts()   A

Complexity

Conditions 5
Paths 8

Size

Total Lines 19
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 13
c 1
b 0
f 0
dl 0
loc 19
rs 9.5222
cc 5
nc 8
nop 1
1
<?php
2
/**
3
 * This file is part of the ZBateson\MailMimeParser project.
4
 *
5
 * @license http://opensource.org/licenses/bsd-license.php BSD
6
 */
7
8
namespace ZBateson\MailMimeParser\Header\Part;
9
10
use Psr\Log\LoggerInterface;
11
use ZBateson\MbWrapper\MbWrapper;
12
13
/**
14
 * Holds a running value for an RFC-2231 split header parameter.
15
 *
16
 * ParameterConsumer creates SplitParameterTokens when a split header parameter
17
 * is first found, and adds subsequent split parts to an already created one if
18
 * the parameter name matches.
19
 *
20
 * @author Zaahid Bateson
21
 */
22
class SplitParameterPart extends ParameterPart
23
{
24
    /**
25
     * @var HeaderPartFactory used to create combined MimeToken parts.
26
     */
27
    protected HeaderPartFactory $partFactory;
28
29
    /**
30
     * Initializes a SplitParameterToken.
31
     *
32
     * @param ParameterPart[] $children
33
     */
34
    public function __construct(
35
        LoggerInterface $logger,
36
        MbWrapper $charsetConverter,
37
        HeaderPartFactory $headerPartFactory,
38
        array $children
39
    ) {
40
        $this->partFactory = $headerPartFactory;
41
        NameValuePart::__construct($logger, $charsetConverter, [$children[0]], $children);
42
        $this->children = $children;
43
    }
44
45
    protected function getNameFromParts(array $parts) : string
46
    {
47
        return $parts[0]->getName();
48
    }
49
50
    private function getMimeTokens(string $value) : array
51
    {
52
        $pattern = MimeToken::MIME_PART_PATTERN;
53
        // remove whitespace between two adjacent mime encoded parts
54
        $normed = \preg_replace("/($pattern)\\s+(?=$pattern)/", '$1', $value);
55
        // with PREG_SPLIT_DELIM_CAPTURE, matched and unmatched parts are returned
56
        $aMimeParts = \preg_split("/($pattern)/", $normed, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
57
        return \array_map(
58
            fn ($p) => (\preg_match("/$pattern/", $p)) ? $this->partFactory->newMimeToken($p) : $this->partFactory->newToken($p, true, true),
59
            $aMimeParts
60
        );
61
    }
62
63
    private function combineAdjacentUnencodedParts(array $parts) : array
64
    {
65
        $runningValue = '';
66
        $returnedParts = [];
67
        foreach ($parts as $part) {
68
            if (!$part->encoded) {
69
                $runningValue .= $part->value;
70
                continue;
71
            }
72
            if (!empty($runningValue)) {
73
                $returnedParts = \array_merge($returnedParts, $this->getMimeTokens($runningValue));
74
                $runningValue = '';
75
            }
76
            $returnedParts[] = $part;
77
        }
78
        if (!empty($runningValue)) {
79
            $returnedParts = \array_merge($returnedParts, $this->getMimeTokens($runningValue));
80
        }
81
        return $returnedParts;
82
    }
83
84
    protected function getValueFromParts(array $parts) : string
85
    {
86
        $sorted = $parts;
87
        \usort($sorted, fn ($a, $b) => $a->index <=> $b->index);
88
89
        $first = $sorted[0];
90
        $this->language = $first->language;
91
        $charset = $this->charset = $first->charset;
92
93
        $combined = $this->combineAdjacentUnencodedParts($sorted);
94
95
        return \implode(\array_map(
96
            fn ($p) => ($p instanceof ParameterPart && $p->encoded)
97
                ? $this->decodePartValue($p->getValue(), ($p->charset === null) ? $charset : $p->charset)
98
                : $p->getValue(),
99
            $combined
100
        ));
101
    }
102
}
103