Completed
Push — master ( 1961d1...9a54a7 )
by Andre
23s queued 12s
created

src/Parser.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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
    /**
42
     * @var int
43
     */
44
    protected $maxCombinedInitials = 2;
45
46
    public function __construct(array $languages = [])
47
    {
48
        if (empty($languages)) {
49
            $languages = [new English()];
50
        }
51
52
        $this->languages = $languages;
53
    }
54
55
    /**
56
     * split full names into the following parts:
57
     * - prefix / salutation  (Mr., Mrs., etc)
58
     * - given name / first name
59
     * - middle initials
60
     * - surname / last name
61
     * - suffix (II, Phd, Jr, etc)
62
     *
63
     * @param string $name
64
     * @return Name
65
     */
66
    public function parse($name): Name
67
    {
68
        $name = $this->normalize($name);
69
70
        $segments = explode(',', $name);
71
72
        if (1 < count($segments)) {
73
            return $this->parseSplitName($segments[0], $segments[1], $segments[2] ?? '');
74
        }
75
76
        $parts = explode(' ', $name);
77
78
        foreach ($this->getMappers() as $mapper) {
79
            $parts = $mapper->map($parts);
80
        }
81
82
        return new Name($parts);
83
    }
84
85
    /**
86
     * handles split-parsing of comma-separated name parts
87
     *
88
     * @param $left - the name part left of the comma
89
     * @param $right - the name part right of the comma
90
     *
91
     * @return Name
92
     */
93
    protected function parseSplitName($first, $second, $third): Name
94
    {
95
        $parts = array_merge(
96
            $this->getFirstSegmentParser()->parse($first)->getParts(),
97
            $this->getSecondSegmentParser()->parse($second)->getParts(),
98
            $this->getThirdSegmentParser()->parse($third)->getParts()
99
        );
100
101
        return new Name($parts);
102
    }
103
104
    /**
105
     * @return Parser
106
     */
107 View Code Duplication
    protected function getFirstSegmentParser(): Parser
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
108
    {
109
        $parser = new Parser();
110
111
        $parser->setMappers([
112
            new SalutationMapper($this->getSalutations(), $this->getMaxSalutationIndex()),
113
            new SuffixMapper($this->getSuffixes(), false, 2),
114
            new LastnameMapper($this->getPrefixes(), true),
115
            new FirstnameMapper(),
116
            new MiddlenameMapper(),
117
        ]);
118
119
        return $parser;
120
    }
121
122
    /**
123
     * @return Parser
124
     */
125 View Code Duplication
    protected function getSecondSegmentParser(): Parser
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
126
    {
127
        $parser = new Parser();
128
129
        $parser->setMappers([
130
            new SalutationMapper($this->getSalutations(), $this->getMaxSalutationIndex()),
131
            new SuffixMapper($this->getSuffixes(), true, 1),
132
            new NicknameMapper($this->getNicknameDelimiters()),
133
            new InitialMapper($this->getMaxCombinedInitials(), true),
134
            new FirstnameMapper(),
135
            new MiddlenameMapper(true),
136
        ]);
137
138
        return $parser;
139
    }
140
141
    protected function getThirdSegmentParser(): Parser
142
    {
143
        $parser = new Parser();
144
145
        $parser->setMappers([
146
            new SuffixMapper($this->getSuffixes(), true, 0),
147
        ]);
148
149
        return $parser;
150
    }
151
152
    /**
153
     * get the mappers for this parser
154
     *
155
     * @return array
156
     */
157
    public function getMappers(): array
158
    {
159
        if (empty($this->mappers)) {
160
            $this->setMappers([
161
                new NicknameMapper($this->getNicknameDelimiters()),
162
                new SalutationMapper($this->getSalutations(), $this->getMaxSalutationIndex()),
163
                new SuffixMapper($this->getSuffixes()),
164
                new InitialMapper($this->getMaxCombinedInitials()),
165
                new LastnameMapper($this->getPrefixes()),
166
                new FirstnameMapper(),
167
                new MiddlenameMapper(),
168
            ]);
169
        }
170
171
        return $this->mappers;
172
    }
