Completed
Push — master ( 4be0da...2b28ed )
by Andre
01:45
created

LastnameMapper::map()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 12
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 6
nc 2
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): array
25
    {
26
        if (!$this->options['match_single'] && count($parts) < 2) {
27
            return $parts;
28
        }
29
30
        $parts = array_reverse($parts);
31
32
        $parts = $this->mapReversedParts($parts);
33
34
        return array_reverse($parts);
35
    }
36
37
    /**
38
     * @param array $parts
39
     * @return array
40
     */
41
    protected function mapReversedParts(array $parts): array
42
    {
43
        $length = count($parts);
44
45
        foreach ($parts as $k => $part) {
46
            if ($part instanceof Suffix) {
47
                continue;
48
            }
49
50
            if ($part instanceof AbstractPart) {
51
                break;
52
            }
53
54
            $originalIndex = $length - $k - 1;
55
            $originalParts = array_reverse($parts);
56
57
            if ($this->isFollowedByLastnamePart($originalParts, $originalIndex)) {
58
                if ($this->isApplicablePrefix($originalParts, $originalIndex)) {
59
                    $lastname = new Lastname($part);
60
                    $lastname->setApplyPrefix(true);
61
                    $parts[$k] = $lastname;
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