Completed
Pull Request — master (#3)
by Andre
01:34
created

Parser::addLanguages()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 3
nc 2
nop 0
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
    public function __construct(array $languages = [])
32
    {
33
        if (empty($languages)) {
34
            $languages = [new English()];
35
        }
36
37
        $this->languages = $languages;
38
    }
39
40
    /**
41
     * split full names into the following parts:
42
     * - prefix / salutation  (Mr., Mrs., etc)
43
     * - given name / first name
44
     * - middle initials
45
     * - surname / last name
46
     * - suffix (II, Phd, Jr, etc)
47
     *
48
     * @param string $name
49
     * @return Name
50
     */
51
    public function parse($name): Name
52
    {
53
        $name = $this->normalize($name);
54
55
        $segments = explode(',', $name);
56
57
        if (1 < count($segments)) {
58
            return $this->parseSplitName($segments[0], $segments[1], $segments[2] ?? '');
59
        }
60
61
        $parts = explode(' ', $name);
62
63
        foreach ($this->getMappers() as $mapper) {
64
            $parts = $mapper->map($parts);
65
        }
66
67
        return new Name($parts);
68
    }
69
70
    /**
71
     * handles split-parsing of comma-separated name parts
72
     *
73
     * @param $left - the name part left of the comma
74
     * @param $right - the name part right of the comma
75
     *
76
     * @return Name
77
     */
78
    protected function parseSplitName($first, $second, $third): Name
79
    {
80
        $parts = array_merge(
81
            $this->getFirstSegmentParser()->parse($first)->getParts(),
82
            $this->getSecondSegmentParser()->parse($second)->getParts(),
83
            $this->getThirdSegmentParser()->parse($third)->getParts()
84
        );
85
86
        return new Name($parts);
87
    }
88
89
    /**
90
     * @return Parser
91
     */
92 View Code Duplication
    protected function getFirstSegmentParser(): Parser
0 ignored issues
show
Duplication introduced by
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...
93
    {
94
        $parser = new Parser();
95
        $parser->setMappers([
96
            new SalutationMapper($this->getSalutations()),
97
            new SuffixMapper($this->getSuffixes()),
98
            new LastnameMapper($this->getPrefixes(), true),
99
            new FirstnameMapper(),
100
            new MiddlenameMapper(),
101
        ]);
102
103
        return $parser;
104
    }
105
106
    /**
107
     * @return Parser
108
     */
109 View Code Duplication
    protected function getSecondSegmentParser(): Parser
0 ignored issues
show
Duplication introduced by
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...
110
    {
111
        $parser = new Parser();
112
        $parser->setMappers([
113
            new SalutationMapper($this->getSalutations()),
114
            new SuffixMapper($this->getSuffixes(), true),
115
            new NicknameMapper(),
116
            new InitialMapper(true),
117
            new FirstnameMapper(),
118
            new MiddlenameMapper(),
119
        ]);
120
121
        return $parser;
122
    }
123
124
    protected function getThirdSegmentParser(): Parser
125
    {
126
        $parser = new Parser();
127
        $parser->setMappers([
128
            new SuffixMapper($this->getSuffixes(), true),
129
        ]);
130
131
        return $parser;
132
    }
133
134
    /**
135
     * get the mappers for this parser
136
     *
137
     * @return array
138
     */
139
    public function getMappers(): array
140
    {
141
        if (empty($this->mappers)) {
142
            $this->setMappers([
143
                new NicknameMapper(),
144
                new SalutationMapper($this->getSalutations()),
145
                new SuffixMapper($this->getSuffixes()),
146
                new InitialMapper(),
147
                new LastnameMapper($this->getPrefixes()),
148
                new FirstnameMapper(),
149
                new MiddlenameMapper(),
150
            ]);
151
        }
152
153
        return $this->mappers;
154
    }
155
156
    /**
157
     * set the mappers for this parser
158
     *
159
     * @param array $mappers
160
     * @return Parser
161
     */
162
    public function setMappers(array $mappers): Parser
163
    {
164
        $this->mappers = $mappers;
165
166
        return $this;
167
    }
168
169
    /**
170
     * normalize the name
171
     *
172
     * @param string $name
173
     * @return string
174
     */
175
    protected function normalize(string $name): string
176
    {
177
        $whitespace = $this->getWhitespace();
178
179
        $name = trim($name);
180
181
        return preg_replace('/[' . preg_quote($whitespace) . ']+/', ' ', $name);
182
    }
183
184
    /**
185
     * get a string of characters that are supposed to be treated as whitespace
186
     *
187
     * @return string
188
     */
189
    public function getWhitespace(): string
190
    {
191
        return $this->whitespace;
192
    }
193
194
    /**
195
     * set the string of characters that are supposed to be treated as whitespace
196
     *
197
     * @param $whitespace
198
     * @return Parser
199
     */
200
    public function setWhitespace($whitespace): Parser
201
    {
202
        $this->whitespace = $whitespace;
203
204
        return $this;
205
    }
206
207
    /**
208
     *
209
     */
210
    public function addLanguages()
211
    {
212
        foreach (func_get_args() as $language) {
213
            $this->languages[] = $language;
214
        }
215
    }
216
217
    /**
218
     * @return array
219
     */
220
    protected function getPrefixes()
221
    {
222
        $prefixes = [];
223
224
        /** @var LanguageInterface $language */
225
        foreach ($this->languages as $language) {
226
            $prefixes += $language->getLastnamePrefixes();
227
        }
228
229
        return $prefixes;
230
    }
231
232
    /**
233
     * @return array
234
     */
235
    protected function getSuffixes()
236
    {
237
        $suffixes = [];
238
239
        /** @var LanguageInterface $language */
240
        foreach ($this->languages as $language) {
241
            $suffixes += $language->getSuffixes();
242
        }
243
244
        return $suffixes;
245
    }
246
247
    /**
248
     * @return array
249
     */
250
    protected function getSalutations()
251
    {
252
        $salutations = [];
253
254
        /** @var LanguageInterface $language */
255
        foreach ($this->languages as $language) {
256
            $salutations += $language->getSalutations();
257
        }
258
259
        return $salutations;
260
    }
261
}
262