173
174
    /**
175
     * set the mappers for this parser
176
     *
177
     * @param array $mappers
178
     * @return Parser
179
     */
180
    public function setMappers(array $mappers): Parser
181
    {
182
        $this->mappers = $mappers;
183
184
        return $this;
185
    }
186
187
    /**
188
     * normalize the name
189
     *
190
     * @param string $name
191
     * @return string
192
     */
193
    protected function normalize(string $name): string
194
    {
195
        $whitespace = $this->getWhitespace();
196
197
        $name = trim($name);
198
199
        return preg_replace('/[' . preg_quote($whitespace) . ']+/', ' ', $name);
200
    }
201
202
    /**
203
     * get a string of characters that are supposed to be treated as whitespace
204
     *
205
     * @return string
206
     */
207
    public function getWhitespace(): string
208
    {
209
        return $this->whitespace;
210
    }
211
212
    /**
213
     * set the string of characters that are supposed to be treated as whitespace
214
     *
215
     * @param $whitespace
216
     * @return Parser
217
     */
218
    public function setWhitespace($whitespace): Parser
219
    {
220
        $this->whitespace = $whitespace;
221
222
        return $this;
223
    }
224
225
    /**
226
     * @return array
227
     */
228
    protected function getPrefixes()
229
    {
230
        $prefixes = [];
231
232
        /** @var LanguageInterface $language */
233
        foreach ($this->languages as $language) {
234
            $prefixes += $language->getLastnamePrefixes();
235
        }
236
237
        return $prefixes;
238
    }
239
240
    /**
241
     * @return array
242
     */
243
    protected function getSuffixes()
244
    {
245
        $suffixes = [];
246
247
        /** @var LanguageInterface $language */
248
        foreach ($this->languages as $language) {
249
            $suffixes += $language->getSuffixes();
250
        }
251
252
        return $suffixes;
253
    }
254
255
    /**
256
     * @return array
257
     */
258
    protected function getSalutations()
259
    {
260
        $salutations = [];
261
262
        /** @var LanguageInterface $language */
263
        foreach ($this->languages as $language) {
264
            $salutations += $language->getSalutations();
265
        }
266
267
        return $salutations;
268
    }
269
270
    /**
271
     * @return array
272
     */
273
    public function getNicknameDelimiters(): array
274
    {
275
        return $this->nicknameDelimiters;
276
    }
277
278
    /**
279
     * @param array $nicknameDelimiters
280
     * @return Parser
281
     */
282
    public function setNicknameDelimiters(array $nicknameDelimiters): Parser
283
    {
284
        $this->nicknameDelimiters = $nicknameDelimiters;
285
286
        return $this;
287
    }
288
289
    /**
290
     * @return int
291
     */
292
    public function getMaxSalutationIndex(): int
293
    {
294
        return $this->maxSalutationIndex;
295
    }
296
297
    /**
298
     * @param int $maxSalutationIndex
299
     * @return Parser
300
     */
301
    public function setMaxSalutationIndex(int $maxSalutationIndex): Parser
302
    {
303
        $this->maxSalutationIndex = $maxSalutationIndex;
304
305
        return $this;
306
    }
307
308
    /**
309
     * @return int
310
     */
311
    public function getMaxCombinedInitials(): int
312
    {
313
        return $this->maxCombinedInitials;
314
    }
315
316
    /**
317
     * @param int $maxCombinedInitials
318
     * @return Parser
319
     */
320
    public function setMaxCombinedInitials(int $maxCombinedInitials): Parser
321
    {
322
        $this->maxCombinedInitials = $maxCombinedInitials;
323
324
        return $this;
325
    }
326
}
327