* * @license http://opensource.org/licenses/bsd-license.php BSD * * @version $Id$ * */ class Solar_Inflect extends Solar_Base { /** * * Default configuration values. * * @config array identical Words that do not change from singular to plural. * * @config array irregular Irregular singular-to-plural inflections. * * @config array to_singular Rules for preg_replace() to convert plurals to singulars. * * @config array to_plural Rules for preg_replace() to convert singulars to plurals. * * @var array * */ protected $_Solar_Inflect = array( 'identical' => array(), 'irregular' => array(), 'to_singular' => array(), 'to_plural' => array(), ); /** * * A list of words that are the same in singular and plural. * * This list is adapted from Ruby on Rails ActiveSupport inflections. * * @var array * */ protected $_identical = array( 'equipment', 'fish', 'information', 'money', 'rice', 'series', 'sheep', 'species', ); /** * * Irregular singular-to-plural conversions. * * Array format is "singular" => "plural" and are literal text, not * regular expressions. * * This list is adapted from Ruby on Rails ActiveSupport inflections. * * @var array * */ protected $_irregular = array( 'child' => 'children', 'man' => 'men', 'move' => 'moves', 'person' => 'people', 'sex' => 'sexes', ); /** * * Regex rules for converting plural to singular. * * Array format is "pattern" => "replacement" for [[php::preg_replace() | ]]. * * All patterns are treated as '/pattern$/i'. * * This list is adapted from Ruby on Rails ActiveSupport inflections. * * @var array * */ protected $_to_singular = array( 's' => '', '(n)ews' => '$1ews', '([ti])a' => '$1um', '((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses' => '$1$2sis', '(^analy)ses' => '$1sis', '([^f])ves' => '$1fe', '(hive)s' => '$1', '(tive)s' => '$1', '([lr])ves' => '$1f', '([^aeiouy]|qu)ies' => '$1y', '(s)eries' => '$1eries', '(m)ovies' => '$1ovie', '(x|ch|ss|sh)es' => '$1', '([m|l])ice' => '$1ouse', '(bus)es' => '$1', '(o)es' => '$1', '(shoe)s' => '$1', '(cris|ax|test)es' => '$1is', '(octop|vir)i' => '$1us', '(alias|status)es' => '$1', '^(ox)en' => '$1', '(vert|ind)ices' => '$1ex', '(matr)ices' => '$1ix', '(quiz)zes' => '$1', ); /** * * Regex rules for converting singular to plural. * * Array format is "pattern" => "replacement" for [[php::preg_replace() | ]]. * * All patterns are treated as '/pattern$/i'. * * This list is taken from Ruby on Rails ActiveSupport inflections. * * @var array * */ protected $_to_plural = array( '' => 's', 's' => 's', '(ax|test)is' => '$1es', '(octop|vir)us' => '$1i', '(alias|status)' => '$1es', '(bu)s' => '$1ses', '(buffal|tomat)o' => '$1oes', '([ti])um' => '$1a', 'sis' => 'ses', '(?:([^f])fe|([lr])f)' => '$1$2ves', '(hive)' => '$1s', '([^aeiouy]|qu)y' => '$1ies', '(x|ch|ss|sh)' => '$1es', '(matr|vert|ind)ix|ex' => '$1ices', '([m|l])ouse' => '$1ice', '^(ox)' => '$1en', '(quiz)' => '$1zes', ); /** * * Post-construction tasks to complete object construction. * * @return void * */ protected function _postConstruct() { parent::_postConstruct(); // append to the default arrays from configs $list = array('identical', 'irregular', 'to_singular', 'to_plural'); foreach ($list as $key) { if ($this->_config[$key]) { $var = "_$key"; $this->$var = array_merge( $this->$var, (array) $this->_config[$key] ); } } // reverse rules so they are processed in LIFO order $this->_to_plural = array_reverse($this->_to_plural); $this->_to_singular = array_reverse($this->_to_singular); } /** * * Returns a singular word as a plural. * * @param string $str A singular word. * * @return string The plural form of the word. * */ public function toPlural($str) { $key = strtolower($str); // look for words that are the same either way if (in_array($key, $this->_identical)) { return $str; } // look for irregular words foreach ($this->_irregular as $key => $val) { $find = "/(.*)$key\$/i"; $repl = "\$1$val"; if (preg_match($find, $str)) { return preg_replace($find, $repl, $str); } } // apply normal rules foreach($this->_to_plural as $find => $repl) { $find = '/' . $find . '$/i'; if (preg_match($find, $str)) { return preg_replace($find, $repl, $str); } } // couldn't find a plural form return $str; } /** * * Returns a plural word as a singular. * * @param string $str A plural word. * * @return string The singular form of the word. * */ public function toSingular($str) { $key = strtolower($str); // look for words that are the same either way if (in_array($key, $this->_identical)) { return $str; } // look for irregular words // note that we flip singulars and plurals $list = array_flip($this->_irregular); foreach ($list as $key => $val) { $find = "/(.*)$key\$/i"; $repl = "\$1$val"; if (preg_match($find, $str)) { return preg_replace($find, $repl, $str); } } // apply normal rules foreach($this->_to_singular as $find => $repl) { $find = '/' . $find . '$/i'; if (preg_match($find, $str)) { return preg_replace($find, $repl, $str); } } // couldn't find a singular form return $str; } /** * * Returns any string, converted to using dashes with only lowercase * alphanumerics. * * @param string $str The string to convert. * * @return string The converted string. * */ public function toDashes($str) { $str = preg_replace('/[^a-z0-9 _-]/i', '', $str); $str = $this->camelToDashes($str); $str = preg_replace('/[ _-]+/', '-', $str); return $str; } /** * * Returns "foo_bar_baz" as "fooBarBaz". * * @param string $str The underscore word. * * @return string The word in camel-caps. * */ public function underToCamel($str) { $str = ucwords(str_replace('_', ' ', $str)); $str = str_replace(' ', '', $str); $str[0] = strtolower($str[0]); return $str; } /** * * Returns "foo-bar-baz" as "fooBarBaz". * * @param string $str The dashed word. * * @return string The word in camel-caps. * */ public function dashesToCamel($str) { $str = ucwords(str_replace('-', ' ', $str)); $str = str_replace(' ', '', $str); $str[0] = strtolower($str[0]); return $str; } /** * * Returns "foo_bar_baz" as "FooBarBaz". * * @param string $str The underscore word. * * @return string The word in studly-caps. * */ public function underToStudly($str) { $str = $this->underToCamel($str); $str[0] = strtoupper($str[0]); return $str; } /** * * Returns "foo-bar-baz" as "FooBarBaz". * * @param string $str The dashed word. * * @return string The word in studly-caps. * */ public function dashesToStudly($str) { $str = $this->dashesToCamel($str); $str[0] = strtoupper($str[0]); return $str; } /** * * Returns "camelCapsWord" and "CamelCapsWord" as "Camel_Caps_Word". * * @param string $str The camel-caps word. * * @return string The word with underscores in place of camel caps. * */ public function camelToUnder($str) { $str = preg_replace('/([a-z])([A-Z])/', '$1 $2', $str); $str = str_replace(' ', '_', ucwords($str)); return $str; } /** * * Returns "camelCapsWord" and "CamelCapsWord" as "camel-caps-word". * * @param string $str The camel-caps word. * * @return string The word with dashes in place of camel caps. * */ public function camelToDashes($str) { $str = preg_replace('/([a-z])([A-Z])/', '$1 $2', $str); $str = str_replace(' ', '-', ucwords($str)); return strtolower($str); } /** * * Returns "Class_Name" as "Class/Name.php". * * @param string $str The class name. * * @return string The class as a file name. * */ public function classToFile($str) { return str_replace('_', '/', $str) . '.php'; } }