Completed
Push — master ( 2284e8...d443e4 )
by Andre
01:49 queued 32s
created

Parser::normalize()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 4
nc 1
nop 1
1
<?php
2
3
namespace TheIconic\NameParser;
4
5
use TheIconic\NameParser\Mapper\NicknameMapper;
6
use TheIconic\NameParser\Mapper\SalutationMapper;
7
use TheIconic\NameParser\Mapper\SuffixMapper;
8
use TheIconic\NameParser\Mapper\InitialMapper;
9
use TheIconic\NameParser\Mapper\LastnameMapper;
10
use TheIconic\NameParser\Mapper\FirstnameMapper;
11
use TheIconic\NameParser\Mapper\MiddlenameMapper;
12
13
class Parser
14
{
15
    /**
16
     * @var string
17
     */
18
    protected $whitespace = " \r\n\t";
19
20
    /**
21
     * @var array
22
     */
23
    protected $mappers = [];
24
25
    /**
26
     * split full names into the following parts:
27
     * - prefix / salutation  (Mr., Mrs., etc)
28
     * - given name / first name
29
     * - middle initials
30
     * - surname / last name
31
     * - suffix (II, Phd, Jr, etc)
32
     *
33
     * @param string $name
34
     * @return Name
35
     */
36
    public function parse($name): Name
37
    {
38
        $name = $this->normalize($name);
39
40
        $segments = explode(',', $name);
41
42
        if (1 < count($segments)) {
43
            return $this->parseSplitName($segments[0], $segments[1], $segments[2] ?? '');
44
        }
45
46
        $parts = explode(' ', $name);
47
48
        foreach ($this->getMappers() as $mapper) {
49
            $parts = $mapper->map($parts);
50
        }
51
52
        return new Name($parts);
53
    }
54
55
    /**
56
     * handles split-parsing of comma-separated name parts
57
     *
58
     * @param $left - the name part left of the comma
59
     * @param $right - the name part right of the comma
60
     *
61
     * @return Name
62
     */
63
    protected function parseSplitName($first, $second, $third): Name
64
    {
65
        $parts = array_merge(
66
            $this->getFirstSegmentParser()->parse($first)->getParts(),
67
            $this->getSecondSegmentParser()->parse($second)->getParts(),
68
            $this->getThirdSegmentParser()->parse($third)->getParts()
69
        );
70
71
        return new Name($parts);
72
    }
73
74
    /**
75
     * @return Parser
76
     */
77
    protected function getFirstSegmentParser(): Parser
78
    {
79
        $parser = new Parser();
80
        $parser->setMappers([
81
            new SalutationMapper(),
82
            new SuffixMapper(),
83
            new LastnameMapper(['match_single' => true]),
84
            new FirstnameMapper(),
85
            new MiddlenameMapper(),
86
        ]);
87
88
        return $parser;
89
    }
90
91
    /**
92
     * @return Parser
93
     */
94
    protected function getSecondSegmentParser(): Parser
95
    {
96
        $parser = new Parser();
97
        $parser->setMappers([
98
            new SalutationMapper(),
99
            new SuffixMapper(['match_single' => true]),
100
            new NicknameMapper(),
101
            new InitialMapper(['match_last' => true]),
102
            new FirstnameMapper(),
103
            new MiddlenameMapper(),
104
        ]);
105
106
        return $parser;
107
    }
108
109
    protected function getThirdSegmentParser(): Parser
110
    {
111
        $parser = new Parser();
112
        $parser->setMappers([
113
            new SuffixMapper(['match_single' => true]),
114
        ]);
115
116
        return $parser;
117
    }
118
119
    /**
120
     * get the mappers for this parser
121
     *
122
     * @return array
123
     */
124
    public function getMappers(): array
125
    {
126
        if (empty($this->mappers)) {
127
            $this->setMappers([
128
                new NicknameMapper(),
129
                new SalutationMapper(),
130
                new SuffixMapper(),
131
                new InitialMapper(),
132
                new LastnameMapper(),
133
                new FirstnameMapper(),
134
                new MiddlenameMapper(),
135
            ]);
136
        }
137
138
        return $this->mappers;
139
    }
140
141
    /**
142
     * set the mappers for this parser
143
     *
144
     * @param array $mappers
145
     * @return Parser
146
     */
147
    public function setMappers(array $mappers): Parser
148
    {
149
        $this->mappers = $mappers;
150
151
        return $this;
152
    }
153
154
    /**
155
     * normalize the name
156
     *
157
     * @param string $name
158
     * @return string
159
     */
160
    protected function normalize(string $name): string
161
    {
162
        $whitespace = $this->getWhitespace();
163
164
        $name = trim($name);
165
166
        return preg_replace('/[' . preg_quote($whitespace) . ']+/', ' ', $name);
167
    }
168
169
    /**
170
     * get a string of characters that are supposed to be treated as whitespace
171
     *
172
     * @return string
173
     */
174
    public function getWhitespace(): string
175
    {
176
        return $this->whitespace;
177
    }
178
179
    /**
180
     * set the string of characters that are supposed to be treated as whitespace
181
     *
182
     * @param $whitespace
183
     * @return Parser
184
     */
185
    public function setWhitespace($whitespace): Parser
186
    {
187
        $this->whitespace = $whitespace;
188
189
        return $this;
190
    }
191
}
192