1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace DaveChild\TextStatistics; |
4
|
|
|
|
5
|
|
|
class Pluralise |
6
|
|
|
{ |
7
|
|
|
/** |
8
|
|
|
* Singularising and Pluralising functions from following URL, released |
9
|
|
|
* under an MIT license and used with thanks: |
10
|
|
|
* http://kuwamoto.org/2007/12/17/improved-pluralizing-in-php-actionscript-and-ror/ |
11
|
|
|
*/ |
12
|
|
|
private static $plural = array( |
13
|
|
|
'/(quiz)$/i' => "$1zes", |
14
|
|
|
'/^(ox)$/i' => "$1en", |
15
|
|
|
'/([m|l])ouse$/i' => "$1ice", |
16
|
|
|
'/(matrix|vertex|index)$/i'=> "$1ices", |
17
|
|
|
'/(x|ch|ss|sh)$/i' => "$1es", |
18
|
|
|
'/([^aeiouy]|qu)y$/i' => "$1ies", |
19
|
|
|
'/(hive)$/i' => "$1s", |
20
|
|
|
'/(?:([^f])fe|([lr])f)$/i' => "$1$2ves", |
21
|
|
|
'/(shea|lea|loa|thie)f$/i' => "$1ves", |
22
|
|
|
'/sis$/i' => "ses", |
23
|
|
|
'/([ti])um$/i' => "$1a", |
24
|
|
|
'/(tomat|potat|ech|her|vet)o$/i'=> "$1oes", |
25
|
|
|
'/(bu)s$/i' => "$1ses", |
26
|
|
|
'/(alias)$/i' => "$1es", |
27
|
|
|
'/(octop)us$/i' => "$1i", |
28
|
|
|
'/(ax|test)is$/i' => "$1es", |
29
|
|
|
'/(us)$/i' => "$1es", |
30
|
|
|
'/s$/i' => "s" |
31
|
|
|
); |
32
|
|
|
|
33
|
|
|
private static $singular = array( |
34
|
|
|
'/(quiz)zes$/i' => "$1", |
35
|
|
|
'/(matr)ices$/i' => "$1ix", |
36
|
|
|
'/(vert|ind)ices$/i' => "$1ex", |
37
|
|
|
'/^(ox)en$/i' => "$1", |
38
|
|
|
'/(alias)es$/i' => "$1", |
39
|
|
|
'/(octop|vir)i$/i' => "$1us", |
40
|
|
|
'/(cris|ax|test)es$/i' => "$1is", |
41
|
|
|
'/(shoe)s$/i' => "$1", |
42
|
|
|
'/(o)es$/i' => "$1", |
43
|
|
|
'/(bus)es$/i' => "$1", |
44
|
|
|
'/([m|l])ice$/i' => "$1ouse", |
45
|
|
|
'/(x|ch|ss|sh)es$/i' => "$1", |
46
|
|
|
'/(m)ovies$/i' => "$1ovie", |
47
|
|
|
'/(s)eries$/i' => "$1eries", |
48
|
|
|
'/([^aeiouy]|qu)ies$/i' => "$1y", |
49
|
|
|
'/([lr])ves$/i' => "$1f", |
50
|
|
|
'/(tive)s$/i' => "$1", |
51
|
|
|
'/(hive)s$/i' => "$1", |
52
|
|
|
'/(li|wi|kni)ves$/i' => "$1fe", |
53
|
|
|
'/(shea|loa|lea|thie)ves$/i'=> "$1f", |
54
|
|
|
'/(^analy)ses$/i' => "$1sis", |
55
|
|
|
'/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i' => "$1$2sis", |
56
|
|
|
'/([ti])a$/i' => "$1um", |
57
|
|
|
'/(n)ews$/i' => "$1ews", |
58
|
|
|
'/(h|bl)ouses$/i' => "$1ouse", |
59
|
|
|
'/(corpse)s$/i' => "$1", |
60
|
|
|
'/(us)es$/i' => "$1", |
61
|
|
|
'/s$/i' => "" |
62
|
|
|
); |
63
|
|
|
|
64
|
|
|
private static $irregular = array( |
65
|
|
|
'child' => 'children', |
66
|
|
|
'foot' => 'feet', |
67
|
|
|
'goose' => 'geese', |
68
|
|
|
'man' => 'men', |
69
|
|
|
'mouse' => 'mice', |
70
|
|
|
'move' => 'moves', |
71
|
|
|
'person' => 'people', |
72
|
|
|
'sex' => 'sexes', |
73
|
|
|
'tooth' => 'teeth', |
74
|
|
|
); |
75
|
|
|
|
76
|
|
|
// Some words are only uncountable sometimes. For example, "blues" can be |
77
|
|
|
// uncountable when referring to music, but countable when referring to |
78
|
|
|
// multiple colours. |
79
|
|
|
private static $uncountable = array( |
80
|
|
|
'beef', |
81
|
|
|
'bison', |
82
|
|
|
'buffalo', |
83
|
|
|
'carbon', |
84
|
|
|
'chemistry', |
85
|
|
|
'copper', |
86
|
|
|
'geometry', |
87
|
|
|
'gold', |
88
|
|
|
'cs', |
89
|
|
|
'css', |
90
|
|
|
'deer', |
91
|
|
|
'equipment', |
92
|
|
|
'fish', |
93
|
|
|
'furniture', |
94
|
|
|
'information', |
95
|
|
|
'mathematics', |
96
|
|
|
'money', |
97
|
|
|
'moose', |
98
|
|
|
'nitrogen', |
99
|
|
|
'oxygen', |
100
|
|
|
'rice', |
101
|
|
|
'series', |
102
|
|
|
'sheep', |
103
|
|
|
'species', |
104
|
|
|
'surgery', |
105
|
|
|
'traffic', |
106
|
|
|
'water' |
107
|
|
|
); |
108
|
|
|
|
109
|
|
|
/** |
110
|
|
|
* Get the plural of the word passed in. |
111
|
|
|
* @param string $string Word to pluralise |
112
|
|
|
* @return string Pluralised word |
113
|
|
|
*/ |
114
|
2 |
View Code Duplication |
public static function getPlural($string) |
|
|
|
|
115
|
|
|
{ |
116
|
|
|
// save some time in the case that singular and plural are the same |
117
|
2 |
|
if (in_array(strtolower($string), self::$uncountable)) { |
118
|
2 |
|
return $string; |
119
|
|
|
} |
120
|
|
|
|
121
|
|
|
// check to see if already plural and irregular |
122
|
1 |
|
foreach (self::$irregular as $pattern => $result) { |
123
|
1 |
|
$_pattern = '/' . $result . '$/i'; |
124
|
1 |
|
if (preg_match($_pattern, $string)) { |
125
|
1 |
|
return $string; |
126
|
|
|
} |
127
|
1 |
|
} |
128
|
|
|
|
129
|
|
|
// check for irregular singular forms |
130
|
1 |
|
foreach (self::$irregular as $pattern => $result) { |
131
|
1 |
|
$pattern = '/' . $pattern . '$/i'; |
132
|
1 |
|
if (preg_match($pattern, $string)) { |
133
|
1 |
|
return preg_replace($pattern, $result, $string); |
134
|
|
|
} |
135
|
1 |
|
} |
136
|
|
|
|
137
|
|
|
// check for matches using regular expressions |
138
|
1 |
|
foreach (self::$plural as $pattern => $result) { |
139
|
1 |
|
if (preg_match($pattern, $string)) { |
140
|
1 |
|
return preg_replace($pattern, $result, $string); |
141
|
|
|
} |
142
|
1 |
|
} |
143
|
|
|
|
144
|
|
|
// No pattern match. Add an "s". |
145
|
1 |
|
return $string . 's'; |
146
|
|
|
} |
147
|
|
|
|
148
|
|
|
/** |
149
|
|
|
* Get the singular of the word passed in. |
150
|
|
|
* @param string $string Word to singularise |
151
|
|
|
* @return string Singularised word |
152
|
|
|
*/ |
153
|
21 |
View Code Duplication |
public static function getSingular($string) |
|
|
|
|
154
|
|
|
{ |
155
|
|
|
// save some time in the case that singular and plural are the same |
156
|
21 |
|
if (in_array(strtolower($string), self::$uncountable)) { |
157
|
6 |
|
return $string; |
158
|
|
|
} |
159
|
|
|
|
160
|
|
|
// check to see if already singular and irregular |
161
|
21 |
|
foreach (self::$irregular as $pattern => $result) { |
162
|
21 |
|
$_pattern = '/' . $pattern . '$/i'; |
163
|
21 |
|
if (preg_match($_pattern, $string)) { |
164
|
7 |
|
return $string; |
165
|
|
|
} |
166
|
21 |
|
} |
167
|
|
|
|
168
|
|
|
// check for irregular plural forms |
169
|
21 |
|
foreach (self::$irregular as $result => $pattern) { |
170
|
21 |
|
$pattern = '/' . $pattern . '$/i'; |
171
|
21 |
|
if (preg_match($pattern, $string)) { |
172
|
13 |
|
return preg_replace($pattern, $result, $string); |
173
|
|
|
} |
174
|
21 |
|
} |
175
|
|
|
|
176
|
|
|
// check for matches using regular expressions |
177
|
21 |
|
foreach (self::$singular as $pattern => $result) { |
178
|
21 |
|
if (preg_match($pattern, $string)) { |
179
|
21 |
|
return preg_replace($pattern, $result, $string); |
180
|
|
|
} |
181
|
21 |
|
} |
182
|
|
|
|
183
|
21 |
|
return $string; |
184
|
|
|
} |
185
|
|
|
} |
186
|
|
|
|
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.