]> git.immae.eu Git - github/wallabag/wallabag.git/blob - vendor/symfony/property-access/Symfony/Component/PropertyAccess/StringUtil.php
twig implementation
[github/wallabag/wallabag.git] / vendor / symfony / property-access / Symfony / Component / PropertyAccess / StringUtil.php
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
12 namespace Symfony\Component\PropertyAccess;
13
14 /**
15 * Creates singulars from plurals.
16 *
17 * @author Bernhard Schussek <bschussek@gmail.com>
18 */
19 class StringUtil
20 {
21 /**
22 * Map english plural to singular suffixes
23 *
24 * @var array
25 *
26 * @see http://english-zone.com/spelling/plurals.html
27 * @see http://www.scribd.com/doc/3271143/List-of-100-Irregular-Plural-Nouns-in-English
28 */
29 private static $pluralMap = array(
30 // First entry: plural suffix, reversed
31 // Second entry: length of plural suffix
32 // Third entry: Whether the suffix may succeed a vocal
33 // Fourth entry: Whether the suffix may succeed a consonant
34 // Fifth entry: singular suffix, normal
35
36 // bacteria (bacterium), criteria (criterion), phenomena (phenomenon)
37 array('a', 1, true, true, array('on', 'um')),
38
39 // nebulae (nebula)
40 array('ea', 2, true, true, 'a'),
41
42 // mice (mouse), lice (louse)
43 array('eci', 3, false, true, 'ouse'),
44
45 // geese (goose)
46 array('esee', 4, false, true, 'oose'),
47
48 // fungi (fungus), alumni (alumnus), syllabi (syllabus), radii (radius)
49 array('i', 1, true, true, 'us'),
50
51 // men (man), women (woman)
52 array('nem', 3, true, true, 'man'),
53
54 // children (child)
55 array('nerdlihc', 8, true, true, 'child'),
56
57 // oxen (ox)
58 array('nexo', 4, false, false, 'ox'),
59
60 // indices (index), appendices (appendix), prices (price)
61 array('seci', 4, false, true, array('ex', 'ix', 'ice')),
62
63 // babies (baby)
64 array('sei', 3, false, true, 'y'),
65
66 // analyses (analysis), ellipses (ellipsis), funguses (fungus),
67 // neuroses (neurosis), theses (thesis), emphases (emphasis),
68 // oases (oasis), crises (crisis), houses (house), bases (base),
69 // atlases (atlas), kisses (kiss)
70 array('ses', 3, true, true, array('s', 'se', 'sis')),
71
72 // objectives (objective), alternative (alternatives)
73 array('sevit', 5, true, true, 'tive'),
74
75 // lives (life), wives (wife)
76 array('sevi', 4, false, true, 'ife'),
77
78 // hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf)
79 array('sev', 3, true, true, 'f'),
80
81 // axes (axis), axes (ax), axes (axe)
82 array('sexa', 4, false, false, array('ax', 'axe', 'axis')),
83
84 // indexes (index), matrixes (matrix)
85 array('sex', 3, true, false, 'x'),
86
87 // quizzes (quiz)
88 array('sezz', 4, true, false, 'z'),
89
90 // bureaus (bureau)
91 array('suae', 4, false, true, 'eau'),
92
93 // roses (rose), garages (garage), cassettes (cassette),
94 // waltzes (waltz), heroes (hero), bushes (bush), arches (arch),
95 // shoes (shoe)
96 array('se', 2, true, true, array('', 'e')),
97
98 // tags (tag)
99 array('s', 1, true, true, ''),
100
101 // chateaux (chateau)
102 array('xuae', 4, false, true, 'eau'),
103 );
104
105 /**
106 * This class should not be instantiated
107 */
108 private function __construct() {}
109
110 /**
111 * Returns the singular form of a word
112 *
113 * If the method can't determine the form with certainty, an array of the
114 * possible singulars is returned.
115 *
116 * @param string $plural A word in plural form
117 * @return string|array The singular form or an array of possible singular
118 * forms
119 */
120 public static function singularify($plural)
121 {
122 $pluralRev = strrev($plural);
123 $lowerPluralRev = strtolower($pluralRev);
124 $pluralLength = strlen($lowerPluralRev);
125
126 // The outer loop iterates over the entries of the plural table
127 // The inner loop $j iterates over the characters of the plural suffix
128 // in the plural table to compare them with the characters of the actual
129 // given plural suffix
130 foreach (self::$pluralMap as $map) {
131 $suffix = $map[0];
132 $suffixLength = $map[1];
133 $j = 0;
134
135 // Compare characters in the plural table and of the suffix of the
136 // given plural one by one
137 while ($suffix[$j] === $lowerPluralRev[$j]) {
138 // Let $j point to the next character
139 ++$j;
140
141 // Successfully compared the last character
142 // Add an entry with the singular suffix to the singular array
143 if ($j === $suffixLength) {
144 // Is there any character preceding the suffix in the plural string?
145 if ($j < $pluralLength) {
146 $nextIsVocal = false !== strpos('aeiou', $lowerPluralRev[$j]);
147
148 if (!$map[2] && $nextIsVocal) {
149 // suffix may not succeed a vocal but next char is one
150 break;
151 }
152
153 if (!$map[3] && !$nextIsVocal) {
154 // suffix may not succeed a consonant but next char is one
155 break;
156 }
157 }
158
159 $newBase = substr($plural, 0, $pluralLength - $suffixLength);
160 $newSuffix = $map[4];
161
162 // Check whether the first character in the plural suffix
163 // is uppercased. If yes, uppercase the first character in
164 // the singular suffix too
165 $firstUpper = ctype_upper($pluralRev[$j - 1]);
166
167 if (is_array($newSuffix)) {
168 $singulars = array();
169
170 foreach ($newSuffix as $newSuffixEntry) {
171 $singulars[] = $newBase.($firstUpper ? ucfirst($newSuffixEntry) : $newSuffixEntry);
172 }
173
174 return $singulars;
175 }
176
177 return $newBase.($firstUpper ? ucFirst($newSuffix) : $newSuffix);
178 }
179
180 // Suffix is longer than word
181 if ($j === $pluralLength) {
182 break;
183 }
184 }
185 }
186
187 // Convert teeth to tooth, feet to foot
188 if (false !== ($pos = strpos($plural, 'ee'))) {
189 return substr_replace($plural, 'oo', $pos, 2);
190 }
191
192 // Assume that plural and singular is identical
193 return $plural;
194 }
195 }