Completed
Pull Request — master (#6)
by
unknown
01:01
created

PersonName::abbreviated()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 0
crap 2
1
<?php
2
3
namespace Webstronauts\PersonName;
4
5
/**
6
 * @property string $first
7
 * @property string $last
8
 * @property string $full
9
 * @property string $familiar
10
 * @property string $abbreviated
11
 * @property string $sorted
12
 * @property string $possessive
13
 * @property string $initials
14
 * @property string $mentionable
15
 */
16
class PersonName
17
{
18
    const POSSESSIVE_FIRST = 'first';
19
    const POSSESSIVE_LAST = 'last';
20
    const POSSESSIVE_FULL = 'full';
21
    const POSSESSIVE_INITIALS = 'initials';
22
    const POSSESSIVE_SORTED = 'sorted';
23
    const POSSESSIVE_ABBREVIATED = 'abbreviated';
24
25
    /**
26
     * @var string
27
     */
28
    private $first;
29
30
    /**
31
     * @var string
32
     */
33
    private $last;
34
35
    /**
36
     * @var array
37
     */
38
    public $wordSplitters = [];
39
40
    /**
41
     * @var array
42
     */
43
    public $lowercaseExceptions = [];
44
45
    /**
46
     * @var array
47
     */
48
    public $uppercaseExceptions = [];
49
50 11
    public static function make(?string $fullName = null): ?self
51
    {
52 11
        $segments = preg_split('/\s/', trim(preg_replace('/\s+/', ' ', $fullName)), 2);
53
54 11
        return $segments[0] ? new static($segments[0], $segments[1] ?? null) : null;
55
    }
56
57
    /**
58
     * Creates a new PersonName instance.
59
     *
60
     * @param string $first
61
     * @param string $last
62
     */
63 29
    public function __construct(string $first, ?string $last = null)
64
    {
65 29
        $this->first = $first;
66 29
        $this->last = $last;
67 29
        $this->wordSplitters = [' ', '-', "O'", "L'", "La'", "D'", "De'", 'St.', 'Mc', 'Mac'];
68 29
        $this->lowercaseExceptions = ['the', 'van', 'den', 'von', 'und', 'der', 'de', 'da', 'of', 'and', "l'", "d'"];
69 29
        $this->uppercaseExceptions = ['III', 'IV', 'VI', 'VII', 'VIII', 'IX'];
70 29
    }
71
72 8
    public function first(): string
73
    {
74 8
        return $this->first;
75
    }
76
77 8
    public function last(): ?string
78
    {
79 8
        return $this->last;
80
    }
81
82
    /**
83
     * Returns first + last, such as "Jason Fried".
84
     *
85
     * @return string
86
     */
87 19
    public function full(): string
88
    {
89 19
        return $this->last ? "{$this->first} {$this->last}" : $this->first;
90
    }
91
92
    /**
93
     * Returns first + last initial, such as "Jason F.".
94
     *
95
     * @return string
96
     */
97 7
    public function familiar(): string
98
    {
99 7
        return $this->last ? "{$this->first} {$this->last[0]}." : $this->first;
100
    }
101
102
    /**
103
     * Returns first initial + last, such as "J. Fried".
104
     *
105
     * @return string
106
     */
107 3
    public function abbreviated(): string
108
    {
109 3
        return $this->last ? "{$this->first[0]}. {$this->last}" : $this->first;
110
    }
111
112
    /**
113
     * Returns last + first for sorting.
114
     *
115
     * @return string
116
     */
117 3
    public function sorted(): string
118
    {
119 3
        return $this->last ? "{$this->last}, {$this->first}" : $this->first;
120
    }
121
122
    /**
123
     * Returns full name with with trailing 's or ' if name ends in s.
124
     *
125
     * @param  string  $method
126
     * @return string
127
     */
128 7
    public function possessive(string $method = self::POSSESSIVE_FULL): string
129
    {
130 7
        return sprintf('%s\'%s', call_user_func([$this, $method]), substr($this, -1) !== 's' ? 's' : '');
131
    }
132
133
    /**
134
     * Returns just the initials.
135
     *
136
     * @return string
137
     */
138 7
    public function initials(): string
139
    {
140 7
        preg_match_all('/([[:word:]])[[:word:]]*/i', preg_replace('/(\(|\[).*(\)|\])/', '', $this), $matches);
141
142 7
        return implode('', end($matches));
143
    }
144
145
    /**
146
     * Returns a mentionable version of the familiar name.
147
     *
148
     * @return string
149
     */
150 3
    public function mentionable(): string
151
    {
152 3
        return strtolower(preg_replace('/\s+/', '', substr($this->familiar, 0, -1)));
153
    }
154
155
    /**
156
     * Returns a proper name case version of the full name.
157
     * @param  string $name Which part of the name to proper case. Default full|first|last.
158
     *
159
     * @return string
160
     */
161 3
    public function proper($name = null): string
162
    {
163 3
        switch ($name) {
164 3
            case 'first':
165 1
                $name = strtolower($this->first());
166 1
                break;
167 2
            case 'last':
168 1
                $name = strtolower($this->last());
169 1
                break;
170
            default:
171 1
                $name = strtolower($this->full());
172
        }
173 3
        foreach ($this->wordSplitters as $delimiter) {
174 3
            $words = explode($delimiter, $name);
175 3
            $newWords = [];
176 3
            foreach ($words as $word) {
177 3
                if (in_array(strtoupper($word), $this->uppercaseExceptions)) {
178
                    $word = strtoupper($word);
179 3
                } elseif (!in_array($word, $this->lowercaseExceptions)) {
180 3
                    $word = ucfirst($word);
181
                }
182 3
                $newWords[] = $word;
183
            }
184
185 3
            if (in_array(strtolower($delimiter), $this->lowercaseExceptions)) {
186 3
                $delimiter = strtolower($delimiter);
187
            }
188
189 3
            $name = implode($delimiter, $newWords);
190
        }
191
192 3
        return $name;
193
    }
194
195
    /**
196
     * Make the methods accessibles as attributes.
197
     *
198
     * @param  string  $attribute
199
     * @return mixed
200
     */
201 27
    public function __get($attribute)
202
    {
203 27
        return call_user_func([$this, $attribute]);
204
    }
205
206 14
    public function __toString(): string
207
    {
208 14
        return $this->full;
209
    }
210
}
211