DsnParser::parse()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 7
dl 0
loc 14
rs 10
c 0
b 0
f 0
ccs 8
cts 8
cp 1
cc 2
nc 2
nop 1
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Artack\Dsn\Parser;
6
7
use Artack\Dsn\DeliveryStatus;
8
use Artack\Dsn\Field\ActionField;
9
use Artack\Dsn\Field\AddressTypeField;
10
use Artack\Dsn\Field\DateField;
11
use Artack\Dsn\Field\DiagnosticTypeField;
12
use Artack\Dsn\Field\MtaNameTypeField;
13
use Artack\Dsn\Field\StatusField;
14
use Artack\Dsn\Field\ValueField;
15
use Artack\Dsn\Fields;
16
17
class DsnParser
18
{
19
    private static $map = [
20
//        'original-envelope-id' => null,
21
        'reporting-mta' => MtaNameTypeField::class,
22
        'dsn-gateway' => MtaNameTypeField::class,
23
        'received-from-mta' => MtaNameTypeField::class,
24
        'arrival-date' => DateField::class,
25
        'original-recipient' => AddressTypeField::class,
26
        'final-recipient' => AddressTypeField::class,
27
        'action' => ActionField::class,
28
        'status' => StatusField::class,
29
        'remote-mta' => MtaNameTypeField::class,
30
        'diagnostic-code' => DiagnosticTypeField::class,
31
        'last-attempt-date' => DateField::class,
32
//        'final-log-id' => null,
33
        'will-retry-until' => DateField::class,
34
    ];
35
36 12
    public function parse(string $content): DeliveryStatus
37
    {
38 12
        $deliveryStatus = new DeliveryStatus();
39
40 12
        $groups = explode("\n\n", $content);
41
42 12
        $messageFieldGroup = array_shift($groups);
43 12
        $deliveryStatus->setMessageFields($this->parseBlock($messageFieldGroup));
44
45 8
        foreach ($groups as $group) {
46 8
            $deliveryStatus->addRecipientFields($this->parseBlock($group));
47
        }
48
49 8
        return $deliveryStatus;
50
    }
51
52 12
    private function parseBlock(string $block): Fields
53
    {
54 12
        $blockFields = new Fields();
55 12
        $lines = explode("\n", trim($block));
56
57 12
        foreach ($lines as $key => $line) {
58 12
            if (false === strpos($line, ':')) {
59 6
                $lines[$key - 1] .= $line;
60 4
                unset($lines[$key]);
61
            }
62
        }
63
64 10
        $block = implode("\n", $lines);
65 10
        preg_match_all('/^(.*?):\s((.*?);)?(.*?)(\s\((.*)\))?$/m', $block, $matches, PREG_SET_ORDER);
66
67 10
        foreach ($matches as $match) {
68 10
            $name = $match[1];
69 10
            $type = $match[3] ?? null;
70 10
            $value = trim($match[4]);
71 10
            $comment = $match[6] ?? null;
72
73 10
            $class = self::$map[strtolower($name)] ?? null;
74 10
            switch ($class) {
75
                case DateField::class:
76 4
                    $header = new DateField($name, new \DateTimeImmutable($value));
77 4
                    break;
78
                case ActionField::class:
79 8
                    $header = new ActionField($name, $value);
80 8
                    break;
81
                case DiagnosticTypeField::class:
82 6
                    $header = new DiagnosticTypeField($name, $value, $type, $comment);
83 6
                    break;
84
                case AddressTypeField::class:
85 8
                    $header = new AddressTypeField($name, $value, $type, $comment);
86 8
                    break;
87
                case MtaNameTypeField::class:
88 10
                    $header = new MtaNameTypeField($name, $value, $type, $comment);
89 8
                    break;
90
                case StatusField::class:
91 8
                    preg_match('/(\d{1}).(\d{1,3}).(\d{1,3})/', $value, $matches);
92 8
                    $header = new StatusField($name, (int) $matches[1], (int) $matches[2], (int) $matches[3], $comment);
93 8
                    break;
94
                default:
95 2
                    $header = new ValueField($name, $value, $comment);
96
            }
97 8
            $blockFields->add($header);
98
        }
99
100 8
        return $blockFields;
101
    }
102
}
103