Completed
Pull Request — master (#42)
by Frederik
02:28
created

SectionList::fromString()   D

Complexity

Conditions 9
Paths 8

Size

Total Lines 31
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 90

Importance

Changes 0
Metric Value
dl 0
loc 31
ccs 0
cts 26
cp 0
rs 4.909
c 0
b 0
f 0
cc 9
eloc 18
nc 8
nop 1
crap 90
1
<?php
2
declare(strict_types=1);
3
4
namespace Genkgo\Mail\Protocol\Imap\MessageData;
5
6
/**
7
 * Class SectionList
8
 * @package Genkgo\Mail\Protocol\Imap\MessageData
9
 */
10
final class SectionList
11
{
12
    /**
13
     *
14
     */
15
    private CONST RFC_3501_SECTION_FIXED = [
16
        'HEADER' => true,
17
        'TEXT' => true,
18
    ];
19
20
    /**
21
     * @var array
22
     */
23
    private $sections = [];
24
25
    /**
26
     * @var bool
27
     */
28
    private $forceBrackets = false;
29
30
    /**
31
     * SectionList constructor.
32
     * @param array $sections
33
     */
34
    public function __construct(array $sections = [])
35
    {
36
        foreach ($sections as $section) {
37
            $this->validateSection($section);
38
        }
39
40
        $this->sections = $sections;
41
    }
42
43
    /**
44
     * @return string
45
     */
46
    public function __toString(): string
47
    {
48
        if ($this->forceBrackets === false && empty($this->sections)) {
49
            return '';
50
        }
51
52
        return sprintf(
53
            '[%s]',
54
            implode(' ', $this->sections)
55
        );
56
    }
57
58
    /**
59
     * @return SectionList
60
     */
61
    public static function newEmpty(): self
62
    {
63
        $list = new self();
64
        $list->forceBrackets = true;
65
        return $list;
66
    }
67
68
    /**
69
     * @param string $sections
70
     * @return SectionList
71
     */
72
    public static function fromString(string $sections): self
73
    {
74
        $result = preg_match('/^\[(.*?)\]$/', $sections, $matches);
75
        if ($result !== 1) {
76
            throw new \InvalidArgumentException('No section list');
77
        }
78
79
        $sections = array_filter(explode(' ', $matches[1]));
80
        for ($i = 0; $i < count($sections); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
81
            if ($sections[$i] === 'HEADER.FIELDS' || $sections[$i] === 'HEADER.FIELDS.NOT') {
82
                if ($sections[$i + 1][0] !== '(') {
83
                    throw new \InvalidArgumentException(
84
                        'HEADER.FIELDS or HEADER.FIELDS.NOT requires header-list'
85
                    );
86
                }
87
88
                do {
89
                    $sections[$i] .= $sections[$i + 1];
90
                    unset($sections[$i + 1]);
91
                } while (isset($sections[$i + 1]) && substr($sections[$i + 1], -1) !== ')');
92
            }
93
        }
94
95
        $sectionList = new self($sections);
96
97
        if (empty($sectionList->sections)) {
98
            $sectionList->forceBrackets = true;
99
        }
100
101
        return $sectionList;
102
    }
103
104
    /**
105
     * @param string $section
106
     */
107
    private function validateSection(string $section): void
108
    {
109
        if ($section === '') {
110
            throw new \InvalidArgumentException('Empty section');
111
        }
112
113
        if (isset(self::RFC_3501_SECTION_FIXED[$section])) {
114
            return;
115
        }
116
117
        if (preg_match('/^HEADER.FIELDS(\.NOT)? \((.*?)\)$/', $section) === 1) {
118
            return;
119
        }
120
121
        throw new \InvalidArgumentException('Invalid section item ' . $section);
122
    }
123
}