You've already forked joomla_test
							
							
		
			
				
	
	
		
			463 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			463 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| /**
 | |
|  * @package     Joomla.Platform
 | |
|  * @subpackage  String
 | |
|  *
 | |
|  * @copyright   Copyright (C) 2005 - 2011 Open Source Matters, Inc. All rights reserved.
 | |
|  * @license     GNU General Public License version 2 or later; see LICENSE
 | |
|  */
 | |
| 
 | |
| defined('JPATH_PLATFORM') or die;
 | |
| 
 | |
| /**
 | |
|  * Joomla Platform String Inflector Class
 | |
|  *
 | |
|  * The Inflector transforms words
 | |
|  *
 | |
|  * @package     Joomla.Platform
 | |
|  * @subpackage  String
 | |
|  * @since       12.1
 | |
|  */
 | |
| class JStringInflector
 | |
| {
 | |
| 	/**
 | |
| 	 * The singleton instance.
 | |
| 	 *
 | |
| 	 * @var    JStringInflector
 | |
| 	 * @since  12.1
 | |
| 	 */
 | |
| 	private static $_instance;
 | |
| 
 | |
| 	/**
 | |
| 	 * The inflector rules for singularisation, pluralisation and countability.
 | |
| 	 *
 | |
| 	 * @var    array
 | |
| 	 * @since  12.1
 | |
| 	 */
 | |
| 	private $_rules = array(
 | |
| 		'singular' => array(
 | |
| 			'/(matr)ices$/i' => '\1ix',
 | |
| 			'/(vert|ind)ices$/i' => '\1ex',
 | |
| 			'/(alumn|bacill|cact|foc|fung|nucle|radi|stimul|syllab|termin|viri?)i$/i' => '\1us',
 | |
| 			'/([ftw]ax)es/i' => '\1',
 | |
| 			'/(cris|ax|test)es$/i' => '\1is',
 | |
| 			'/(shoe|slave)s$/i' => '\1',
 | |
| 			'/(o)es$/i' => '\1',
 | |
| 			'/([^aeiouy]|qu)ies$/i' => '\1y',
 | |
| 			'/$1ses$/i' => '\s',
 | |
| 			'/ses$/i' => '\s',
 | |
| 			'/eaus$/' => 'eau',
 | |
| 			'/^(.*us)$/' => '\\1',
 | |
| 			'/s$/i' => '',
 | |
| 		),
 | |
| 		'plural' => array(
 | |
| 			'/([m|l])ouse$/i' => '\1ice',
 | |
| 			'/(matr|vert|ind)(ix|ex)$/i'  => '\1ices',
 | |
| 			'/(x|ch|ss|sh)$/i' => '\1es',
 | |
| 			'/([^aeiouy]|qu)y$/i' => '\1ies',
 | |
| 			'/([^aeiouy]|qu)ies$/i' => '\1y',
 | |
| 			'/(?:([^f])fe|([lr])f)$/i' => '\1\2ves',
 | |
| 			'/sis$/i' => 'ses',
 | |
| 			'/([ti])um$/i' => '\1a',
 | |
| 			'/(buffal|tomat)o$/i' => '\1\2oes',
 | |
| 			'/(alumn|bacill|cact|foc|fung|nucle|radi|stimul|syllab|termin|vir)us$/i' => '\1i',
 | |
| 			'/us$/i' => 'uses',
 | |
| 			'/(ax|cris|test)is$/i' => '\1es',
 | |
| 			'/s$/i' => 's',
 | |
| 			'/$/' => 's',
 | |
| 		),
 | |
| 		'countable' => array(
 | |
| 			'id',
 | |
| 			'hits',
 | |
| 			'clicks',
 | |
| 		),
 | |
| 	);
 | |
| 
 | |
| 	/**
 | |
| 	 * Cached inflections.
 | |
| 	 *
 | |
| 	 * The array is in the form [singular => plural]
 | |
| 	 *
 | |
| 	 * @var    array
 | |
| 	 * @since  12.1
 | |
| 	 */
 | |
| 	private $_cache = array();
 | |
| 
 | |
| 	/**
 | |
| 	 * Protected constructor.
 | |
| 	 *
 | |
| 	 * @since  12.1
 | |
| 	 */
 | |
| 	protected function __construct()
 | |
| 	{
 | |
| 		// Pre=populate the irregual singular/plural.
 | |
| 		$this
 | |
| 			->addWord('deer')
 | |
| 			->addWord('moose')
 | |
| 			->addWord('sheep')
 | |
| 			->addWord('bison')
 | |
| 			->addWord('salmon')
 | |
| 			->addWord('pike')
 | |
| 			->addWord('trout')
 | |
| 			->addWord('fish')
 | |
| 			->addWord('swine')
 | |
| 
 | |
| 			->addWord('alias', 'aliases')
 | |
| 			->addWord('bus', 'buses')
 | |
| 			->addWord('foot', 'feet')
 | |
| 			->addWord('goose', 'geese')
 | |
| 			->addWord('hive', 'hives')
 | |
| 			->addWord('louse', 'lice')
 | |
| 			->addWord('man', 'men')
 | |
| 			->addWord('mouse', 'mice')
 | |
| 			->addWord('ox', 'oxen')
 | |
| 			->addWord('quiz', 'quizes')
 | |
| 			->addWord('status', 'statuses')
 | |
| 			->addWord('tooth', 'teeth')
 | |
| 			->addWord('woman', 'women');
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Adds inflection regex rules to the inflector.
 | |
| 	 *
 | |
| 	 * @param   mixed   $data      A string or an array of strings or regex rules to add.
 | |
| 	 * @param   string  $ruleType  The rule type: singular | plural | countable
 | |
| 	 *
 | |
| 	 * @return  void
 | |
| 	 *
 | |
| 	 * @since   12.1
 | |
| 	 * @throws  InvalidArgumentException
 | |
| 	 */
 | |
| 	private function _addRule($data, $ruleType)
 | |
| 	{
 | |
| 		if (is_string($data))
 | |
| 		{
 | |
| 			$data = array($data);
 | |
| 		}
 | |
| 		elseif (!is_array($data))
 | |
| 		{
 | |
| 			// Do not translate.
 | |
| 			throw new InvalidArgumentException('Invalid inflector rule data.');
 | |
| 		}
 | |
| 
 | |
| 		foreach ($data as $rule)
 | |
| 		{
 | |
| 			// Ensure a string is pushed.
 | |
| 			array_push($this->_rules[$ruleType], (string) $rule);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Gets an inflected word from the cache where the singular form is supplied.
 | |
| 	 *
 | |
| 	 * @param   string  $singular  A singular form of a word.
 | |
| 	 *
 | |
| 	 * @return  mixed  The cached inflection or false if none found.
 | |
| 	 *
 | |
| 	 * @since   12.1
 | |
| 	 */
 | |
| 	private function _getCachedPlural($singular)
 | |
| 	{
 | |
| 		$singular = JString::strtolower($singular);
 | |
| 
 | |
| 		// Check if the word is in cache.
 | |
| 		if (isset($this->_cache[$singular]))
 | |
| 		{
 | |
| 			return $this->_cache[$singular];
 | |
| 		}
 | |
| 
 | |
| 		return false;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Gets an inflected word from the cache where the plural form is supplied.
 | |
| 	 *
 | |
| 	 * @param   string  $plural  A plural form of a word.
 | |
| 	 *
 | |
| 	 * @return  mixed  The cached inflection or false if none found.
 | |
| 	 *
 | |
| 	 * @since   12.1
 | |
| 	 */
 | |
| 	private function _getCachedSingular($plural)
 | |
| 	{
 | |
| 		$plural = JString::strtolower($plural);
 | |
| 
 | |
| 		return array_search($plural, $this->_cache);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Execute a regex from rules.
 | |
| 	 *
 | |
| 	 * The 'plural' rule type expects a singular word.
 | |
| 	 * The 'singular' rule type expects a plural word.
 | |
| 	 *
 | |
| 	 * @param   string  $word      The string input.
 | |
| 	 * @param   string  $ruleType  String (eg, singular|plural)
 | |
| 	 *
 | |
| 	 * @return  mixed  An inflected string, or false if no rule could be applied.
 | |
| 	 *
 | |
| 	 * @since   12.1
 | |
| 	 */
 | |
| 	private function _matchRegexRule($word, $ruleType)
 | |
| 	{
 | |
| 		// Cycle through the regex rules.
 | |
| 		foreach ($this->_rules[$ruleType] as $regex => $replacement)
 | |
| 		{
 | |
| 			$matches = 0;
 | |
| 			$matchedWord = preg_replace($regex, $replacement, $word, -1, $matches);
 | |
| 
 | |
| 			if ($matches > 0)
 | |
| 			{
 | |
| 				return $matchedWord;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		return false;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Sets an inflected word in the cache.
 | |
| 	 *
 | |
| 	 * @param   string  $singular  The singular form of the word.
 | |
| 	 * @param   string  $plural    The plural form of the word. If omitted, it is assumed the singular and plural are identical.
 | |
| 	 *
 | |
| 	 * @return  void
 | |
| 	 *
 | |
| 	 * @since   12.1
 | |
| 	 */
 | |
| 	private function _setCache($singular, $plural = null)
 | |
| 	{
 | |
| 		$singular = JString::strtolower($singular);
 | |
| 
 | |
| 		if ($plural === null)
 | |
| 		{
 | |
| 			$plural = $singular;
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			$plural = JString::strtolower($plural);
 | |
| 		}
 | |
| 
 | |
| 		$this->_cache[$singular] = $plural;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Adds a countable word.
 | |
| 	 *
 | |
| 	 * @param   mixed  $data  A string or an array of strings to add.
 | |
| 	 *
 | |
| 	 * @return  JStringInflector  Returns this object to support chaining.
 | |
| 	 *
 | |
| 	 * @since   12.1
 | |
| 	 */
 | |
| 	public function addCountableRule($data)
 | |
| 	{
 | |
| 		$this->_addRule($data, 'countable');
 | |
| 
 | |
| 		return $this;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Adds a specific singular-plural pair for a word.
 | |
| 	 *
 | |
| 	 * @param   string  $singular  The singular form of the word.
 | |
| 	 * @param   string  $plural    The plural form of the word. If omitted, it is assumed the singular and plural are identical.
 | |
| 	 *
 | |
| 	 * @return  JStringInflector  Returns this object to support chaining.
 | |
| 	 *
 | |
| 	 * @since   12.1
 | |
| 	 */
 | |
| 	public function addWord($singular, $plural =null)
 | |
| 	{
 | |
| 		$this->_setCache($singular, $plural);
 | |
| 
 | |
| 		return $this;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Adds a pluralisation rule.
 | |
| 	 *
 | |
| 	 * @param   mixed  $data  A string or an array of regex rules to add.
 | |
| 	 *
 | |
| 	 * @return  JStringInflector  Returns this object to support chaining.
 | |
| 	 *
 | |
| 	 * @since   12.1
 | |
| 	 */
 | |
| 	public function addPluraliseRule($data)
 | |
| 	{
 | |
| 		$this->_addRule($data, 'plural');
 | |
| 
 | |
| 		return $this;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Adds a singularisation rule.
 | |
| 	 *
 | |
| 	 * @param   mixed  $data  A string or an array of regex rules to add.
 | |
| 	 *
 | |
| 	 * @return  JStringInflector  Returns this object to support chaining.
 | |
| 	 *
 | |
| 	 * @since   12.1
 | |
| 	 */
 | |
| 	public function addSingulariseRule($data)
 | |
| 	{
 | |
| 		$this->_addRule($data, 'singular');
 | |
| 
 | |
| 		return $this;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Gets an instance of the JStringInflector singleton.
 | |
| 	 *
 | |
| 	 * @param   boolean  $new  If true (default is false), returns a new instance regardless if one exists.
 | |
| 	 *                         This argument is mainly used for testing.
 | |
| 	 *
 | |
| 	 * @return  JStringInflector
 | |
| 	 *
 | |
| 	 * @since   12.1
 | |
| 	 */
 | |
| 	public static function getInstance($new = false)
 | |
| 	{
 | |
| 		if ($new)
 | |
| 		{
 | |
| 			return new static;
 | |
| 		}
 | |
| 		elseif (!is_object(self::$_instance))
 | |
| 		{
 | |
| 			self::$_instance = new static;
 | |
| 		}
 | |
| 
 | |
| 		return self::$_instance;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Checks if a word is countable.
 | |
| 	 *
 | |
| 	 * @param   string  $word  The string input.
 | |
| 	 *
 | |
| 	 * @return  boolean  True if word is countable, false otherwise.
 | |
| 	 *
 | |
| 	 * @since  12.1
 | |
| 	 */
 | |
| 	public function isCountable($word)
 | |
| 	{
 | |
| 		return (boolean) in_array($word, $this->_rules['countable']);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Checks if a word is in a plural form.
 | |
| 	 *
 | |
| 	 * @param   string  $word  The string input.
 | |
| 	 *
 | |
| 	 * @return  boolean  True if word is plural, false if not.
 | |
| 	 *
 | |
| 	 * @since  12.1
 | |
| 	 */
 | |
| 	public function isPlural($word)
 | |
| 	{
 | |
| 		// Try the cache for an known inflection.
 | |
| 		$inflection = $this->_getCachedSingular($word);
 | |
| 
 | |
| 		if ($inflection !== false)
 | |
| 		{
 | |
| 			return true;
 | |
| 		}
 | |
| 
 | |
| 		// Compute the inflection to cache the values, and compare.
 | |
| 		return $this->toPlural($this->toSingular($word)) == $word;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Checks if a word is in a singular form.
 | |
| 	 *
 | |
| 	 * @param   string  $word  The string input.
 | |
| 	 *
 | |
| 	 * @return  boolean  True if word is singular, false if not.
 | |
| 	 *
 | |
| 	 * @since  12.1
 | |
| 	 */
 | |
| 	public function isSingular($word)
 | |
| 	{
 | |
| 		// Try the cache for an known inflection.
 | |
| 		$inflection = $this->_getCachedPlural($word);
 | |
| 
 | |
| 		if ($inflection !== false)
 | |
| 		{
 | |
| 			return true;
 | |
| 		}
 | |
| 
 | |
| 		// Compute the inflection to cache the values, and compare.
 | |
| 		return $this->toSingular($this->toPlural($word)) == $word;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Converts a word into its plural form.
 | |
| 	 *
 | |
| 	 * @param   string  $word  The singular word to pluralise.
 | |
| 	 *
 | |
| 	 * @return  mixed  An inflected string, or false if no rule could be applied.
 | |
| 	 *
 | |
| 	 * @since  12.1
 | |
| 	 */
 | |
| 	public function toPlural($word)
 | |
| 	{
 | |
| 		// Try to get the cached plural form from the singular.
 | |
| 		$cache = $this->_getCachedPlural($word);
 | |
| 		if ($cache !== false)
 | |
| 		{
 | |
| 			return $cache;
 | |
| 		}
 | |
| 
 | |
| 		// Check if the word is a known singular.
 | |
| 		if ($this->_getCachedSingular($word))
 | |
| 		{
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		// Compute the inflection.
 | |
| 		$inflected = $this->_matchRegexRule($word, 'plural');
 | |
| 		if ($inflected !== false)
 | |
| 		{
 | |
| 			$this->_setCache($word, $inflected);
 | |
| 			return $inflected;
 | |
| 		}
 | |
| 
 | |
| 		return false;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Converts a word into its singular form.
 | |
| 	 *
 | |
| 	 * @param   string  $word  The plural word to singularise.
 | |
| 	 *
 | |
| 	 * @return  mixed  An inflected string, or false if no rule could be applied.
 | |
| 	 *
 | |
| 	 * @since  12.1
 | |
| 	 */
 | |
| 	public function toSingular($word)
 | |
| 	{
 | |
| 		// Try to get the cached singular form from the plural.
 | |
| 		$cache = $this->_getCachedSingular($word);
 | |
| 		if ($cache !== false)
 | |
| 		{
 | |
| 			return $cache;
 | |
| 		}
 | |
| 
 | |
| 		// Check if the word is a known plural.
 | |
| 		if ($this->_getCachedPlural($word))
 | |
| 		{
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		// Compute the inflection.
 | |
| 		$inflected = $this->_matchRegexRule($word, 'singular');
 | |
| 		if ($inflected !== false)
 | |
| 		{
 | |
| 			$this->_setCache($inflected, $word);
 | |
| 			return $inflected;
 | |
| 		}
 | |
| 
 | |
| 		return false;
 | |
| 	}
 | |
| }
 | 
