You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
PlexShare/fuel/core/classes/inflector.php

462 lines
12 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<?php
/**
* Part of the Fuel framework.
*
* @package Fuel
* @version 1.8
* @author Fuel Development Team
* @license MIT License
* @copyright 2010 - 2016 Fuel Development Team
* @link http://fuelphp.com
*/
namespace Fuel\Core;
/**
* Some of this code was written by Flinn Mueller.
*
* @package Fuel
* @category Core
* @copyright Flinn Mueller
* @link http://docs.fuelphp.com/classes/inlector.html
*/
class Inflector
{
/**
* @var array default list of uncountable words, in English
*/
protected static $uncountable_words = array(
'equipment', 'information', 'rice', 'money',
'species', 'series', 'fish', 'meta',
);
/**
* @var array default list of iregular plural words, in English
*/
protected static $plural_rules = array(
'/^(ox)$/i' => '\1\2en', // ox
'/([m|l])ouse$/i' => '\1ice', // mouse, louse
'/(matr|vert|ind)ix|ex$/i' => '\1ices', // matrix, vertex, index
'/(x|ch|ss|sh)$/i' => '\1es', // search, switch, fix, box, process, address
'/([^aeiouy]|qu)y$/i' => '\1ies', // query, ability, agency
'/(hive)$/i' => '\1s', // archive, hive
'/(?:([^f])fe|([lr])f)$/i' => '\1\2ves', // half, safe, wife
'/sis$/i' => 'ses', // basis, diagnosis
'/([ti])um$/i' => '\1a', // datum, medium
'/(p)erson$/i' => '\1eople', // person, salesperson
'/(m)an$/i' => '\1en', // man, woman, spokesman
'/(c)hild$/i' => '\1hildren', // child
'/(buffal|tomat)o$/i' => '\1\2oes', // buffalo, tomato
'/(bu|campu)s$/i' => '\1\2ses', // bus, campus
'/(alias|status|virus)$/i' => '\1es', // alias
'/(octop)us$/i' => '\1i', // octopus
'/(ax|cris|test)is$/i' => '\1es', // axis, crisis
'/s$/' => 's', // no change (compatibility)
'/$/' => 's',
);
/**
* @var array default list of iregular singular words, in English
*/
protected static $singular_rules = array(
'/(matr)ices$/i' => '\1ix',
'/(vert|ind)ices$/i' => '\1ex',
'/^(ox)en/i' => '\1',
'/(alias)es$/i' => '\1',
'/([octop|vir])i$/i' => '\1us',
'/(cris|ax|test)es$/i' => '\1is',
'/(shoe)s$/i' => '\1',
'/(o)es$/i' => '\1',
'/(bus|campus)es$/i' => '\1',
'/([m|l])ice$/i' => '\1ouse',
'/(x|ch|ss|sh)es$/i' => '\1',
'/(m)ovies$/i' => '\1\2ovie',
'/(s)eries$/i' => '\1\2eries',
'/([^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',
'/(p)eople$/i' => '\1\2erson',
'/(m)en$/i' => '\1an',
'/(s)tatuses$/i' => '\1\2tatus',
'/(c)hildren$/i' => '\1\2hild',
'/(n)ews$/i' => '\1\2ews',
'/([^us])s$/i' => '\1',
);
/**
* Load any localized rules on first load
*/
public static function _init()
{
static::load_rules();
}
/**
* Load any localized rulesets based on the current language configuration
* If not exists, the current rules remain active
*/
public static function load_rules()
{
\Lang::load('inflector', true, false, true);
if ($rules = \Lang::get('inflector.uncountable_words', array()))
{
static::$uncountable_words = $rules;
}
if ($rules = \Lang::get('inflector.singular_rules', array()))
{
static::$singular_rules = $rules;
}
if ($rules = \Lang::get('inflector.plural_rules', array()))
{
static::$plural_rules = $rules;
}
}
/**
* Add order suffix to numbers ex. 1st 2nd 3rd 4th 5th
*
* @param int $number the number to ordinalize
* @return string the ordinalized version of $number
* @link http://snipplr.com/view/4627/a-function-to-add-a-prefix-to-numbers-ex-1st-2nd-3rd-4th-5th/
*/
public static function ordinalize($number)
{
if ( ! is_numeric($number))
{
return $number;
}
if (in_array(($number % 100), range(11, 13)))
{
return $number . 'th';
}
else
{
switch ($number % 10)
{
case 1:
return $number . 'st';
break;
case 2:
return $number . 'nd';
break;
case 3:
return $number . 'rd';
break;
default:
return $number . 'th';
break;
}
}
}
/**
* Gets the plural version of the given word
*
* @param string $word the word to pluralize
* @param int $count number of instances
* @return string the plural version of $word
*/
public static function pluralize($word, $count = 0)
{
$result = strval($word);
// If a counter is provided, and that equals 1
// return as singular.
if ($count === 1)
{
return $result;
}
if ( ! static::is_countable($result))
{
return $result;
}
foreach (static::$plural_rules as $rule => $replacement)
{
if (preg_match($rule, $result))
{
$result = preg_replace($rule, $replacement, $result);
break;
}
}
return $result;
}
/**
* Gets the singular version of the given word
*
* @param string $word the word to singularize
* @return string the singular version of $word
*/
public static function singularize($word)
{
$result = strval($word);
if ( ! static::is_countable($result))
{
return $result;
}
foreach (static::$singular_rules as $rule => $replacement)
{
if (preg_match($rule, $result))
{
$result = preg_replace($rule, $replacement, $result);
break;
}
}
return $result;
}
/**
* Takes a string that has words separated by underscores and turns it into
* a CamelCased string.
*
* @param string $underscored_word the underscored word
* @return string the CamelCased version of $underscored_word
*/
public static function camelize($underscored_word)
{
return preg_replace_callback(
'/(^|_)(.)/',
function ($parm)
{
return strtoupper($parm[2]);
},
strval($underscored_word)
);
}
/**
* Takes a CamelCased string and returns an underscore separated version.
*
* @param string $camel_cased_word the CamelCased word
* @return string an underscore separated version of $camel_cased_word
*/
public static function underscore($camel_cased_word)
{
return \Str::lower(preg_replace('/([A-Z]+)([A-Z])/', '\1_\2', preg_replace('/([a-z\d])([A-Z])/', '\1_\2', strval($camel_cased_word))));
}
/**
* Translate string to 7-bit ASCII
* Only works with UTF-8.
*
* @param string $str string to translate
* @param bool $allow_non_ascii whether to remove non ascii
* @return string translated string
*/
public static function ascii($str, $allow_non_ascii = false)
{
// Translate unicode characters to their simpler counterparts
\Config::load('ascii', true);
$foreign_characters = \Config::get('ascii');
$str = preg_replace(array_keys($foreign_characters), array_values($foreign_characters), $str);
if ( ! $allow_non_ascii)
{
return preg_replace('/[^\x09\x0A\x0D\x20-\x7E]/', '', $str);
}
return $str;
}
/**
* Converts your text to a URL-friendly title so it can be used in the URL.
* Only works with UTF8 input and and only outputs 7 bit ASCII characters.
*
* @param string $str the text
* @param string $sep the separator
* @param bool $lowercase whether to convert to lowercase
* @param bool $allow_non_ascii whether to allow non ascii
* @return string the new title
*/
public static function friendly_title($str, $sep = '-', $lowercase = false, $allow_non_ascii = false)
{
// Remove tags
$str = \Security::strip_tags($str);
// Decode all entities to their simpler forms
$str = html_entity_decode($str, ENT_QUOTES, 'UTF-8');
// Only allow 7bit characters
$str = static::ascii($str, $allow_non_ascii);
if ($allow_non_ascii)
{
// Strip regular special chars
$str = preg_replace("#[\.;:\]\}\[\{\+\)\(\*&\^\$\#@\!±`%~']#iu", '', $str);
}
else
{
// Strip unwanted characters
$str = preg_replace("#[^a-z0-9]#i", $sep, $str);
}
// Remove all quotes
$str = preg_replace("#[\"\']#", '', $str);
// Replace apostrophes by separators
$str = preg_replace("#[\]#", '-', $str);
// Replace repeating characters
$str = preg_replace("#[/_|+ -]+#u", $sep, $str);
// Remove separators from both ends
$str = trim($str, $sep);
// And convert to lowercase if needed
if ($lowercase === true)
{
$str = \Str::lower($str);
}
return $str;
}
/**
* Turns an underscore or dash separated word and turns it into a human looking string.
*
* @param string $str the word
* @param string $sep the separator (either _ or -)
* @param bool $lowercase lowercase string and upper case first
* @return string the human version of given string
*/
public static function humanize($str, $sep = '_', $lowercase = true)
{
// Allow dash, otherwise default to underscore
$sep = $sep != '-' ? '_' : $sep;
if ($lowercase === true)
{
$str = \Str::ucfirst($str);
}
return str_replace($sep, " ", strval($str));
}
/**
* Takes the class name out of a modulized string.
*
* @param string $class_name_in_module the modulized class
* @return string the string without the class name
*/
public static function demodulize($class_name_in_module)
{
return preg_replace('/^.*::/', '', strval($class_name_in_module));
}
/**
* Takes the namespace off the given class name.
*
* @param string $class_name the class name
* @return string the string without the namespace
*/
public static function denamespace($class_name)
{
$class_name = trim($class_name, '\\');
if ($last_separator = strrpos($class_name, '\\'))
{
$class_name = substr($class_name, $last_separator + 1);
}
return $class_name;
}
/**
* Returns the namespace of the given class name.
*
* @param string $class_name the class name
* @return string the string without the namespace
*/
public static function get_namespace($class_name)
{
$class_name = trim($class_name, '\\');
if ($last_separator = strrpos($class_name, '\\'))
{
return substr($class_name, 0, $last_separator + 1);
}
return '';
}
/**
* Takes a class name and determines the table name. The table name is a
* pluralized version of the class name.
*
* @param string $class_name the table name
* @return string the table name
*/
public static function tableize($class_name)
{
$class_name = static::denamespace($class_name);
if (strncasecmp($class_name, 'Model_', 6) === 0)
{
$class_name = substr($class_name, 6);
}
return \Str::lower(static::pluralize(static::underscore($class_name)));
}
/**
* Takes an underscored classname and uppercases all letters after the underscores.
*
* @param string $class classname
* @param string $sep separator
* @return string
*/
public static function words_to_upper($class, $sep = '_')
{
return str_replace(' ', $sep, ucwords(str_replace($sep, ' ', $class)));
}
/**
* Takes a table name and creates the class name.
*
* @param string $name the table name
* @param bool $force_singular whether to singularize the table name or not
* @return string the class name
*/
public static function classify($name, $force_singular = true)
{
$class = ($force_singular) ? static::singularize($name) : $name;
return static::words_to_upper($class);
}
/**
* Gets the foreign key for a given class.
*
* @param string $class_name the class name
* @param bool $use_underscore whether to use an underscore or not
* @return string the foreign key
*/
public static function foreign_key($class_name, $use_underscore = true)
{
$class_name = static::denamespace(\Str::lower($class_name));
if (strncasecmp($class_name, 'Model_', 6) === 0)
{
$class_name = substr($class_name, 6);
}
return static::underscore(static::demodulize($class_name)).($use_underscore ? "_id" : "id");
}
/**
* Checks if the given word has a plural version.
*
* @param string $word the word to check
* @return bool if the word is countable
*/
public static function is_countable($word)
{
return ! (\in_array(\Str::lower(\strval($word)), static::$uncountable_words));
}
}