2 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
4 // +----------------------------------------------------------------------+
5 // | Akelos Framework - http://www.akelos.org |
6 // +----------------------------------------------------------------------+
7 // | Copyright (c) 2002-2006, Akelos Media, S.L. & Bermi Ferrer Martinez |
8 // | Released under the GNU Lesser General Public License, see LICENSE.txt|
9 // +----------------------------------------------------------------------+
12 * @package ActiveSupport
13 * @subpackage Inflector
14 * @author Bermi Ferrer <bermi a.t akelos c.om>
15 * @copyright Copyright (c) 2002-2006, Akelos Media, S.L. http://www.akelos.org
16 * @license GNU Lesser General Public License <http://www.gnu.org/copyleft/lesser.html>
20 * AkInflector for pluralize and singularize English nouns.
22 * This AkInflector is a port of Ruby on Rails AkInflector.
24 * It can be really helpful for developers that want to
25 * create frameworks based on naming conventions rather than
28 * It was ported to PHP for the Akelos Framework, a
29 * multilingual Ruby on Rails like framework for PHP that will
32 * @author Bermi Ferrer Martinez <bermi a.t akelos c.om>
33 * @copyright Copyright (c) 2002-2006, Akelos Media, S.L. http://www.akelos.org
34 * @license GNU Lesser General Public License <http://www.gnu.org/copyleft/lesser.html>
38 // ------ CLASS METHODS ------ //
40 // ---- Public methods ---- //
45 * Pluralizes English nouns.
49 * @param string $word English noun to pluralize
50 * @return string Plural noun
52 function pluralize($word, $new_plural = null)
55 if(isset($new_plural)){
56 $_cached[$word] = $new_plural;
59 $_original_word = $word;
60 if(!isset($_cached[$_original_word])){
62 '/(quiz)$/i' => '\1zes',
63 '/^(ox)$/i' => '\1en',
64 '/([m|l])ouse$/i' => '\1ice',
65 '/(matr|vert|ind)ix|ex$/i' => '\1ices',
66 '/(x|ch|ss|sh)$/i' => '\1es',
67 '/([^aeiouy]|qu)ies$/i' => '\1y',
68 '/([^aeiouy]|qu)y$/i' => '\1ies',
69 '/(hive)$/i' => '\1s',
70 '/(?:([^f])fe|([lr])f)$/i' => '\1\2ves',
72 '/([ti])um$/i' => '\1a',
73 '/(buffal|tomat)o$/i' => '\1oes',
74 '/(bu)s$/i' => '\1ses',
75 '/(alias|status)/i'=> '\1es',
76 '/(octop|vir)us$/i'=> '\1i',
77 '/(ax|test)is$/i'=> '\1es',
81 $uncountable = array('equipment', 'information', 'rice', 'money', 'species', 'series', 'fish', 'sheep');
86 'child' => 'children',
90 $lowercased_word = strtolower($word);
92 foreach ($uncountable as $_uncountable){
93 if(substr($lowercased_word,(-1*strlen($_uncountable))) == $_uncountable){
94 $_cached[$_original_word] = $word;
99 foreach ($irregular as $_plural=> $_singular){
100 if (preg_match('/('.$_plural.')$/i', $word, $arr)) {
101 $_cached[$_original_word] = preg_replace('/('.$_plural.')$/i', substr($arr[0],0,1).substr($_singular,1), $word);
102 return $_cached[$_original_word];
106 foreach ($plural as $rule => $replacement) {
107 if (preg_match($rule, $word)) {
108 $_cached[$_original_word] = preg_replace($rule, $replacement, $word);
109 return $_cached[$_original_word];
112 $_cached[$_original_word] = false;
115 return $_cached[$_original_word];
122 * Singularizes English nouns.
126 * @param string $word English noun to singularize
127 * @return string Singular noun.
129 function singularize($word, $new_singular = null)
132 if(isset($new_singular)){
133 $_cached[$word] = $new_singular;
136 $_original_word = $word;
137 if(!isset($_cached[$_original_word])){
139 '/(quiz)zes$/i' => '\\1',
140 '/(matr)ices$/i' => '\\1ix',
141 '/(vert|ind)ices$/i' => '\\1ex',
142 '/^(ox)en/i' => '\\1',
143 '/(alias|status|wax)es$/i' => '\\1',
144 '/([octop|vir])i$/i' => '\\1us',
145 '/(cris|ax|test)es$/i' => '\\1is',
146 '/(shoe)s$/i' => '\\1',
147 '/(o)es$/i' => '\\1',
148 '/(bus)es$/i' => '\\1',
149 '/([m|l])ice$/i' => '\\1ouse',
150 '/(x|ch|ss|sh)es$/i' => '\\1',
151 '/(m)ovies$/i' => '\\1ovie',
152 '/(s)eries$/i' => '\\1eries',
153 '/([^aeiouy]|qu)ies$/i' => '\\1y',
154 '/([lr])ves$/i' => '\\1f',
155 '/(tive)s$/i' => '\\1',
156 '/(hive)s$/i' => '\\1',
157 '/([^f])ves$/i' => '\\1fe',
158 '/(^analy)ses$/i' => '\\1sis',
159 '/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i' => '\\1\\2sis',
160 '/([ti])a$/i' => '\\1um',
161 '/(n)ews$/i' => '\\1ews',
166 $uncountable = array('equipment', 'information', 'rice', 'money', 'species', 'series', 'fish', 'sheep','sms');
169 'person' => 'people',
171 'child' => 'children',
173 'database' => 'databases',
176 $lowercased_word = strtolower($word);
177 foreach ($uncountable as $_uncountable){
178 if(substr($lowercased_word,(-1*strlen($_uncountable))) == $_uncountable){
179 $_cached[$_original_word] = $word;
184 foreach ($irregular as $_singular => $_plural){
185 if (preg_match('/('.$_plural.')$/i', $word, $arr)) {
186 $_cached[$_original_word] = preg_replace('/('.$_plural.')$/i', substr($arr[0],0,1).substr($_singular,1), $word);
187 return $_cached[$_original_word];
191 foreach ($singular as $rule => $replacement) {
192 if (preg_match($rule, $word)) {
193 $_cached[$_original_word] = preg_replace($rule, $replacement, $word);
194 return $_cached[$_original_word];
197 $_cached[$_original_word] = $word;
200 return $_cached[$_original_word];
204 // {{{ conditionalPlural()
207 * Get the plural form of a word if first parameter is greater than 1
209 * @param integer $numer_of_records
210 * @param string $word
211 * @return string Pluralized string when number of items is greater than 1
213 function conditionalPlural($numer_of_records, $word)
215 return $numer_of_records > 1 ? AkInflector
::pluralize($word) : $word;
222 * Converts an underscored or CamelCase word into a English
225 * The titleize function converts text like "WelcomePage",
226 * "welcome_page" or "welcome page" to this "Welcome
228 * If second parameter is set to 'first' it will only
229 * capitalize the first character of the title.
233 * @param string $word Word to format as tile
234 * @param string $uppercase If set to 'first' it will only uppercase the
235 * first character. Otherwise it will uppercase all
236 * the words in the title.
237 * @return string Text formatted as title
239 function titleize($word, $uppercase = '')
241 $uppercase = $uppercase == 'first' ?
'ucfirst' : 'ucwords';
242 return $uppercase(AkInflector
::humanize(AkInflector
::underscore($word)));
249 * Returns given word as CamelCased
251 * Converts a word like "send_email" to "SendEmail". It
252 * will remove non alphanumeric character from the word, so
253 * "who's online" will be converted to "WhoSOnline"
258 * @param string $word Word to convert to camel case
259 * @return string UpperCamelCasedWord
261 function camelize($word)
264 if(!isset($_cached[$word])){
265 if(preg_match_all('/\/(.?)/',$word,$got)){
266 foreach ($got[1] as $k=>$v){
267 $got[1][$k] = '::'.strtoupper($v);
269 $word = str_replace($got[0],$got[1],$word);
271 $_cached[$word] = str_replace(' ','',ucwords(preg_replace('/[^A-Z^a-z^0-9^:]+/',' ',$word)));
273 return $_cached[$word];
280 * Converts a word "into_it_s_underscored_version"
282 * Convert any "CamelCased" or "ordinary Word" into an
283 * "underscored_word".
285 * This can be really useful for creating friendly URLs.
289 * @param string $word Word to underscore
290 * @return string Underscored word
292 function underscore($word)
295 if(!isset($_cached[$word])){
296 $_cached[$word] = strtolower(preg_replace(
297 array('/[^A-Z^a-z^0-9^\/]+/','/([a-z\d])([A-Z])/','/([A-Z]+)([A-Z][a-z])/'),
298 array('_','\1_\2','\1_\2'), $word));
300 return $_cached[$word];
308 * Returns a human-readable string from $word
310 * Returns a human-readable string from $word, by replacing
311 * underscores with a space, and by upper-casing the initial
312 * character by default.
314 * If you need to uppercase all the words you just have to
315 * pass 'all' as a second parameter.
319 * @param string $word String to "humanize"
320 * @param string $uppercase If set to 'all' it will uppercase all the words
321 * instead of just the first one.
322 * @return string Human-readable word
324 function humanize($word, $uppercase = '')
326 $uppercase = $uppercase == 'all' ?
'ucwords' : 'ucfirst';
327 return $uppercase(str_replace('_',' ',preg_replace('/_id$/', '',$word)));
334 * Same as camelize but first char is lowercased
336 * Converts a word like "send_email" to "sendEmail". It
337 * will remove non alphanumeric character from the word, so
338 * "who's online" will be converted to "whoSOnline"
343 * @param string $word Word to lowerCamelCase
344 * @return string Returns a lowerCamelCasedWord
346 function variablize($word)
348 $word = AkInflector
::camelize($word);
349 return strtolower($word[0]).substr($word,1);
356 * Converts a class name to its table name according to rails
357 * naming conventions.
359 * Converts "Person" to "people"
364 * @param string $class_name Class name for getting related table_name.
365 * @return string plural_table_name
367 function tableize($class_name)
369 return AkInflector
::pluralize(AkInflector
::underscore($class_name));
376 * Converts a table name to its class name according to Akelos
377 * naming conventions.
379 * Converts "people" to "Person"
384 * @param string $table_name Table name for getting related ClassName.
385 * @return string SingularClassName
387 function classify($table_name)
389 return AkInflector
::camelize(AkInflector
::singularize($table_name));
396 * Converts number to its ordinal English form.
398 * This method converts 13 to 13th, 2 to 2nd ...
402 * @param integer $number Number to get its ordinal value
403 * @return string Ordinal representation of given string.
405 function ordinalize($number)
407 if (in_array(($number %
100),range(11,13))){
410 switch (($number %
10)) {
429 * Removes the module name from a module/path, Module::name or Module_ControllerClassName.
431 * Example: AkInflector::demodulize('admin/dashboard_controller'); //=> dashboard_controller
432 * AkInflector::demodulize('Admin_DashboardController'); //=> DashboardController
433 * AkInflector::demodulize('Admin::Dashboard'); //=> Dashboard
435 function demodulize($module_name)
437 $module_name = str_replace('::', '/', $module_name);
438 return (strstr($module_name, '/') ?
preg_replace('/^.*\//', '', $module_name) : (strstr($module_name, '_') ?
substr($module_name, 1+
strrpos($module_name,'_')) : $module_name));
442 * Transforms a string to its unaccented version.
443 * This might be useful for generating "friendly" URLs
445 function unaccent($text)
448 'À'=>'A', 'Á'=>'A', 'Â'=>'A', 'Ã'=>'A', 'Ä'=>'A', 'Å'=>'A', 'Æ'=>'A', 'Ç'=>'C',
449 'È'=>'E', 'É'=>'E', 'Ê'=>'E', 'Ë'=>'E', 'Ì'=>'I', 'Í'=>'I', 'Î'=>'I', 'Ï'=>'I',
450 'Ð'=>'D', 'Ñ'=>'N', 'Ò'=>'O', 'Ó'=>'O', 'Ô'=>'O', 'Õ'=>'O', 'Ö'=>'O', 'Ø'=>'O',
451 'Ù'=>'U', 'Ú'=>'U', 'Û'=>'U', 'Ü'=>'U', 'Ý'=>'Y', 'Þ'=>'T', 'ß'=>'s', 'à'=>'a',
452 'á'=>'a', 'â'=>'a', 'ã'=>'a', 'ä'=>'a', 'å'=>'a', 'æ'=>'a', 'ç'=>'c', 'è'=>'e',
453 'é'=>'e', 'ê'=>'e', 'ë'=>'e', 'ì'=>'i', 'í'=>'i', 'î'=>'i', 'ï'=>'i', 'ð'=>'e',
454 'ñ'=>'n', 'ò'=>'o', 'ó'=>'o', 'ô'=>'o', 'õ'=>'o', 'ö'=>'o', 'ø'=>'o', 'ù'=>'u',
455 'ú'=>'u', 'û'=>'u', 'ü'=>'u', 'ý'=>'y', 'þ'=>'t', 'ÿ'=>'y');
456 return str_replace(array_keys($map), array_values($map), $text);
460 function urlize($text)
462 return trim(AkInflector
::underscore(AkInflector
::unaccent($text)),'_');
466 * Returns $class_name in underscored form, with "_id" tacked on at the end.
467 * This is for use in dealing with the database.
469 * @param string $class_name
472 function foreignKey($class_name, $separate_class_name_and_id_with_underscore = true)
474 return AkInflector
::underscore(AkInflector
::humanize(AkInflector
::underscore($class_name))).($separate_class_name_and_id_with_underscore ?
"_id" : "id");
477 function toControllerFilename($name)
479 $name = str_replace('::', '/', $name);
480 return AK_CONTROLLERS_DIR
.DS
.join(DS
, array_map(array('AkInflector','underscore'), strstr($name, '/') ?
explode('/', $name) : array($name))).'_controller.php';
483 function toModelFilename($name)
485 return AK_MODELS_DIR
.DS
.AkInflector
::underscore($name).'.php';
488 function toHelperFilename($name)
490 return AK_APP_DIR
.DS
.'helpers'.DS
.AkInflector
::underscore($name).'.php';
493 function toFullName($name, $correct)
495 if (strstr($name, '_') && (strtolower($name) == $name)){
496 return AkInflector
::camelize($name);
499 if (preg_match("/^(. * )({$correct})$/i", $name, $reg)){
500 if ($reg[2] == $correct){
503 return ucfirst($reg[1].$correct);
506 return ucfirst($name.$correct);
510 function is_singular($singular)
512 return AkInflector
::singularize(AkInflector
::pluralize($singular)) == $singular;
515 function is_plural($plural)
517 return AkInflector
::pluralize(AkInflector
::singularize($plural)) == $plural;