Completed
Push — master ( 09801d...b7f648 )
by Andre
01:52
created

LastnameMapper::mapReversedParts()   B

Complexity

Conditions 6
Paths 4

Size

Total Lines 27
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 27
rs 8.439
c 0
b 0
f 0
cc 6
eloc 15
nc 4
nop 1
1
<?php
2
3
namespace TheIconic\NameParser\Mapper;
4
5
use TheIconic\NameParser\Part\AbstractPart;
6
use TheIconic\NameParser\Part\Lastname;
7
use TheIconic\NameParser\Part\Suffix;
8
9
class LastnameMapper extends AbstractMapper
10
{
11
    /**
12
     * @var array options
13
     */
14
    protected $options = [
15
        'match_single' => false,
16
    ];
17
18
    /**
19
     * map lastnames in the parts array
20
     *
21
     * @param array $parts the name parts
22
     * @return array the mapped parts
23
     */
24
    public function map(array $parts)
25
    {
26
        if (!$this->options['match_single'] && count($parts) < 2) {
27
            return $parts;
28
        }
29
30
        if (count($parts) === 2 && $parts[0] instanceof AbstractPart) {
31
            $parts[1] = new Lastname($parts[1]);
32
        }
33
34
        $parts = array_reverse($parts);
35
36
        $parts = $this->mapReversedParts($parts);
37
38
        return array_reverse($parts);
39
    }
40
41
    /**
42
     * @param array $parts
43
     * @return array
44
     */
45
    protected function mapReversedParts(array $parts): array
46
    {
47
        foreach ($parts as $k => $part) {
48
            if ($part instanceof Suffix) {
49
                continue;
50
            }
51
52
            if ($part instanceof AbstractPart) {
53
                break;
54
            }
55
56
            $originalIndex = count($parts) - $k - 1;
57
            $originalParts = array_reverse($parts);
58
59
            if ($this->isFollowedByLastnamePart($originalParts, $originalIndex)) {
60
                if ($this->isApplicablePrefix($originalParts, $originalIndex)) {
61
                    $parts[$k] = new Lastname($part);
62
                    continue;
63
                }
64
                break;
65
            }
66
67
            $parts[$k] = new Lastname($part);
68
        }
69
70
        return $parts;
71
    }
72
73
    /**
74
     * @param array $parts
75
     * @param int $index
76
     * @return bool
77
     */
78
    protected function isFollowedByLastnamePart(array $parts, int $index): bool
79
    {
80
        $next = $index + 1;
81
82
        return (isset($parts[$next]) && $parts[$next] instanceof Lastname);
83
    }
84
85
    /**
86
     * Assuming that the part at the given index is matched as a prefix,
87
     * determines if the prefix should be applied to the lastname.
88
     *
89
     * We only apply it to the lastname if we already have at least one
90
     * lastname part and there are other parts left in
91
     * the name (this effectively prioritises firstname over prefix matching).
92
     *
93
     * This expects the parts array and index to be in the original order.
94
     *
95
     * @param array $parts
96
     * @param int $index
97
     * @return bool
98
     */
99
    protected function isApplicablePrefix(array $parts, int $index): bool
100
    {
101
        if (!Lastname::isPrefix($parts[$index])) {
102
            return false;
103
        }
104
105
        return $this->hasUnmappedPartsBefore($parts, $index);
106
    }
107
}
108