PluginProbe
WindPress – Tailwind CSS integration for WordPress / 3.0.5
WindPress – Tailwind CSS integration for WordPress v3.0.5
3.2.89 3.2.88 3.2.87 3.2.86 3.2.85 3.2.84 3.2.83 3.2.82 3.2.81 trunk 3.0.0 3.0.1 3.0.10 3.0.11 3.0.12 3.0.13 3.0.14 3.0.15 3.0.16 3.0.17 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 All 143 releases
windpress / vendor / symfony / string / Inflector / EnglishInflector.php

EnglishInflector.php in WindPress – Tailwind CSS integration for WordPress 3.0.5, at vendor/symfony/string/Inflector/EnglishInflector.php

421 lines 16.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11 namespace WindPressPackages\Symfony\Component\String\Inflector;
12
13 final class EnglishInflector implements InflectorInterface
14 {
15 /**
16 * Map English plural to singular suffixes.
17 *
18 * @see http://english-zone.com/spelling/plurals.html
19 */
20 private const PLURAL_MAP = [
21 // First entry: plural suffix, reversed
22 // Second entry: length of plural suffix
23 // Third entry: Whether the suffix may succeed a vowel
24 // Fourth entry: Whether the suffix may succeed a consonant
25 // Fifth entry: singular suffix, normal
26 // bacteria (bacterium)
27 ['airetcab', 8, \true, \true, 'bacterium'],
28 // corpora (corpus)
29 ['aroproc', 7, \true, \true, 'corpus'],
30 // criteria (criterion)
31 ['airetirc', 8, \true, \true, 'criterion'],
32 // curricula (curriculum)
33 ['alucirruc', 9, \true, \true, 'curriculum'],
34 // genera (genus)
35 ['areneg', 6, \true, \true, 'genus'],
36 // media (medium)
37 ['aidem', 5, \true, \true, 'medium'],
38 // memoranda (memorandum)
39 ['adnaromem', 9, \true, \true, 'memorandum'],
40 // phenomena (phenomenon)
41 ['anemonehp', 9, \true, \true, 'phenomenon'],
42 // strata (stratum)
43 ['atarts', 6, \true, \true, 'stratum'],
44 // nebulae (nebula)
45 ['ea', 2, \true, \true, 'a'],
46 // services (service)
47 ['secivres', 8, \true, \true, 'service'],
48 // mice (mouse), lice (louse)
49 ['eci', 3, \false, \true, 'ouse'],
50 // geese (goose)
51 ['esee', 4, \false, \true, 'oose'],
52 // fungi (fungus), alumni (alumnus), syllabi (syllabus), radii (radius)
53 ['i', 1, \true, \true, 'us'],
54 // men (man), women (woman)
55 ['nem', 3, \true, \true, 'man'],
56 // children (child)
57 ['nerdlihc', 8, \true, \true, 'child'],
58 // oxen (ox)
59 ['nexo', 4, \false, \false, 'ox'],
60 // indices (index), appendices (appendix), prices (price)
61 ['seci', 4, \false, \true, ['ex', 'ix', 'ice']],
62 // codes (code)
63 ['sedoc', 5, \false, \true, 'code'],
64 // selfies (selfie)
65 ['seifles', 7, \true, \true, 'selfie'],
66 // zombies (zombie)
67 ['seibmoz', 7, \true, \true, 'zombie'],
68 // movies (movie)
69 ['seivom', 6, \true, \true, 'movie'],
70 // names (name)
71 ['seman', 5, \true, \false, 'name'],
72 // conspectuses (conspectus), prospectuses (prospectus)
73 ['sesutcep', 8, \true, \true, 'pectus'],
74 // feet (foot)
75 ['teef', 4, \true, \true, 'foot'],
76 // geese (goose)
77 ['eseeg', 5, \true, \true, 'goose'],
78 // teeth (tooth)
79 ['hteet', 5, \true, \true, 'tooth'],
80 // news (news)
81 ['swen', 4, \true, \true, 'news'],
82 // series (series)
83 ['seires', 6, \true, \true, 'series'],
84 // babies (baby)
85 ['sei', 3, \false, \true, 'y'],
86 // accesses (access), addresses (address), kisses (kiss)
87 ['sess', 4, \true, \false, 'ss'],
88 // statuses (status)
89 ['sesutats', 8, \true, \true, 'status'],
90 // analyses (analysis), ellipses (ellipsis), fungi (fungus),
91 // neuroses (neurosis), theses (thesis), emphases (emphasis),
92 // oases (oasis), crises (crisis), houses (house), bases (base),
93 // atlases (atlas)
94 ['ses', 3, \true, \true, ['s', 'se', 'sis']],
95 // objectives (objective), alternative (alternatives)
96 ['sevit', 5, \true, \true, 'tive'],
97 // drives (drive)
98 ['sevird', 6, \false, \true, 'drive'],
99 // lives (life), wives (wife)
100 ['sevi', 4, \false, \true, 'ife'],
101 // moves (move)
102 ['sevom', 5, \true, \true, 'move'],
103 // hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf), caves (cave), staves (staff)
104 ['sev', 3, \true, \true, ['f', 've', 'ff']],
105 // axes (axis), axes (ax), axes (axe)
106 ['sexa', 4, \false, \false, ['ax', 'axe', 'axis']],
107 // indexes (index), matrixes (matrix)
108 ['sex', 3, \true, \false, 'x'],
109 // quizzes (quiz)
110 ['sezz', 4, \true, \false, 'z'],
111 // bureaus (bureau)
112 ['suae', 4, \false, \true, 'eau'],
113 // fees (fee), trees (tree), employees (employee)
114 ['see', 3, \true, \true, 'ee'],
115 // edges (edge)
116 ['segd', 4, \true, \true, 'dge'],
117 // roses (rose), garages (garage), cassettes (cassette),
118 // waltzes (waltz), heroes (hero), bushes (bush), arches (arch),
119 // shoes (shoe)
120 ['se', 2, \true, \true, ['', 'e']],
121 // status (status)
122 ['sutats', 6, \true, \true, 'status'],
123 // tags (tag)
124 ['s', 1, \true, \true, ''],
125 // chateaux (chateau)
126 ['xuae', 4, \false, \true, 'eau'],
127 // people (person)
128 ['elpoep', 6, \true, \true, 'person'],
129 ];
130 /**
131 * Map English singular to plural suffixes.
132 *
133 * @see http://english-zone.com/spelling/plurals.html
134 */
135 private const SINGULAR_MAP = [
136 // First entry: singular suffix, reversed
137 // Second entry: length of singular suffix
138 // Third entry: Whether the suffix may succeed a vowel
139 // Fourth entry: Whether the suffix may succeed a consonant
140 // Fifth entry: plural suffix, normal
141 // axes (axis)
142 ['sixa', 4, \false, \false, 'axes'],
143 // criterion (criteria)
144 ['airetirc', 8, \false, \false, 'criterion'],
145 // nebulae (nebula)
146 ['aluben', 6, \false, \false, 'nebulae'],
147 // children (child)
148 ['dlihc', 5, \true, \true, 'children'],
149 // prices (price)
150 ['eci', 3, \false, \true, 'ices'],
151 // services (service)
152 ['ecivres', 7, \true, \true, 'services'],
153 // lives (life), wives (wife)
154 ['efi', 3, \false, \true, 'ives'],
155 // selfies (selfie)
156 ['eifles', 6, \true, \true, 'selfies'],
157 // movies (movie)
158 ['eivom', 5, \true, \true, 'movies'],
159 // lice (louse)
160 ['esuol', 5, \false, \true, 'lice'],
161 // mice (mouse)
162 ['esuom', 5, \false, \true, 'mice'],
163 // geese (goose)
164 ['esoo', 4, \false, \true, 'eese'],
165 // houses (house), bases (base)
166 ['es', 2, \true, \true, 'ses'],
167 // geese (goose)
168 ['esoog', 5, \true, \true, 'geese'],
169 // caves (cave)
170 ['ev', 2, \true, \true, 'ves'],
171 // drives (drive)
172 ['evird', 5, \false, \true, 'drives'],
173 // objectives (objective), alternative (alternatives)
174 ['evit', 4, \true, \true, 'tives'],
175 // moves (move)
176 ['evom', 4, \true, \true, 'moves'],
177 // staves (staff)
178 ['ffats', 5, \true, \true, 'staves'],
179 // hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf)
180 ['ff', 2, \true, \true, 'ffs'],
181 // hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf)
182 ['f', 1, \true, \true, ['fs', 'ves']],
183 // arches (arch)
184 ['hc', 2, \true, \true, 'ches'],
185 // bushes (bush)
186 ['hs', 2, \true, \true, 'shes'],
187 // teeth (tooth)
188 ['htoot', 5, \true, \true, 'teeth'],
189 // albums (album)
190 ['mubla', 5, \true, \true, 'albums'],
191 // bacteria (bacterium), curricula (curriculum), media (medium), memoranda (memorandum), phenomena (phenomenon), strata (stratum)
192 ['mu', 2, \true, \true, 'a'],
193 // men (man), women (woman)
194 ['nam', 3, \true, \true, 'men'],
195 // people (person)
196 ['nosrep', 6, \true, \true, ['persons', 'people']],
197 // criteria (criterion)
198 ['noiretirc', 9, \true, \true, 'criteria'],
199 // phenomena (phenomenon)
200 ['nonemonehp', 10, \true, \true, 'phenomena'],
201 // echoes (echo)
202 ['ohce', 4, \true, \true, 'echoes'],
203 // heroes (hero)
204 ['oreh', 4, \true, \true, 'heroes'],
205 // atlases (atlas)
206 ['salta', 5, \true, \true, 'atlases'],
207 // aliases (alias)
208 ['saila', 5, \true, \true, 'aliases'],
209 // irises (iris)
210 ['siri', 4, \true, \true, 'irises'],
211 // analyses (analysis), ellipses (ellipsis), neuroses (neurosis)
212 // theses (thesis), emphases (emphasis), oases (oasis),
213 // crises (crisis)
214 ['sis', 3, \true, \true, 'ses'],
215 // accesses (access), addresses (address), kisses (kiss)
216 ['ss', 2, \true, \false, 'sses'],
217 // syllabi (syllabus)
218 ['suballys', 8, \true, \true, 'syllabi'],
219 // buses (bus)
220 ['sub', 3, \true, \true, 'buses'],
221 // circuses (circus)
222 ['suc', 3, \true, \true, 'cuses'],
223 // hippocampi (hippocampus)
224 ['supmacoppih', 11, \false, \false, 'hippocampi'],
225 // campuses (campus)
226 ['sup', 3, \true, \true, 'puses'],
227 // status (status)
228 ['sutats', 6, \true, \true, ['status', 'statuses']],
229 // conspectuses (conspectus), prospectuses (prospectus)
230 ['sutcep', 6, \true, \true, 'pectuses'],
231 // fungi (fungus), alumni (alumnus), syllabi (syllabus), radii (radius)
232 ['su', 2, \true, \true, 'i'],
233 // news (news)
234 ['swen', 4, \true, \true, 'news'],
235 // feet (foot)
236 ['toof', 4, \true, \true, 'feet'],
237 // chateaux (chateau), bureaus (bureau)
238 ['uae', 3, \false, \true, ['eaus', 'eaux']],
239 // oxen (ox)
240 ['xo', 2, \false, \false, 'oxen'],
241 // hoaxes (hoax)
242 ['xaoh', 4, \true, \false, 'hoaxes'],
243 // indices (index)
244 ['xedni', 5, \false, \true, ['indicies', 'indexes']],
245 // boxes (box)
246 ['xo', 2, \false, \true, 'oxes'],
247 // indexes (index), matrixes (matrix)
248 ['x', 1, \true, \false, ['cies', 'xes']],
249 // appendices (appendix)
250 ['xi', 2, \false, \true, 'ices'],
251 // babies (baby)
252 ['y', 1, \false, \true, 'ies'],
253 // quizzes (quiz)
254 ['ziuq', 4, \true, \false, 'quizzes'],
255 // waltzes (waltz)
256 ['z', 1, \true, \true, 'zes'],
257 ];
258 /**
259 * A list of words which should not be inflected, reversed.
260 */
261 private const UNINFLECTED = [
262 '',
263 // data
264 'atad',
265 // deer
266 'reed',
267 // equipment
268 'tnempiuqe',
269 // feedback
270 'kcabdeef',
271 // fish
272 'hsif',
273 // health
274 'htlaeh',
275 // history
276 'yrotsih',
277 // info
278 'ofni',
279 // information
280 'noitamrofni',
281 // money
282 'yenom',
283 // moose
284 'esoom',
285 // series
286 'seires',
287 // sheep
288 'peehs',
289 // species
290 'seiceps',
291 // traffic
292 'ciffart',
293 // aircraft
294 'tfarcria',
295 // hardware
296 'erawdrah',
297 ];
298 public function singularize(string $plural) : array
299 {
300 $pluralRev = \strrev($plural);
301 $lowerPluralRev = \strtolower($pluralRev);
302 $pluralLength = \strlen($lowerPluralRev);
303 // Check if the word is one which is not inflected, return early if so
304 if (\in_array($lowerPluralRev, self::UNINFLECTED, \true)) {
305 return [$plural];
306 }
307 // The outer loop iterates over the entries of the plural table
308 // The inner loop $j iterates over the characters of the plural suffix
309 // in the plural table to compare them with the characters of the actual
310 // given plural suffix
311 foreach (self::PLURAL_MAP as $map) {
312 $suffix = $map[0];
313 $suffixLength = $map[1];
314 $j = 0;
315 // Compare characters in the plural table and of the suffix of the
316 // given plural one by one
317 while ($suffix[$j] === $lowerPluralRev[$j]) {
318 // Let $j point to the next character
319 ++$j;
320 // Successfully compared the last character
321 // Add an entry with the singular suffix to the singular array
322 if ($j === $suffixLength) {
323 // Is there any character preceding the suffix in the plural string?
324 if ($j < $pluralLength) {
325 $nextIsVowel = \str_contains('aeiou', $lowerPluralRev[$j]);
326 if (!$map[2] && $nextIsVowel) {
327 // suffix may not succeed a vowel but next char is one
328 break;
329 }
330 if (!$map[3] && !$nextIsVowel) {
331 // suffix may not succeed a consonant but next char is one
332 break;
333 }
334 }
335 $newBase = \substr($plural, 0, $pluralLength - $suffixLength);
336 $newSuffix = $map[4];
337 // Check whether the first character in the plural suffix
338 // is uppercased. If yes, uppercase the first character in
339 // the singular suffix too
340 $firstUpper = \ctype_upper($pluralRev[$j - 1]);
341 if (\is_array($newSuffix)) {
342 $singulars = [];
343 foreach ($newSuffix as $newSuffixEntry) {
344 $singulars[] = $newBase . ($firstUpper ? \ucfirst($newSuffixEntry) : $newSuffixEntry);
345 }
346 return $singulars;
347 }
348 return [$newBase . ($firstUpper ? \ucfirst($newSuffix) : $newSuffix)];
349 }
350 // Suffix is longer than word
351 if ($j === $pluralLength) {
352 break;
353 }
354 }
355 }
356 // Assume that plural and singular is identical
357 return [$plural];
358 }
359 public function pluralize(string $singular) : array
360 {
361 $singularRev = \strrev($singular);
362 $lowerSingularRev = \strtolower($singularRev);
363 $singularLength = \strlen($lowerSingularRev);
364 // Check if the word is one which is not inflected, return early if so
365 if (\in_array($lowerSingularRev, self::UNINFLECTED, \true)) {
366 return [$singular];
367 }
368 // The outer loop iterates over the entries of the singular table
369 // The inner loop $j iterates over the characters of the singular suffix
370 // in the singular table to compare them with the characters of the actual
371 // given singular suffix
372 foreach (self::SINGULAR_MAP as $map) {
373 $suffix = $map[0];
374 $suffixLength = $map[1];
375 $j = 0;
376 // Compare characters in the singular table and of the suffix of the
377 // given plural one by one
378 while ($suffix[$j] === $lowerSingularRev[$j]) {
379 // Let $j point to the next character
380 ++$j;
381 // Successfully compared the last character
382 // Add an entry with the plural suffix to the plural array
383 if ($j === $suffixLength) {
384 // Is there any character preceding the suffix in the plural string?
385 if ($j < $singularLength) {
386 $nextIsVowel = \str_contains('aeiou', $lowerSingularRev[$j]);
387 if (!$map[2] && $nextIsVowel) {
388 // suffix may not succeed a vowel but next char is one
389 break;
390 }
391 if (!$map[3] && !$nextIsVowel) {
392 // suffix may not succeed a consonant but next char is one
393 break;
394 }
395 }
396 $newBase = \substr($singular, 0, $singularLength - $suffixLength);
397 $newSuffix = $map[4];
398 // Check whether the first character in the singular suffix
399 // is uppercased. If yes, uppercase the first character in
400 // the singular suffix too
401 $firstUpper = \ctype_upper($singularRev[$j - 1]);
402 if (\is_array($newSuffix)) {
403 $plurals = [];
404 foreach ($newSuffix as $newSuffixEntry) {
405 $plurals[] = $newBase . ($firstUpper ? \ucfirst($newSuffixEntry) : $newSuffixEntry);
406 }
407 return $plurals;
408 }
409 return [$newBase . ($firstUpper ? \ucfirst($newSuffix) : $newSuffix)];
410 }
411 // Suffix is longer than word
412 if ($j === $singularLength) {
413 break;
414 }
415 }
416 }
417 // Assume that plural is singular with a trailing `s`
418 return [$singular . 's'];
419 }
420 }
421