Completed
Pull Request — master (#22)
by
unknown
02:30
created

Parser::initialsAllowed()   A

Complexity

Conditions 2
Paths 2

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

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
272
        }
273
    }
274
275
    /**
276
     * @return array
277
     */
278
    public function getNicknameDelimiters(): array
279
    {
280
        return $this->nicknameDelimiters;
281
    }
282
283
    /**
284
     * @param array $nicknameDelimiters
285
     * @return Parser
286
     */
287
    public function setNicknameDelimiters(array $nicknameDelimiters): Parser
288
    {
289
        $this->nicknameDelimiters = $nicknameDelimiters;
290
291
        return $this;
292
    }
293
294
    /**
295
     * @return int
296
     */
297
    public function getMaxSalutationIndex(): int
298
    {
299
        return $this->maxSalutationIndex;
300
    }
301
302
    /**
303
     * @param int $maxSalutationIndex
304
     * @return Parser
305
     */
306
    public function setMaxSalutationIndex(int $maxSalutationIndex): Parser
307
    {
308
        $this->maxSalutationIndex = $maxSalutationIndex;
309
310
        return $this;
311
    }
312
}
313