Improved logic for plural() and singular() as words like "tax" would become "taxs" and it was tough to code in new rules.
diff --git a/system/helpers/inflector_helper.php b/system/helpers/inflector_helper.php
index c7c113b..7b99bc5 100644
--- a/system/helpers/inflector_helper.php
+++ b/system/helpers/inflector_helper.php
@@ -41,30 +41,48 @@
{
function singular($str)
{
- $str = trim($str);
- $end = substr($str, -3);
-
- $str = preg_replace('/(.*)?([s|c]h)es/i','$1$2',$str);
-
- if (strtolower($end) == 'ies')
- {
- $str = substr($str, 0, strlen($str)-3).(preg_match('/[a-z]/',$end) ? 'y' : 'Y');
- }
- elseif (strtolower($end) == 'ses')
- {
- $str = substr($str, 0, strlen($str)-2);
- }
- else
- {
- $end = strtolower(substr($str, -1));
+ $result = strval($str);
- if ($end == 's')
+ $singular_rules = array(
+ '/(matr)ices$/' => '\1ix',
+ '/(vert|ind)ices$/' => '\1ex',
+ '/^(ox)en/' => '\1',
+ '/(alias)es$/' => '\1',
+ '/([octop|vir])i$/' => '\1us',
+ '/(cris|ax|test)es$/' => '\1is',
+ '/(shoe)s$/' => '\1',
+ '/(o)es$/' => '\1',
+ '/(bus|campus)es$/' => '\1',
+ '/([m|l])ice$/' => '\1ouse',
+ '/(x|ch|ss|sh)es$/' => '\1',
+ '/(m)ovies$/' => '\1\2ovie',
+ '/(s)eries$/' => '\1\2eries',
+ '/([^aeiouy]|qu)ies$/' => '\1y',
+ '/([lr])ves$/' => '\1f',
+ '/(tive)s$/' => '\1',
+ '/(hive)s$/' => '\1',
+ '/([^f])ves$/' => '\1fe',
+ '/(^analy)ses$/' => '\1sis',
+ '/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/' => '\1\2sis',
+ '/([ti])a$/' => '\1um',
+ '/(p)eople$/' => '\1\2erson',
+ '/(m)en$/' => '\1an',
+ '/(s)tatuses$/' => '\1\2tatus',
+ '/(c)hildren$/' => '\1\2hild',
+ '/(n)ews$/' => '\1\2ews',
+ '/([^u])s$/' => '\1',
+ );
+
+ foreach ($singular_rules as $rule => $replacement)
+ {
+ if (preg_match($rule, $result))
{
- $str = substr($str, 0, strlen($str)-1);
+ $result = preg_replace($rule, $replacement, $result);
+ break;
}
}
- return $str;
+ return $result;
}
}
@@ -83,40 +101,41 @@
if ( ! function_exists('plural'))
{
function plural($str, $force = FALSE)
- {
- $str = trim($str);
- $end = substr($str, -1);
+ {
+ $result = strval($str);
+
+ $plural_rules = array(
+ '/^(ox)$/' => '\1\2en', // ox
+ '/([m|l])ouse$/' => '\1ice', // mouse, louse
+ '/(matr|vert|ind)ix|ex$/' => '\1ices', // matrix, vertex, index
+ '/(x|ch|ss|sh)$/' => '\1es', // search, switch, fix, box, process, address
+ '/([^aeiouy]|qu)y$/' => '\1ies', // query, ability, agency
+ '/(hive)$/' => '\1s', // archive, hive
+ '/(?:([^f])fe|([lr])f)$/' => '\1\2ves', // half, safe, wife
+ '/sis$/' => 'ses', // basis, diagnosis
+ '/([ti])um$/' => '\1a', // datum, medium
+ '/(p)erson$/' => '\1eople', // person, salesperson
+ '/(m)an$/' => '\1en', // man, woman, spokesman
+ '/(c)hild$/' => '\1hildren', // child
+ '/(buffal|tomat)o$/' => '\1\2oes', // buffalo, tomato
+ '/(bu|campu)s$/' => '\1\2ses', // bus, campus
+ '/(alias|status|virus)/' => '\1es', // alias
+ '/(octop)us$/' => '\1i', // octopus
+ '/(ax|cris|test)is$/' => '\1es', // axis, crisis
+ '/s$/' => 's', // no change (compatibility)
+ '/$/' => 's',
+ );
- if (preg_match('/y/i',$end))
+ foreach ($plural_rules as $rule => $replacement)
{
- // Y preceded by vowel => regular plural
- $vowels = array('a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U');
- $str = in_array(substr($str, -2, 1), $vowels) ? $str.'s' : substr($str, 0, -1).'ies';
- }
- elseif (preg_match('/h/i',$end))
- {
- if(preg_match('/^[c|s]h$/i',substr($str, -2)))
+ if (preg_match($rule, $result))
{
- $str .= 'es';
+ $result = preg_replace($rule, $replacement, $result);
+ break;
}
- else
- {
- $str .= 's';
- }
- }
- elseif (preg_match('/s/i',$end))
- {
- if ($force == TRUE)
- {
- $str .= 'es';
- }
- }
- else
- {
- $str .= 's';
}
- return $str;
+ return $result;
}
}