PluginProbe ʕ •ᴥ•ʔ
Independent Analytics – WordPress Analytics Plugin / 2.15.3
Independent Analytics – WordPress Analytics Plugin v2.15.3
2.15.4 2.15.3 2.15.2 2.15.1 2.15.0 2.14.10 trunk 1.1 1.10 1.10.1 1.11 1.12 1.13 1.14 1.15 1.16 1.17 1.17.1 1.17.2 1.17.3 1.17.4 1.18 1.18.1 1.19.0 1.19.1 1.2 1.20.0 1.21.0 1.22.0 1.22.1 1.23.0 1.23.1 1.24.0 1.24.1 1.25.0 1.25.1 1.26.0 1.27.0 1.28.0 1.28.1 1.28.2 1.28.3 1.29.0 1.3 1.30.0 1.30.1 1.4 1.5 1.6 1.7 1.8 1.9 2.0.0 2.0.1 2.1.4 2.1.5 2.1.6 2.10.0 2.10.1 2.10.2 2.10.3 2.10.4 2.11.0 2.11.1 2.11.10 2.11.2 2.11.3 2.11.4 2.11.5 2.11.6 2.11.7 2.11.8 2.11.9 2.12.0 2.12.1 2.12.2 2.13.1 2.13.2 2.13.5 2.13.6 2.14.0 2.14.1 2.14.2 2.14.4 2.14.6 2.14.7 2.14.8 2.14.9 2.2.0 2.2.1 2.3.1 2.3.2 2.4.2 2.4.3 2.5.0 2.5.1 2.6.0 2.6.1 2.6.2 2.6.3 2.6.4 2.7.0 2.7.1 2.7.2 2.7.3 2.8.2 2.8.3 2.8.4 2.8.5 2.8.6 2.8.7 2.8.8 2.8.9 2.9.2 2.9.3 2.9.4 2.9.5 2.9.6 2.9.7
independent-analytics / vendor / symfony / string / Inflector / EnglishInflector.php
independent-analytics / vendor / symfony / string / Inflector Last commit date
EnglishInflector.php 3 weeks ago FrenchInflector.php 2 years ago InflectorInterface.php 2 years ago
EnglishInflector.php
380 lines
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 IAWPSCOPED\Symfony\Component\String\Inflector;
12
13 /** @internal */
14 final class EnglishInflector implements InflectorInterface
15 {
16 /**
17 * Map English plural to singular suffixes.
18 *
19 * @see http://english-zone.com/spelling/plurals.html
20 */
21 private const PLURAL_MAP = [
22 // First entry: plural suffix, reversed
23 // Second entry: length of plural suffix
24 // Third entry: Whether the suffix may succeed a vocal
25 // Fourth entry: Whether the suffix may succeed a consonant
26 // Fifth entry: singular suffix, normal
27 // bacteria (bacterium), criteria (criterion), phenomena (phenomenon)
28 ['a', 1, \true, \true, ['on', 'um']],
29 // nebulae (nebula)
30 ['ea', 2, \true, \true, 'a'],
31 // services (service)
32 ['secivres', 8, \true, \true, 'service'],
33 // mice (mouse), lice (louse)
34 ['eci', 3, \false, \true, 'ouse'],
35 // geese (goose)
36 ['esee', 4, \false, \true, 'oose'],
37 // fungi (fungus), alumni (alumnus), syllabi (syllabus), radii (radius)
38 ['i', 1, \true, \true, 'us'],
39 // men (man), women (woman)
40 ['nem', 3, \true, \true, 'man'],
41 // children (child)
42 ['nerdlihc', 8, \true, \true, 'child'],
43 // oxen (ox)
44 ['nexo', 4, \false, \false, 'ox'],
45 // indices (index), appendices (appendix), prices (price)
46 ['seci', 4, \false, \true, ['ex', 'ix', 'ice']],
47 // selfies (selfie)
48 ['seifles', 7, \true, \true, 'selfie'],
49 // zombies (zombie)
50 ['seibmoz', 7, \true, \true, 'zombie'],
51 // movies (movie)
52 ['seivom', 6, \true, \true, 'movie'],
53 // conspectuses (conspectus), prospectuses (prospectus)
54 ['sesutcep', 8, \true, \true, 'pectus'],
55 // feet (foot)
56 ['teef', 4, \true, \true, 'foot'],
57 // geese (goose)
58 ['eseeg', 5, \true, \true, 'goose'],
59 // teeth (tooth)
60 ['hteet', 5, \true, \true, 'tooth'],
61 // news (news)
62 ['swen', 4, \true, \true, 'news'],
63 // series (series)
64 ['seires', 6, \true, \true, 'series'],
65 // babies (baby)
66 ['sei', 3, \false, \true, 'y'],
67 // accesses (access), addresses (address), kisses (kiss)
68 ['sess', 4, \true, \false, 'ss'],
69 // analyses (analysis), ellipses (ellipsis), fungi (fungus),
70 // neuroses (neurosis), theses (thesis), emphases (emphasis),
71 // oases (oasis), crises (crisis), houses (house), bases (base),
72 // atlases (atlas)
73 ['ses', 3, \true, \true, ['s', 'se', 'sis']],
74 // objectives (objective), alternative (alternatives)
75 ['sevit', 5, \true, \true, 'tive'],
76 // drives (drive)
77 ['sevird', 6, \false, \true, 'drive'],
78 // lives (life), wives (wife)
79 ['sevi', 4, \false, \true, 'ife'],
80 // moves (move)
81 ['sevom', 5, \true, \true, 'move'],
82 // hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf), caves (cave), staves (staff)
83 ['sev', 3, \true, \true, ['f', 've', 'ff']],
84 // axes (axis), axes (ax), axes (axe)
85 ['sexa', 4, \false, \false, ['ax', 'axe', 'axis']],
86 // indexes (index), matrixes (matrix)
87 ['sex', 3, \true, \false, 'x'],
88 // quizzes (quiz)
89 ['sezz', 4, \true, \false, 'z'],
90 // bureaus (bureau)
91 ['suae', 4, \false, \true, 'eau'],
92 // fees (fee), trees (tree), employees (employee)
93 ['see', 3, \true, \true, 'ee'],
94 // edges (edge)
95 ['segd', 4, \true, \true, 'dge'],
96 // roses (rose), garages (garage), cassettes (cassette),
97 // waltzes (waltz), heroes (hero), bushes (bush), arches (arch),
98 // shoes (shoe)
99 ['se', 2, \true, \true, ['', 'e']],
100 // tags (tag)
101 ['s', 1, \true, \true, ''],
102 // chateaux (chateau)
103 ['xuae', 4, \false, \true, 'eau'],
104 // people (person)
105 ['elpoep', 6, \true, \true, 'person'],
106 ];
107 /**
108 * Map English singular to plural suffixes.
109 *
110 * @see http://english-zone.com/spelling/plurals.html
111 */
112 private const SINGULAR_MAP = [
113 // First entry: singular suffix, reversed
114 // Second entry: length of singular suffix
115 // Third entry: Whether the suffix may succeed a vocal
116 // Fourth entry: Whether the suffix may succeed a consonant
117 // Fifth entry: plural suffix, normal
118 // criterion (criteria)
119 ['airetirc', 8, \false, \false, 'criterion'],
120 // nebulae (nebula)
121 ['aluben', 6, \false, \false, 'nebulae'],
122 // children (child)
123 ['dlihc', 5, \true, \true, 'children'],
124 // prices (price)
125 ['eci', 3, \false, \true, 'ices'],
126 // services (service)
127 ['ecivres', 7, \true, \true, 'services'],
128 // lives (life), wives (wife)
129 ['efi', 3, \false, \true, 'ives'],
130 // selfies (selfie)
131 ['eifles', 6, \true, \true, 'selfies'],
132 // movies (movie)
133 ['eivom', 5, \true, \true, 'movies'],
134 // lice (louse)
135 ['esuol', 5, \false, \true, 'lice'],
136 // mice (mouse)
137 ['esuom', 5, \false, \true, 'mice'],
138 // geese (goose)
139 ['esoo', 4, \false, \true, 'eese'],
140 // houses (house), bases (base)
141 ['es', 2, \true, \true, 'ses'],
142 // geese (goose)
143 ['esoog', 5, \true, \true, 'geese'],
144 // caves (cave)
145 ['ev', 2, \true, \true, 'ves'],
146 // drives (drive)
147 ['evird', 5, \false, \true, 'drives'],
148 // objectives (objective), alternative (alternatives)
149 ['evit', 4, \true, \true, 'tives'],
150 // moves (move)
151 ['evom', 4, \true, \true, 'moves'],
152 // staves (staff)
153 ['ffats', 5, \true, \true, 'staves'],
154 // hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf)
155 ['ff', 2, \true, \true, 'ffs'],
156 // hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf)
157 ['f', 1, \true, \true, ['fs', 'ves']],
158 // arches (arch)
159 ['hc', 2, \true, \true, 'ches'],
160 // bushes (bush)
161 ['hs', 2, \true, \true, 'shes'],
162 // teeth (tooth)
163 ['htoot', 5, \true, \true, 'teeth'],
164 // bacteria (bacterium), criteria (criterion), phenomena (phenomenon)
165 ['mu', 2, \true, \true, 'a'],
166 // men (man), women (woman)
167 ['nam', 3, \true, \true, 'men'],
168 // people (person)
169 ['nosrep', 6, \true, \true, ['persons', 'people']],
170 // bacteria (bacterium), criteria (criterion), phenomena (phenomenon)
171 ['noi', 3, \true, \true, 'ions'],
172 // coupon (coupons)
173 ['nop', 3, \true, \true, 'pons'],
174 // seasons (season), treasons (treason), poisons (poison), lessons (lesson)
175 ['nos', 3, \true, \true, 'sons'],
176 // bacteria (bacterium), criteria (criterion), phenomena (phenomenon)
177 ['no', 2, \true, \true, 'a'],
178 // echoes (echo)
179 ['ohce', 4, \true, \true, 'echoes'],
180 // heroes (hero)
181 ['oreh', 4, \true, \true, 'heroes'],
182 // atlases (atlas)
183 ['salta', 5, \true, \true, 'atlases'],
184 // irises (iris)
185 ['siri', 4, \true, \true, 'irises'],
186 // analyses (analysis), ellipses (ellipsis), neuroses (neurosis)
187 // theses (thesis), emphases (emphasis), oases (oasis),
188 // crises (crisis)
189 ['sis', 3, \true, \true, 'ses'],
190 // accesses (access), addresses (address), kisses (kiss)
191 ['ss', 2, \true, \false, 'sses'],
192 // syllabi (syllabus)
193 ['suballys', 8, \true, \true, 'syllabi'],
194 // buses (bus)
195 ['sub', 3, \true, \true, 'buses'],
196 // circuses (circus)
197 ['suc', 3, \true, \true, 'cuses'],
198 // conspectuses (conspectus), prospectuses (prospectus)
199 ['sutcep', 6, \true, \true, 'pectuses'],
200 // fungi (fungus), alumni (alumnus), syllabi (syllabus), radii (radius)
201 ['su', 2, \true, \true, 'i'],
202 // news (news)
203 ['swen', 4, \true, \true, 'news'],
204 // feet (foot)
205 ['toof', 4, \true, \true, 'feet'],
206 // chateaux (chateau), bureaus (bureau)
207 ['uae', 3, \false, \true, ['eaus', 'eaux']],
208 // oxen (ox)
209 ['xo', 2, \false, \false, 'oxen'],
210 // hoaxes (hoax)
211 ['xaoh', 4, \true, \false, 'hoaxes'],
212 // indices (index)
213 ['xedni', 5, \false, \true, ['indicies', 'indexes']],
214 // boxes (box)
215 ['xo', 2, \false, \true, 'oxes'],
216 // indexes (index), matrixes (matrix)
217 ['x', 1, \true, \false, ['cies', 'xes']],
218 // appendices (appendix)
219 ['xi', 2, \false, \true, 'ices'],
220 // babies (baby)
221 ['y', 1, \false, \true, 'ies'],
222 // quizzes (quiz)
223 ['ziuq', 4, \true, \false, 'quizzes'],
224 // waltzes (waltz)
225 ['z', 1, \true, \true, 'zes'],
226 ];
227 /**
228 * A list of words which should not be inflected, reversed.
229 */
230 private const UNINFLECTED = [
231 '',
232 // data
233 'atad',
234 // deer
235 'reed',
236 // feedback
237 'kcabdeef',
238 // fish
239 'hsif',
240 // info
241 'ofni',
242 // moose
243 'esoom',
244 // series
245 'seires',
246 // sheep
247 'peehs',
248 // species
249 'seiceps',
250 ];
251 /**
252 * {@inheritdoc}
253 */
254 public function singularize(string $plural) : array
255 {
256 $pluralRev = \strrev($plural);
257 $lowerPluralRev = \strtolower($pluralRev);
258 $pluralLength = \strlen($lowerPluralRev);
259 // Check if the word is one which is not inflected, return early if so
260 if (\in_array($lowerPluralRev, self::UNINFLECTED, \true)) {
261 return [$plural];
262 }
263 // The outer loop iterates over the entries of the plural table
264 // The inner loop $j iterates over the characters of the plural suffix
265 // in the plural table to compare them with the characters of the actual
266 // given plural suffix
267 foreach (self::PLURAL_MAP as $map) {
268 $suffix = $map[0];
269 $suffixLength = $map[1];
270 $j = 0;
271 // Compare characters in the plural table and of the suffix of the
272 // given plural one by one
273 while ($suffix[$j] === $lowerPluralRev[$j]) {
274 // Let $j point to the next character
275 ++$j;
276 // Successfully compared the last character
277 // Add an entry with the singular suffix to the singular array
278 if ($j === $suffixLength) {
279 // Is there any character preceding the suffix in the plural string?
280 if ($j < $pluralLength) {
281 $nextIsVocal = \false !== \strpos('aeiou', $lowerPluralRev[$j]);
282 if (!$map[2] && $nextIsVocal) {
283 // suffix may not succeed a vocal but next char is one
284 break;
285 }
286 if (!$map[3] && !$nextIsVocal) {
287 // suffix may not succeed a consonant but next char is one
288 break;
289 }
290 }
291 $newBase = \substr($plural, 0, $pluralLength - $suffixLength);
292 $newSuffix = $map[4];
293 // Check whether the first character in the plural suffix
294 // is uppercased. If yes, uppercase the first character in
295 // the singular suffix too
296 $firstUpper = \ctype_upper($pluralRev[$j - 1]);
297 if (\is_array($newSuffix)) {
298 $singulars = [];
299 foreach ($newSuffix as $newSuffixEntry) {
300 $singulars[] = $newBase . ($firstUpper ? \ucfirst($newSuffixEntry) : $newSuffixEntry);
301 }
302 return $singulars;
303 }
304 return [$newBase . ($firstUpper ? \ucfirst($newSuffix) : $newSuffix)];
305 }
306 // Suffix is longer than word
307 if ($j === $pluralLength) {
308 break;
309 }
310 }
311 }
312 // Assume that plural and singular is identical
313 return [$plural];
314 }
315 /**
316 * {@inheritdoc}
317 */
318 public function pluralize(string $singular) : array
319 {
320 $singularRev = \strrev($singular);
321 $lowerSingularRev = \strtolower($singularRev);
322 $singularLength = \strlen($lowerSingularRev);
323 // Check if the word is one which is not inflected, return early if so
324 if (\in_array($lowerSingularRev, self::UNINFLECTED, \true)) {
325 return [$singular];
326 }
327 // The outer loop iterates over the entries of the singular table
328 // The inner loop $j iterates over the characters of the singular suffix
329 // in the singular table to compare them with the characters of the actual
330 // given singular suffix
331 foreach (self::SINGULAR_MAP as $map) {
332 $suffix = $map[0];
333 $suffixLength = $map[1];
334 $j = 0;
335 // Compare characters in the singular table and of the suffix of the
336 // given plural one by one
337 while ($suffix[$j] === $lowerSingularRev[$j]) {
338 // Let $j point to the next character
339 ++$j;
340 // Successfully compared the last character
341 // Add an entry with the plural suffix to the plural array
342 if ($j === $suffixLength) {
343 // Is there any character preceding the suffix in the plural string?
344 if ($j < $singularLength) {
345 $nextIsVocal = \false !== \strpos('aeiou', $lowerSingularRev[$j]);
346 if (!$map[2] && $nextIsVocal) {
347 // suffix may not succeed a vocal but next char is one
348 break;
349 }
350 if (!$map[3] && !$nextIsVocal) {
351 // suffix may not succeed a consonant but next char is one
352 break;
353 }
354 }
355 $newBase = \substr($singular, 0, $singularLength - $suffixLength);
356 $newSuffix = $map[4];
357 // Check whether the first character in the singular suffix
358 // is uppercased. If yes, uppercase the first character in
359 // the singular suffix too
360 $firstUpper = \ctype_upper($singularRev[$j - 1]);
361 if (\is_array($newSuffix)) {
362 $plurals = [];
363 foreach ($newSuffix as $newSuffixEntry) {
364 $plurals[] = $newBase . ($firstUpper ? \ucfirst($newSuffixEntry) : $newSuffixEntry);
365 }
366 return $plurals;
367 }
368 return [$newBase . ($firstUpper ? \ucfirst($newSuffix) : $newSuffix)];
369 }
370 // Suffix is longer than word
371 if ($j === $singularLength) {
372 break;
373 }
374 }
375 }
376 // Assume that plural is singular with a trailing `s`
377 return [$singular . 's'];
378 }
379 }
380