15
15
* Converts words between singular and plural forms.
16
16
*
17
17
* @author Bernhard Schussek <bschussek@gmail.com>
18
- *
19
- * @internal
20
18
*/
21
19
final class Inflector
22
20
{
23
21
/**
24
22
* Map English plural to singular suffixes.
25
23
*
26
- * @var array
27
- *
28
24
* @see http://english-zone.com/spelling/plurals.html
29
25
*/
30
26
private static $ pluralMap = [
@@ -142,175 +138,178 @@ final class Inflector
142
138
/**
143
139
* Map English singular to plural suffixes.
144
140
*
145
- * @var array
146
- *
147
141
* @see http://english-zone.com/spelling/plurals.html
148
142
*/
149
- private static $ singularMap = array (
143
+ private static $ singularMap = [
150
144
// First entry: singular suffix, reversed
151
145
// Second entry: length of singular suffix
152
146
// Third entry: Whether the suffix may succeed a vocal
153
147
// Fourth entry: Whether the suffix may succeed a consonant
154
148
// Fifth entry: plural suffix, normal
155
149
156
150
// criterion (criteria)
157
- array ( 'airetirc ' , 8 , false , false , 'criterion ' ) ,
151
+ [ 'airetirc ' , 8 , false , false , 'criterion ' ] ,
158
152
159
153
// nebulae (nebula)
160
- array ( 'aluben ' , 6 , false , false , 'nebulae ' ) ,
154
+ [ 'aluben ' , 6 , false , false , 'nebulae ' ] ,
161
155
162
156
// children (child)
163
- array ( 'dlihc ' , 5 , true , true , 'children ' ) ,
157
+ [ 'dlihc ' , 5 , true , true , 'children ' ] ,
164
158
165
159
// prices (price)
166
- array ( 'eci ' , 3 , false , true , 'ices ' ) ,
160
+ [ 'eci ' , 3 , false , true , 'ices ' ] ,
167
161
168
162
// services (service)
169
- array ( 'ecivres ' , 7 , true , true , 'services ' ) ,
163
+ [ 'ecivres ' , 7 , true , true , 'services ' ] ,
170
164
171
165
// lives (life), wives (wife)
172
- array ( 'efi ' , 3 , false , true , 'ives ' ) ,
166
+ [ 'efi ' , 3 , false , true , 'ives ' ] ,
173
167
174
168
// selfies (selfie)
175
- array ( 'eifles ' , 6 , true , true , 'selfies ' ) ,
169
+ [ 'eifles ' , 6 , true , true , 'selfies ' ] ,
176
170
177
171
// movies (movie)
178
- array ( 'eivom ' , 5 , true , true , 'movies ' ) ,
172
+ [ 'eivom ' , 5 , true , true , 'movies ' ] ,
179
173
180
174
// lice (louse)
181
- array ( 'esuol ' , 5 , false , true , 'lice ' ) ,
175
+ [ 'esuol ' , 5 , false , true , 'lice ' ] ,
182
176
183
177
// mice (mouse)
184
- array ( 'esuom ' , 5 , false , true , 'mice ' ) ,
178
+ [ 'esuom ' , 5 , false , true , 'mice ' ] ,
185
179
186
180
// geese (goose)
187
- array ( 'esoo ' , 4 , false , true , 'eese ' ) ,
181
+ [ 'esoo ' , 4 , false , true , 'eese ' ] ,
188
182
189
183
// houses (house), bases (base)
190
- array ( 'es ' , 2 , true , true , 'ses ' ) ,
184
+ [ 'es ' , 2 , true , true , 'ses ' ] ,
191
185
192
186
// geese (goose)
193
- array ( 'esoog ' , 5 , true , true , 'geese ' ) ,
187
+ [ 'esoog ' , 5 , true , true , 'geese ' ] ,
194
188
195
189
// caves (cave)
196
- array ( 'ev ' , 2 , true , true , 'ves ' ) ,
190
+ [ 'ev ' , 2 , true , true , 'ves ' ] ,
197
191
198
192
// drives (drive)
199
- array ( 'evird ' , 5 , false , true , 'drives ' ) ,
193
+ [ 'evird ' , 5 , false , true , 'drives ' ] ,
200
194
201
195
// objectives (objective), alternative (alternatives)
202
- array ( 'evit ' , 4 , true , true , 'tives ' ) ,
196
+ [ 'evit ' , 4 , true , true , 'tives ' ] ,
203
197
204
198
// moves (move)
205
- array ( 'evom ' , 4 , true , true , 'moves ' ) ,
199
+ [ 'evom ' , 4 , true , true , 'moves ' ] ,
206
200
207
201
// staves (staff)
208
- array ( 'ffats ' , 5 , true , true , 'staves ' ) ,
202
+ [ 'ffats ' , 5 , true , true , 'staves ' ] ,
209
203
210
204
// hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf)
211
- array ( 'ff ' , 2 , true , true , 'ffs ' ) ,
205
+ [ 'ff ' , 2 , true , true , 'ffs ' ] ,
212
206
213
207
// hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf)
214
- array ( 'f ' , 1 , true , true , array ( 'fs ' , 'ves ' )) ,
208
+ [ 'f ' , 1 , true , true , [ 'fs ' , 'ves ' ]] ,
215
209
216
210
// arches (arch)
217
- array ( 'hc ' , 2 , true , true , 'ches ' ) ,
211
+ [ 'hc ' , 2 , true , true , 'ches ' ] ,
218
212
219
213
// bushes (bush)
220
- array ( 'hs ' , 2 , true , true , 'shes ' ) ,
214
+ [ 'hs ' , 2 , true , true , 'shes ' ] ,
221
215
222
216
// teeth (tooth)
223
- array ( 'htoot ' , 5 , true , true , 'teeth ' ) ,
217
+ [ 'htoot ' , 5 , true , true , 'teeth ' ] ,
224
218
225
219
// bacteria (bacterium), criteria (criterion), phenomena (phenomenon)
226
- array ('mu ' , 2 , true , true , 'a ' ),
227
-
228
- // echoes (echo)
229
- array ('ohce ' , 4 , true , true , 'echoes ' ),
220
+ ['mu ' , 2 , true , true , 'a ' ],
230
221
231
222
// men (man), women (woman)
232
- array ( 'nam ' , 3 , true , true , 'men ' ) ,
223
+ [ 'nam ' , 3 , true , true , 'men ' ] ,
233
224
234
225
// people (person)
235
- array ( 'nosrep ' , 6 , true , true , array ( 'persons ' , 'people ' )) ,
226
+ [ 'nosrep ' , 6 , true , true , [ 'persons ' , 'people ' ]] ,
236
227
237
228
// bacteria (bacterium), criteria (criterion), phenomena (phenomenon)
238
- array ( 'noi ' , 3 , true , true , 'ions ' ) ,
229
+ [ 'noi ' , 3 , true , true , 'ions ' ] ,
239
230
240
231
// bacteria (bacterium), criteria (criterion), phenomena (phenomenon)
241
- array ('no ' , 2 , true , true , 'a ' ),
232
+ ['no ' , 2 , true , true , 'a ' ],
233
+
234
+ // echoes (echo)
235
+ ['ohce ' , 4 , true , true , 'echoes ' ],
236
+
237
+ // heroes (hero)
238
+ ['oreh ' , 4 , true , true , 'heroes ' ],
242
239
243
240
// atlases (atlas)
244
- array ( 'salta ' , 5 , true , true , 'atlases ' ) ,
241
+ [ 'salta ' , 5 , true , true , 'atlases ' ] ,
245
242
246
243
// irises (iris)
247
- array ( 'siri ' , 4 , true , true , 'irises ' ) ,
244
+ [ 'siri ' , 4 , true , true , 'irises ' ] ,
248
245
249
246
// analyses (analysis), ellipses (ellipsis), neuroses (neurosis)
250
247
// theses (thesis), emphases (emphasis), oases (oasis),
251
248
// crises (crisis)
252
- array ( 'sis ' , 3 , true , true , 'ses ' ) ,
249
+ [ 'sis ' , 3 , true , true , 'ses ' ] ,
253
250
254
251
// accesses (access), addresses (address), kisses (kiss)
255
- array ( 'ss ' , 2 , true , false , 'sses ' ) ,
252
+ [ 'ss ' , 2 , true , false , 'sses ' ] ,
256
253
257
254
// syllabi (syllabus)
258
- array ( 'suballys ' , 8 , true , true , 'syllabi ' ) ,
255
+ [ 'suballys ' , 8 , true , true , 'syllabi ' ] ,
259
256
260
257
// buses (bus)
261
- array ('sub ' , 3 , true , true , 'buses ' ),
258
+ ['sub ' , 3 , true , true , 'buses ' ],
259
+
260
+ // circuses (circus)
261
+ ['suc ' , 3 , true , true , 'cuses ' ],
262
262
263
263
// fungi (fungus), alumni (alumnus), syllabi (syllabus), radii (radius)
264
- array ( 'su ' , 2 , true , true , 'i ' ) ,
264
+ [ 'su ' , 2 , true , true , 'i ' ] ,
265
265
266
266
// news (news)
267
- array ( 'swen ' , 4 , true , true , 'news ' ) ,
267
+ [ 'swen ' , 4 , true , true , 'news ' ] ,
268
268
269
269
// feet (foot)
270
- array ( 'toof ' , 4 , true , true , 'feet ' ) ,
270
+ [ 'toof ' , 4 , true , true , 'feet ' ] ,
271
271
272
272
// chateaux (chateau), bureaus (bureau)
273
- array ( 'uae ' , 3 , false , true , array ( 'eaus ' , 'eaux ' )) ,
273
+ [ 'uae ' , 3 , false , true , [ 'eaus ' , 'eaux ' ]] ,
274
274
275
275
// oxen (ox)
276
- array ( 'xo ' , 2 , false , false , 'oxen ' ) ,
276
+ [ 'xo ' , 2 , false , false , 'oxen ' ] ,
277
277
278
278
// hoaxes (hoax)
279
- array ( 'xaoh ' , 4 , true , false , 'hoaxes ' ) ,
279
+ [ 'xaoh ' , 4 , true , false , 'hoaxes ' ] ,
280
280
281
281
// indices (index)
282
- array ( 'xedni ' , 5 , false , true , array ( 'indicies ' , 'indexes ' )) ,
282
+ [ 'xedni ' , 5 , false , true , [ 'indicies ' , 'indexes ' ]] ,
283
283
284
284
// indexes (index), matrixes (matrix)
285
- array ( 'x ' , 1 , true , false , array ( 'cies ' , 'xes ' )) ,
285
+ [ 'x ' , 1 , true , false , [ 'cies ' , 'xes ' ]] ,
286
286
287
287
// appendices (appendix)
288
- array ( 'xi ' , 2 , false , true , 'ices ' ) ,
288
+ [ 'xi ' , 2 , false , true , 'ices ' ] ,
289
289
290
290
// babies (baby)
291
- array ( 'y ' , 1 , false , true , 'ies ' ) ,
291
+ [ 'y ' , 1 , false , true , 'ies ' ] ,
292
292
293
293
// quizzes (quiz)
294
- array ( 'ziuq ' , 4 , true , false , 'quizzes ' ) ,
294
+ [ 'ziuq ' , 4 , true , false , 'quizzes ' ] ,
295
295
296
296
// waltzes (waltz)
297
- array ( 'z ' , 1 , true , false , 'zes ' ) ,
298
- ) ;
297
+ [ 'z ' , 1 , true , true , 'zes ' ] ,
298
+ ] ;
299
299
300
300
/**
301
- * A list of words which should not be inflected.
302
- *
303
- * @var array
301
+ * A list of words which should not be inflected, reversed.
304
302
*/
305
- private static $ uninflected = array (
306
- 'data ' ,
307
- 'deer ' ,
308
- 'feedback ' ,
309
- 'fish ' ,
310
- 'moose ' ,
311
- 'series ' ,
312
- 'sheep ' ,
313
- );
303
+ private static $ uninflected = [
304
+ 'atad ' ,
305
+ 'reed ' ,
306
+ 'kcabdeef ' ,
307
+ 'hsif ' ,
308
+ 'ofni ' ,
309
+ 'esoom ' ,
310
+ 'seires ' ,
311
+ 'peehs ' ,
312
+ ];
314
313
315
314
/**
316
315
* This class should not be instantiated.
@@ -327,10 +326,7 @@ private function __construct()
327
326
*
328
327
* @param string $plural A word in plural form
329
328
*
330
- * @return string|array The singular form or an array of possible singular
331
- * forms
332
- *
333
- * @internal
329
+ * @return string|array The singular form or an array of possible singular forms
334
330
*/
335
331
public static function singularize (string $ plural )
336
332
{
@@ -339,7 +335,7 @@ public static function singularize(string $plural)
339
335
$ pluralLength = \strlen ($ lowerPluralRev );
340
336
341
337
// Check if the word is one which is not inflected, return early if so
342
- if (in_array (strtolower ( $ plural ) , self ::$ uninflected , true )) {
338
+ if (\ in_array ($ lowerPluralRev , self ::$ uninflected , true )) {
343
339
return $ plural ;
344
340
}
345
341
@@ -416,19 +412,16 @@ public static function singularize(string $plural)
416
412
*
417
413
* @param string $singular A word in plural form
418
414
*
419
- * @return string|array The plural form or an array of possible plural
420
- * forms
421
- *
422
- * @internal
415
+ * @return string|array The plural form or an array of possible plural forms
423
416
*/
424
417
public static function pluralize (string $ singular )
425
418
{
426
419
$ singularRev = strrev ($ singular );
427
420
$ lowerSingularRev = strtolower ($ singularRev );
428
- $ singularLength = strlen ($ lowerSingularRev );
421
+ $ singularLength = \ strlen ($ lowerSingularRev );
429
422
430
423
// Check if the word is one which is not inflected, return early if so
431
- if (in_array (strtolower ( $ singular ) , self ::$ uninflected , true )) {
424
+ if (\ in_array ($ lowerSingularRev , self ::$ uninflected , true )) {
432
425
return $ singular ;
433
426
}
434
427
@@ -474,8 +467,8 @@ public static function pluralize(string $singular)
474
467
// the singular suffix too
475
468
$ firstUpper = ctype_upper ($ singularRev [$ j - 1 ]);
476
469
477
- if (is_array ($ newSuffix )) {
478
- $ plurals = array () ;
470
+ if (\ is_array ($ newSuffix )) {
471
+ $ plurals = [] ;
479
472
480
473
foreach ($ newSuffix as $ newSuffixEntry ) {
481
474
$ plurals [] = $ newBase .($ firstUpper ? ucfirst ($ newSuffixEntry ) : $ newSuffixEntry );
0 commit comments