PluginProbe
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses / 2.7.7
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses v2.7.7
2.10.0 2.10.01 2.9.1 2.9.0 2.8.1 2.8.0 2.7.7 2.7.5 2.7.0 2.6.01 2.6.0 2.5.0 2.4.01 trunk 1.0.90 1.0.91 1.0.92 1.0.93 1.0.94 1.0.95 1.0.96 1.0.97 1.0.98 1.0.99 1.1.0 All 77 releases
fluent-community / vendor / wpfluent / framework / src / WPFluent / Support / Pluralizer.php

Pluralizer.php in FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses 2.7.7, at vendor/wpfluent/framework/src/WPFluent/Support/Pluralizer.php

412 lines 10.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentCommunity\Framework\Support;
4
5 class Pluralizer
6 {
7 /**
8 * Plural word form rules.
9 *
10 * @var array<string,string>
11 */
12 public static array $plural = [
13 '/(quiz)$/i' => '$1zes',
14 '/^(ox)$/i' => '$1en',
15 '/([ml])ouse$/i' => '$1ice',
16 '/(matr|vert|ind)(?:ix|ex)$/i' => '$1ices',
17 '/(stoma|epo|monar|matriar|patriar|oligar|eunu)ch$/i' => '$1chs',
18 '/(x|ch|ss|sh)$/i' => '$1es',
19 '/([^aeiouy]|qu)y$/i' => '$1ies',
20 '/(hive)$/i' => '$1s',
21 '/(?:([^f])fe|([lr])f)$/i' => '$1$2ves',
22 '/(shea|lea|loa|thie)f$/i' => '$1ves',
23 '/sis$/i' => 'ses',
24 '/([ti])um$/i' => '$1a',
25 '/(torped|embarg|tomat|potat|ech|her|vet)o$/i' => '$1oes',
26 '/(bu)s$/i' => '$1ses',
27 '/(alias)$/i' => '$1es',
28 '/(fung)us$/i' => '$1i',
29 '/(ax|test)is$/i' => '$1es',
30 '/(us)$/i' => '$1es',
31 '/s$/i' => 's',
32 '/$/' => 's',
33 ];
34
35 /**
36 * Singular word form rules.
37 *
38 * @var array<string,string>
39 */
40 public static array $singular = [
41 '/(quiz)zes$/i' => '$1',
42 '/(matr)ices$/i' => '$1ix',
43 '/(vert|vort|ind)ices$/i' => '$1ex',
44 '/^(ox)en$/i' => '$1',
45 '/(alias)es$/i' => '$1',
46 '/(octop|vir|fung)i$/i' => '$1us',
47 '/(cris|ax|test)es$/i' => '$1is',
48 '/(shoe)s$/i' => '$1',
49 '/(o)es$/i' => '$1',
50 '/(bus)es$/i' => '$1',
51 '/([ml])ice$/i' => '$1ouse',
52 '/(x|ch|ss|sh)es$/i' => '$1',
53 '/(m)ovies$/i' => '$1ovie',
54 '/(s)eries$/i' => '$1eries',
55 '/([^aeiouy]|qu)ies$/i' => '$1y',
56 '/([lr])ves$/i' => '$1f',
57 '/(tive)s$/i' => '$1',
58 '/(hive)s$/i' => '$1',
59 '/(li|wi|kni)ves$/i' => '$1fe',
60 '/(shea|loa|lea|thie)ves$/i' => '$1f',
61 '/(^analy)ses$/i' => '$1sis',
62 '/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i' => '$1$2sis',
63 '/([ti])a$/i' => '$1um',
64 '/(n)ews$/i' => '$1ews',
65 '/(h|bl)ouses$/i' => '$1ouse',
66 '/(corpse)s$/i' => '$1',
67 '/(gallows|headquarters)$/i' => '$1',
68 '/(us)es$/i' => '$1',
69 '/(us|ss)$/i' => '$1',
70 '/s$/i' => '',
71 ];
72
73 /**
74 * Irregular word forms.
75 *
76 * @var array<string,string> Singular to plural mappings
77 */
78 public static array $irregular = [
79 'child' => 'children',
80 'corpus' => 'corpora',
81 'criterion' => 'criteria',
82 'foot' => 'feet',
83 'freshman' => 'freshmen',
84 'goose' => 'geese',
85 'genus' => 'genera',
86 'human' => 'humans',
87 'man' => 'men',
88 'woman' => 'women',
89 'mouse' => 'mice',
90 'louse' => 'lice',
91 'person' => 'people',
92 'tooth' => 'teeth',
93 'ox' => 'oxen',
94 'wolf' => 'wolves',
95 'calf' => 'calves',
96 'leaf' => 'leaves',
97 'loaf' => 'loaves',
98 'life' => 'lives',
99 'wife' => 'wives',
100 'knife' => 'knives',
101 'self' => 'selves',
102 'thief' => 'thieves',
103 'datum' => 'data',
104 'bacterium' => 'bacteria',
105 'medium' => 'media',
106 'analysis' => 'analyses',
107 'diagnosis' => 'diagnoses',
108 'parenthesis' => 'parentheses',
109 'hypothesis' => 'hypotheses',
110 'thesis' => 'theses',
111 'crisis' => 'crises',
112 'oasis' => 'oases',
113 'phenomenon' => 'phenomena',
114 'nucleus' => 'nuclei',
115 'radius' => 'radii',
116 'stimulus' => 'stimuli',
117 'syllabus' => 'syllabi',
118 'index' => 'indices',
119 'appendix' => 'appendices',
120 'matrix' => 'matrices',
121 'axis' => 'axes',
122 'alumnus' => 'alumni',
123 'formula' => 'formulae',
124 'move' => 'moves',
125 'tax' => 'taxes',
126 'tech' => 'techs',
127 'cactus' => 'cacti',
128 'fungus' => 'fungi',
129 'focus' => 'foci',
130 'ellipsis' => 'ellipses',
131 'basis' => 'bases',
132 'vertebra' => 'vertebrae',
133 'stratum' => 'strata',
134 'hero' => 'heroes',
135 'echo' => 'echoes',
136 'potato' => 'potatoes',
137 'tomato' => 'tomatoes',
138 ];
139
140 /**
141 * Uncountable word forms.
142 *
143 * @var string[]
144 */
145 public static array $uncountable = [
146 'advice',
147 'air',
148 'alcohol',
149 'art',
150 'bison',
151 'bread',
152 'butter',
153 'cheese',
154 'chassis',
155 'clothing',
156 'commerce',
157 'compensation',
158 'coreopsis',
159 'data',
160 'deer',
161 'dust',
162 'education',
163 'electricity',
164 'equipment',
165 'evidence',
166 'fashion',
167 'feedback',
168 'fish',
169 'flour',
170 'food',
171 'furniture',
172 'garbage',
173 'gold',
174 'grass',
175 'happiness',
176 'homework',
177 'honesty',
178 'information',
179 'jewelry',
180 'knowledge',
181 'luggage',
182 'mathematics',
183 'meat',
184 'money',
185 'moose',
186 'music',
187 'news',
188 'nutrition',
189 'offspring',
190 'oil',
191 'oxygen',
192 'patience',
193 'permission',
194 'plankton',
195 'poetry',
196 'police',
197 'progress',
198 'rain',
199 'rice',
200 'salt',
201 'series',
202 'sheep',
203 'shopping',
204 'software',
205 'species',
206 'sugar',
207 'swine',
208 'tea',
209 'traffic',
210 'transportation',
211 'water',
212 'weather',
213 'wildlife',
214 'wood',
215 'wool',
216 'work',
217 ];
218
219 /**
220 * Cache for plural inflections.
221 *
222 * @var array<string,string>
223 */
224 protected static array $pluralCache = [];
225
226 /**
227 * Cache for singular inflections.
228 *
229 * @var array<string,string>
230 */
231 protected static array $singularCache = [];
232
233 /**
234 * Convert a plural word to its singular form.
235 *
236 * @param string $value
237 * @return string
238 */
239 public static function singular(string $value): string
240 {
241 if (isset(static::$singularCache[$value])) {
242 return static::$singularCache[$value];
243 }
244
245 $result = static::inflect($value, static::$singular, static::$irregular);
246
247 return static::$singularCache[$value] = $result ?: $value;
248 }
249
250 /**
251 * Convert a singular word to its plural form.
252 *
253 * @param string $value
254 * @param int $count Number of items; if 1, returns singular.
255 * @return string
256 */
257 public static function plural(string $value, int $count = 2): string
258 {
259 if ($count === 1) {
260 return $value;
261 }
262
263 if (in_array($value, static::$irregular, true)) {
264 return $value;
265 }
266
267 if (isset(static::$pluralCache[$value])) {
268 return static::$pluralCache[$value];
269 }
270
271 $irregular = array_flip(static::$irregular);
272 $result = static::inflect($value, static::$plural, $irregular);
273
274 return static::$pluralCache[$value] = $result;
275 }
276
277 /**
278 * Perform inflection (singular or plural) on a word.
279 *
280 * @param string $value
281 * @param array<string,string> $source
282 * @param array<string,string> $irregulars
283 * @return string|null
284 */
285 protected static function inflect(string $value, array $source, array $irregulars): ?string
286 {
287 if (static::uncountable($value)) {
288 return $value;
289 }
290
291 foreach ($irregulars as $irregular => $pattern) {
292 if (preg_match($pattern = '/'.$pattern.'$/i', $value)) {
293 $irregular = static::matchCase($irregular, $value);
294 return preg_replace($pattern, $irregular, $value);
295 }
296 }
297
298 foreach ($source as $pattern => $inflected) {
299 if (preg_match($pattern, $value)) {
300 $inflected = preg_replace($pattern, $inflected, $value);
301 return static::matchCase($inflected, $value);
302 }
303 }
304
305 return null;
306 }
307
308 /**
309 * Check if a word is uncountable.
310 *
311 * @param string $value
312 * @return bool
313 */
314 protected static function uncountable(string $value): bool
315 {
316 return in_array(strtolower($value), static::$uncountable, true);
317 }
318
319 /**
320 * Match the case of a word to another word's case.
321 *
322 * @param string $value
323 * @param string $comparison
324 * @return string
325 */
326 protected static function matchCase(string $value, string $comparison): string
327 {
328 $functions = ['mb_strtolower', 'mb_strtoupper', 'ucfirst', 'ucwords'];
329
330 foreach ($functions as $function) {
331 if (call_user_func($function, $comparison) === $comparison) {
332 return call_user_func($function, $value);
333 }
334 }
335
336 return $value;
337 }
338
339 /**
340 * Check if a word is plural.
341 *
342 * @param string $word
343 * @return bool
344 */
345 public static function isPlural(string $word): bool
346 {
347 return static::singular($word) !== $word;
348 }
349
350 /**
351 * Check if a word is singular.
352 *
353 * @param string $word
354 * @return bool
355 */
356 public static function isSingular(string $word): bool
357 {
358 return static::singular($word) === $word;
359 }
360
361 /**
362 * Pluralize a word only if needed based on count.
363 *
364 * @param string $word
365 * @param int $count
366 * @return string
367 */
368 public static function pluralizeIfNeeded(string $word, int $count): string
369 {
370 return $count === 1 ? $word : static::plural($word, $count);
371 }
372
373 /**
374 * Add a new irregular singular/plural pair.
375 *
376 * @param string $singular
377 * @param string $plural
378 * @return void
379 */
380 public static function addIrregular(string $singular, string $plural): void
381 {
382 static::$irregular[$singular] = $plural;
383 static::clearCache();
384 }
385
386 /**
387 * Add a new uncountable word.
388 *
389 * @param string $word
390 * @return void
391 */
392 public static function addUncountable(string $word): void
393 {
394 $word = strtolower($word);
395 if (!in_array($word, static::$uncountable, true)) {
396 static::$uncountable[] = $word;
397 static::clearCache();
398 }
399 }
400
401 /**
402 * Clear the plural and singular caches.
403 *
404 * @return void
405 */
406 public static function clearCache(): void
407 {
408 static::$pluralCache = [];
409 static::$singularCache = [];
410 }
411 }
412