Completed
Push — master ( 725c5b...9a2599 )
by Andre
10s
created

Parser::setMaxSalutationIndex()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
namespace TheIconic\NameParser;
4
5
use TheIconic\NameParser\Language\English;
6
use TheIconic\NameParser\Mapper\NicknameMapper;
7
use TheIconic\NameParser\Mapper\SalutationMapper;
8
use TheIconic\NameParser\Mapper\SuffixMapper;
9
use TheIconic\NameParser\Mapper\InitialMapper;
10
use TheIconic\NameParser\Mapper\LastnameMapper;
11
use TheIconic\NameParser\Mapper\FirstnameMapper;
12
use TheIconic\NameParser\Mapper\MiddlenameMapper;
13
14
class Parser
15
{
16
    /**
17
     * @var string
18
     */
19
    protected $whitespace = " \r\n\t";
20
21
    /**
22
     * @var array
23
     */
24
    protected $mappers = [];
25
26
    /**
27
     * @var array
28
     */
29
    protected $languages = [];
30
31
    /**
32
     * @var array
33
     */
34
    protected $nicknameDelimiters = [];
35
36
    /**
37
     * @var int
38
     */
39
    protected $maxSalutationIndex = 0;
40
41
    public function __construct(array $languages = [])
42
    {
43
        if (empty($languages)) {
44
            $languages = [new English()];
45
        }
46
47
        $this->languages = $languages;
48
    }
49
50
    /**
51
     * split full names into the following parts:
52
     * - prefix / salutation  (Mr., Mrs., etc)
53
     * - given name / first name
54
     * - middle initials
55
     * - surname / last name
56
     * - suffix (II, Phd, Jr, etc)
57
     *
58
     * @param string $name
59
     * @return Name
60
     */
61
    public function parse($name): Name
62
    {
63
        $name = $this->normalize($name);
64
65
        $segments = explode(',', $name);
66
67
        if (1 < count($segments)) {
68
            return $this->parseSplitName($segments[0], $segments[1], $segments[2] ?? '');
69
        }
70
71
        $parts = explode(' ', $name);
72
73
        foreach ($this->getMappers() as $mapper) {
74
            $parts = $mapper->map($parts);
75
        }
76
77
        return new Name($parts);
78
    }
79
80
    /**
81
     * handles split-parsing of comma-separated name parts
82
     *
83
     * @param $left - the name part left of the comma
84
     * @param $right - the name part right of the comma
85
     *
86
     * @return Name
87
     */
88
    protected function parseSplitName($first, $second, $third): Name
89
    {
90
        $parts = array_merge(
91
            $this->getFirstSegmentParser()->parse($first)->getParts(),
92
            $this->getSecondSegmentParser()->parse($second)->getParts(),
93
            $this->getThirdSegmentParser()->parse($third)->getParts()
94
        );
95
96
        return new Name($parts);
97
    }
98
99
    /**
100
     * @return Parser
101
     */
102
    protected function getFirstSegmentParser(): Parser
103
    {
104
        $parser = new Parser();
105
106
        $parser->setMappers([
107
            new SalutationMapper($this->getSalutations(), $this->getMaxSalutationIndex()),
108
            new SuffixMapper($this->getSuffixes()),
109
            new LastnameMapper($this->getPrefixes(), true),
110
            new FirstnameMapper(),
111
            new MiddlenameMapper(),
112
        ]);
113
114
        return $parser;
115
    }
116
117
    /**
118
     * @return Parser
119
     */
120
    protected function getSecondSegmentParser(): Parser
121
    {
122
        $parser = new Parser();
123
124
        $parser->setMappers([
125
            new SalutationMapper($this->getSalutations(), $this->getMaxSalutationIndex()),
126
            new SuffixMapper($this->getSuffixes(), true),
127
            new NicknameMapper($this->getNicknameDelimiters()),
128
            new InitialMapper(true),
129
            new FirstnameMapper(),
130
            new MiddlenameMapper(true),
131
        ]);
132
133
        return $parser;
134
    }
135
136
    protected function getThirdSegmentParser(): Parser
137
    {
138
        $parser = new Parser();
139
140
        $parser->setMappers([
141
            new SuffixMapper($this->getSuffixes(), true),
142
        ]);
143
144
        return $parser;
145
    }
146
147
    /**
148
     * get the mappers for this parser
149
     *
150
     * @return array
151
     */
152
    public function getMappers(): array
153
    {
154
        if (empty($this->mappers)) {
155
            $this->setMappers([
156
                new NicknameMapper($this->getNicknameDelimiters()),
157
                new SalutationMapper($this->getSalutations(), $this->getMaxSalutationIndex()),
158
                new SuffixMapper($this->getSuffixes()),
159
                new InitialMapper(),
160
                new LastnameMapper($this->getPrefixes()),
161
                new FirstnameMapper(),
162
                new MiddlenameMapper(),
163
            ]);
164
        }
165
166
        return $this->mappers;
167
    }
168
169
    /**
170
     * set the mappers for this parser
171
     *
172
     * @param array $mappers
173
     * @return Parser
174
     */
175
    public function setMappers(array $mappers): Parser
176
    {
177
        $this->mappers = $mappers;
178
179
        return $this;
180
    }
181
182
    /**
183
     * normalize the name
184
     *
185
     * @param string $name
186
     * @return string
187
     */
188
    protected function normalize(string $name): string
189
    {
190
        $whitespace = $this->getWhitespace();
191
192
        $name = trim($name);
193
194
        return preg_replace('/[' . preg_quote($whitespace) . ']+/', ' ', $name);
195
    }
196
197
    /**
198
     * get a string of characters that are supposed to be treated as whitespace
199
     *
200
     * @return string
201
     */
202
    public function getWhitespace(): string
203
    {
204
        return $this->whitespace;
205
    }
206
207
    /**
208
     * set the string of characters that are supposed to be treated as whitespace
209
     *
210
     * @param $whitespace
211
     * @return Parser
212
     */
213
    public function setWhitespace($whitespace): Parser
214
    {
215
        $this->whitespace = $whitespace;
216
217
        return $this;
218
    }
219
220
    /**
221
     * @return array
222
     */
223
    protected function getPrefixes()
224
    {
225
        $prefixes = [];
226
227
        /** @var LanguageInterface $language */
228
        foreach ($this->languages as $language) {
229
            $prefixes += $language->getLastnamePrefixes();
230
        }
231
232
        return $prefixes;
233
    }
234
235
    /**
236
     * @return array
237
     */
238
    protected function getSuffixes()
239
    {
240
        $suffixes = [];
241
242
        /** @var LanguageInterface $language */
243
        foreach ($this->languages as $language) {
244
            $suffixes += $language->getSuffixes();
245
        }
246
247
        return $suffixes;
248
    }
249
250
    /**
251
     * @return array
252
     */
253
    protected function getSalutations()
254
    {
255
        $salutations = [];
256
257
        /** @var LanguageInterface $language */
258
        foreach ($this->languages as $language) {
259
            $salutations += $language->getSalutations();
260
        }
261
262
        return $salutations;
263
    }
264
265
    /**
266
     * @return array
267
     */
268
    public function getNicknameDelimiters(): array
269
    {
270
        return $this->nicknameDelimiters;
271
    }
272
273
    /**
274
     * @param array $nicknameDelimiters
275
     * @return Parser
276
     */
277
    public function setNicknameDelimiters(array $nicknameDelimiters): Parser
278
    {
279
        $this->nicknameDelimiters = $nicknameDelimiters;
280
281
        return $this;
282
    }
283
284
    /**
285
     * @return int
286
     */
287
    public function getMaxSalutationIndex(): int
288
    {
289
        return $this->maxSalutationIndex;
290
    }
291
292
    /**
293
     * @param int $maxSalutationIndex
294
     * @return Parser
295
     */
296
    public function setMaxSalutationIndex(int $maxSalutationIndex): Parser
297
    {
298
        $this->maxSalutationIndex = $maxSalutationIndex;
299
300
        return $this;
301
    }
302
}
303