LDAPAccountManager/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Support/Horde/Support/Inflector.php

438 lines
12 KiB
PHP

<?php
/**
* Copyright 2007-2017 Horde LLC (http://www.horde.org/)
*
* @category Horde
* @package Support
* @license http://www.horde.org/licenses/bsd
*/
/**
* Horde Inflector class.
*
* @todo Add the locale-bubbling pattern from
* Horde_Date_Parser/Horde_Support_Numerizer
*
* @category Horde
* @package Support
* @license http://www.horde.org/licenses/bsd
*/
class Horde_Support_Inflector
{
/**
* Inflection cache
*
* @var array
*/
protected $_cache = array();
/**
* Rules for pluralizing English nouns.
*
* @var array
*/
protected $_pluralizationRules = array(
'/move$/i' => 'moves',
'/sex$/i' => 'sexes',
'/child$/i' => 'children',
'/man$/i' => 'men',
'/foot$/i' => 'feet',
'/person$/i' => 'people',
'/(quiz)$/i' => '$1zes',
'/^(ox)$/i' => '$1en',
'/(m|l)ouse$/i' => '$1ice',
'/(matr|vert|ind)ix|ex$/i' => '$1ices',
'/(x|ch|ss|sh)$/i' => '$1es',
'/([^aeiouy]|qu)ies$/i' => '$1y',
'/([^aeiouy]|qu)y$/i' => '$1ies',
'/(?:([^f])fe|([lr])f)$/i' => '$1$2ves',
'/sis$/i' => 'ses',
'/([ti])um$/i' => '$1a',
'/(buffal|tomat)o$/i' => '$1oes',
'/(bu)s$/i' => '$1ses',
'/(alias|status)$/i' => '$1es',
'/(octop|vir)us$/i' => '$1i',
'/(ax|test)is$/i' => '$1es',
'/s$/i' => 's',
'/$/' => 's',
);
/**
* Rules for singularizing English nouns.
*
* @var array
*/
protected $_singularizationRules = array(
'/cookies$/i' => 'cookie',
'/moves$/i' => 'move',
'/sexes$/i' => 'sex',
'/children$/i' => 'child',
'/men$/i' => 'man',
'/feet$/i' => 'foot',
'/people$/i' => 'person',
'/databases$/i'=> 'database',
'/(quiz)zes$/i' => '\1',
'/(matr)ices$/i' => '\1ix',
'/(vert|ind)ices$/i' => '\1ex',
'/^(ox)en/i' => '\1',
'/(alias|status)es$/i' => '\1',
'/([octop|vir])i$/i' => '\1us',
'/(cris|ax|test)es$/i' => '\1is',
'/(shoe)s$/i' => '\1',
'/(o)es$/i' => '\1',
'/(bus)es$/i' => '\1',
'/([m|l])ice$/i' => '\1ouse',
'/(x|ch|ss|sh)es$/i' => '\1',
'/(m)ovies$/i' => '\1ovie',
'/(s)eries$/i' => '\1eries',
'/([^aeiouy]|qu)ies$/i' => '\1y',
'/([lr])ves$/i' => '\1f',
'/(tive)s$/i' => '\1',
'/(hive)s$/i' => '\1',
'/([^f])ves$/i' => '\1fe',
'/(^analy)ses$/i' => '\1sis',
'/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i' => '\1\2sis',
'/([ti])a$/i' => '\1um',
'/(n)ews$/i' => '\1ews',
'/(.*)s$/i' => '\1',
);
/**
* An array of words with the same singular and plural spellings.
*
* @var array
*/
protected $_uncountables = array(
'aircraft',
'cannon',
'deer',
'equipment',
'fish',
'information',
'money',
'moose',
'rice',
'series',
'sheep',
'species',
'swine',
);
/**
* Constructor.
*
* Stores a map of the uncountable words for quicker checks.
*/
public function __construct()
{
$this->_uncountables_keys = array_flip($this->_uncountables);
}
/**
* Adds an uncountable word.
*
* @param string $word The uncountable word.
*/
public function uncountable($word)
{
$this->_uncountables[] = $word;
$this->_uncountables_keys[$word] = true;
}
/**
* Singular English word to pluralize.
*
* @param string $word Word to pluralize.
*
* @return string Plural form of $word.
*/
public function pluralize($word)
{
if ($plural = $this->getCache($word, 'pluralize')) {
return $plural;
}
if (isset($this->_uncountables_keys[$word])) {
return $word;
}
foreach ($this->_pluralizationRules as $regexp => $replacement) {
$plural = preg_replace($regexp, $replacement, $word, -1, $matches);
if ($matches > 0) {
return $this->setCache($word, 'pluralize', $plural);
}
}
return $this->setCache($word, 'pluralize', $word);
}
/**
* Plural English word to singularize.
*
* @param string $word Word to singularize.
*
* @return string Singular form of $word.
*/
public function singularize($word)
{
if ($singular = $this->getCache($word, 'singularize')) {
return $singular;
}
if (isset($this->_uncountables_keys[$word])) {
return $word;
}
foreach ($this->_singularizationRules as $regexp => $replacement) {
$singular = preg_replace($regexp, $replacement, $word, -1, $matches);
if ($matches > 0) {
return $this->setCache($word, 'singularize', $singular);
}
}
return $this->setCache($word, 'singularize', $word);
}
/**
* Camel-cases a word.
*
* @todo Do we want locale-specific or locale-independent camel casing?
*
* @param string $word The word to camel-case.
* @param string $firstLetter Whether to upper or lower case the first.
* letter of each slash-separated section.
*
* @return string Camelized $word
*/
public function camelize($word, $firstLetter = 'upper')
{
if ($camelized = $this->getCache($word, 'camelize' . $firstLetter)) {
return $camelized;
}
$camelized = $word;
if (Horde_String::lower($camelized) != $camelized &&
strpos($camelized, '_') !== false) {
$camelized = str_replace('_', '/', $camelized);
}
if (strpos($camelized, '/') !== false) {
$camelized = str_replace('/', '/ ', $camelized);
}
if (strpos($camelized, '_') !== false) {
$camelized = strtr($camelized, '_', ' ');
}
$camelized = str_replace(' ', '', Horde_String::ucwords($camelized));
if ($firstLetter == 'lower') {
$parts = array();
foreach (explode('/', $camelized) as $part) {
$part[0] = Horde_String::lower($part[0]);
$parts[] = $part;
}
$camelized = implode('/', $parts);
}
return $this->setCache($word, 'camelize' . $firstLetter, $camelized);
}
/**
* Capitalizes all the words and replaces some characters in the string to
* create a nicer looking title.
*
* Titleize is meant for creating pretty output.
*
* See:
* - http://daringfireball.net/2008/05/title_case
* - http://daringfireball.net/2008/08/title_case_update
*
* Examples:
* 1. titleize("man from the boondocks") => "Man From The Boondocks"
* 2. titleize("x-men: the last stand") => "X Men: The Last Stand"
*/
public function titleize($word)
{
throw new Exception('not implemented yet');
}
/**
* The reverse of camelize().
*
* Makes an underscored form from the expression in the string.
*
* Examples:
* 1. underscore("ActiveRecord") => "active_record"
* 2. underscore("ActiveRecord_Errors") => "active_record_errors"
*
* @todo Do we want locale-specific or locale-independent lowercasing?
*/
public function underscore($camelCasedWord)
{
$word = $camelCasedWord;
if ($result = $this->getCache($word, 'underscore')) {
return $result;
}
$result = Horde_String::lower(preg_replace('/([a-z])([A-Z])/', "\${1}_\${2}", $word));
return $this->setCache($word, 'underscore', $result);
}
/**
* Replaces underscores with dashes in the string.
*
* Example:
* 1. dasherize("puni_puni") => "puni-puni"
*/
public function dasherize($underscoredWord)
{
if ($result = $this->getCache($underscoredWord, 'dasherize')) {
return $result;
}
$result = str_replace('_', '-', $this->underscore($underscoredWord));
return $this->setCache($underscoredWord, 'dasherize', $result);
}
/**
* Capitalizes the first word and turns underscores into spaces and strips
* _id.
*
* Like titleize(), this is meant for creating pretty output.
*
* Examples:
* 1. humanize("employee_salary") => "Employee salary"
* 2. humanize("author_id") => "Author"
*/
public function humanize($lowerCaseAndUnderscoredWord)
{
$word = $lowerCaseAndUnderscoredWord;
if ($result = $this->getCache($word, 'humanize')) {
return $result;
}
$result = ucfirst(str_replace('_', ' ', $this->underscore($word)));
if (substr($result, -3, 3) == ' id') {
$result = str_replace(' id', '', $result);
}
return $this->setCache($word, 'humanize', $result);
}
/**
* Removes the module part from the expression in the string.
*
* Examples:
* 1. demodulize("Fax_Job") => "Job"
* 1. demodulize("User") => "User"
*/
public function demodulize($classNameInModule)
{
$result = explode('_', $classNameInModule);
return array_pop($result);
}
/**
* Creates the name of a table like Rails does for models to table names.
*
* This method uses the pluralize() method on the last word in the string.
*
* Examples:
* 1. tableize("RawScaledScorer") => "raw_scaled_scorers"
* 2. tableize("egg_and_ham") => "egg_and_hams"
* 3. tableize("fancyCategory") => "fancy_categories"
*/
public function tableize($className)
{
if ($result = $this->getCache($className, 'tableize')) {
return $result;
}
$result = $this->pluralize($this->underscore($className));
$result = str_replace('/', '_', $result);
return $this->setCache($className, 'tableize', $result);
}
/**
* Creates a class name from a table name like Rails does for table names
* to models.
*
* Examples:
* 1. classify("egg_and_hams") => "EggAndHam"
* 2. classify("post") => "Post"
*/
public function classify($tableName)
{
if ($result = $this->getCache($tableName, 'classify')) {
return $result;
}
$result = $this->camelize($this->singularize($tableName));
// classes use underscores instead of slashes for namespaces
$result = str_replace('/', '_', $result);
return $this->setCache($tableName, 'classify', $result);
}
/**
* Creates a foreign key name from a class name.
*
* $separateClassNameAndIdWithUnderscore sets whether the method should put
* '_' between the name and 'id'.
*
* Examples:
* 1. foreignKey("Message") => "message_id"
* 2. foreignKey("Message", false) => "messageid"
* 3. foreignKey("Fax_Job") => "fax_job_id"
*/
public function foreignKey($className, $separateClassNameAndIdWithUnderscore = true)
{
throw new Exception('not implemented yet');
}
/**
* Turns a number into an ordinal string used to denote the position in an
* ordered sequence such as 1st, 2nd, 3rd, 4th.
*
* Examples:
* 1. ordinalize(1) => "1st"
* 2. ordinalize(2) => "2nd"
* 3. ordinalize(1002) => "1002nd"
* 4. ordinalize(1003) => "1003rd"
*/
public function ordinalize($number)
{
throw new Exception('not implemented yet');
}
/**
* Clears the inflection cache.
*/
public function clearCache()
{
$this->_cache = array();
}
/**
* Retuns a cached inflection.
*
* @return string | false
*/
public function getCache($word, $rule)
{
return isset($this->_cache[$word . '|' . $rule]) ?
$this->_cache[$word . '|' . $rule] : false;
}
/**
* Caches an inflection.
*
* @param string $word The word being inflected.
* @param string $rule The inflection rule.
* @param string $value The inflected value of $word.
*
* @return string The inflected value
*/
public function setCache($word, $rule, $value)
{
$this->_cache[$word . '|' . $rule] = $value;
return $value;
}
}