Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

[DDC-2160] Smart Pluralize/Singularize support for Doctrine/Common/Util/Inflector #227

Merged
merged 3 commits into from

7 participants

Jonas Bergler doctrinebot Benjamin Eberlei Johannes Lukas Kahwe Smith Marco Pivetta Christophe Coevoet
Jonas Bergler

Doctrine/ORM/Tools/EntityGenerator should pluralize/signularize correctly.

This PR adds functionality to Doctrine/Common/Util/Inflector to singularize/pluralize. The code is largely borrowed from a similar class in the CakePHP project - I'm not sure if the updates to the class doc covers the requirements for this.

Test coverage also added.

Jonas Bergler jbergler Adding pluralize/signularize functionality to inflector. This is to b…
…e used in Doctrine/ORM/Tools/EntityGenerator to fix [DDC-2160] properly.
1dff809
doctrinebot
Collaborator

Hello,

thank you for positing this Pull Request. I have automatically opened an issue on our Jira Bug Tracker for you with the details of this Pull-Request. See the Link:

http://doctrine-project.org/jira/browse/DCOM-147

Jonas Bergler

I am updating the pull request for Doctrine/ORM/Tools/EntityGenerator upstream to use this functionality

lib/Doctrine/Common/Util/Inflector.php
((338 lines not shown))
}
+
+Inflector::reset();
Christophe Coevoet Collaborator
stof added a note

Please remove it. A file containing a class definition should contain only the class

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
lib/Doctrine/Common/Util/Inflector.php
((136 lines not shown))
+ 'headquarters', 'herpes', 'hijinks', 'Hottentotese', 'information', 'innings',
+ 'jackanapes', 'Kiplingese', 'Kongoese', 'Lucchese', 'mackerel', 'Maltese', '.*?media',
+ 'mews', 'moose', 'mumps', 'Nankingese', 'news', 'nexus', 'Niasese',
+ 'Pekingese', 'Piedmontese', 'pincers', 'Pistoiese', 'pliers', 'Portuguese',
+ 'proceedings', 'rabies', 'rice', 'rhinoceros', 'salmon', 'Sarawakese', 'scissors',
+ 'sea[- ]bass', 'series', 'Shavese', 'shears', 'siemens', 'species', 'swine', 'testes',
+ 'trousers', 'trout', 'tuna', 'Vermontese', 'Wenchowese', 'whiting', 'wildebeest',
+ 'Yengeese'
+ );
+
+ /**
+ * Method cache array.
+ *
+ * @var array
+ */
+ protected static $_cache = array();
Christophe Coevoet Collaborator
stof added a note

Please remove the leading underscore.

and properties should be declared before methods

Sure, on both $_cache and _cache() or just the variable?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
tests/Doctrine/Tests/Common/Util/InflectorTest.php
((2 lines not shown))
+
+namespace Doctrine\Tests\Common\Util
+{
+ use Doctrine\Tests\DoctrineTestCase;
+ use Doctrine\Common\Util\Inflector;
+
+ class InflectorTest extends DoctrineTestCase
+ {
+ /**
+ * testInflectingSingulars method
+ *
+ * @return void
+ */
+ public function testInflectingSingulars() {
+ Inflector::reset();
+ $this->assertEquals(Inflector::singularize('categorias'), 'categoria');
Christophe Coevoet Collaborator
stof added a note

the expectation is the first argument. Please keep them in the right order to have the right error message when it fails.

and you should probably use a dataProvider for this test

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
lib/Doctrine/Common/Util/Inflector.php
((153 lines not shown))
+ /**
+ * The initial state of Inflector so reset() works.
+ *
+ * @var array
+ */
+ protected static $_initialState = array();
+
+ /**
+ * Cache inflected values, and return if already available
+ *
+ * @param string $type Inflection type
+ * @param string $key Original value
+ * @param string $value Inflected value
+ * @return string Inflected value, from cache
+ */
+ protected static function _cache($type, $key, $value = false) {
Christophe Coevoet Collaborator
stof added a note

the curly brace should be on its own line for methods

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Benjamin Eberlei
Owner

Awesome, can you change the protected to private? This class can reastically not be overwritten, lets not make people hopes :-)

Jonas Bergler

Done

Johannes
Collaborator

How about making this a dedicated composer package which we can just reference?

There is no point in each project coming up with own inflectors, no?

Marco Pivetta
Owner

@schmittjoh the problem is, again, all the non-composer folks.

Johannes
Collaborator

@Ocramius, if they exists, let them voice their concern, but we cannot stay in the past forever.

Marco Pivetta
Owner

@schmittjoh I'm all for deprecating all that stuff, we are just forced to keep BC until 3.x.

Johannes
Collaborator

Regarding BC that should be easy here as these are all new features.

Benjamin Eberlei
Owner

@schmittjoh i haven't actually thought about this, i suppose a dedicated component for this would be pretty nice. I started an internal inquiry if we should drop PEAR support for 2.4

Benjamin Eberlei
Owner

We will drop PEAR support for 2.4, and will start moving parts out of Common into their own subprojects.

Benjamin Eberlei
Owner

I will merge this for now, then start extracting it.

Benjamin Eberlei beberlei merged commit 28b0e7f into from
Johannes
Collaborator

That's great news!

Thanks for the swift response.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Nov 23, 2012
  1. Jonas Bergler

    Adding pluralize/signularize functionality to inflector. This is to b…

    jbergler authored
    …e used in Doctrine/ORM/Tools/EntityGenerator to fix [DDC-2160] properly.
  2. Jonas Bergler

    Changes to Doctrine/Common/Util/Inflector and Doctrine/Tests/Common/U…

    jbergler authored
    …til/InflectorTest to follow coding standards
Commits on Jan 6, 2013
  1. Jonas Bergler
This page is out of date. Refresh to see the latest.
321 lib/Doctrine/Common/Util/Inflector.php
View
@@ -26,7 +26,9 @@
*
* The methods in these classes are from several different sources collected
* across several different php projects and several different authors. The
- * original author names and emails are not known
+ * original author names and emails are not known.
+ *
+ * Plurialize & Singularize implementation are borrowed from CakePHP with some modifications.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
@@ -38,6 +40,161 @@
class Inflector
{
/**
+ * Plural inflector rules
+ *
+ * @var array
+ */
+ private static $plural = array(
+ 'rules' => array(
+ '/(s)tatus$/i' => '\1\2tatuses',
+ '/(quiz)$/i' => '\1zes',
+ '/^(ox)$/i' => '\1\2en',
+ '/([m|l])ouse$/i' => '\1ice',
+ '/(matr|vert|ind)(ix|ex)$/i' => '\1ices',
+ '/(x|ch|ss|sh)$/i' => '\1es',
+ '/([^aeiouy]|qu)y$/i' => '\1ies',
+ '/(hive)$/i' => '\1s',
+ '/(?:([^f])fe|([lr])f)$/i' => '\1\2ves',
+ '/sis$/i' => 'ses',
+ '/([ti])um$/i' => '\1a',
+ '/(p)erson$/i' => '\1eople',
+ '/(m)an$/i' => '\1en',
+ '/(c)hild$/i' => '\1hildren',
+ '/(buffal|tomat)o$/i' => '\1\2oes',
+ '/(alumn|bacill|cact|foc|fung|nucle|radi|stimul|syllab|termin|vir)us$/i' => '\1i',
+ '/us$/i' => 'uses',
+ '/(alias)$/i' => '\1es',
+ '/(ax|cris|test)is$/i' => '\1es',
+ '/s$/' => 's',
+ '/^$/' => '',
+ '/$/' => 's',
+ ),
+ 'uninflected' => array(
+ '.*[nrlm]ese', '.*deer', '.*fish', '.*measles', '.*ois', '.*pox', '.*sheep', 'people', 'cookie'
+ ),
+ 'irregular' => array(
+ 'atlas' => 'atlases',
+ 'beef' => 'beefs',
+ 'brother' => 'brothers',
+ 'cafe' => 'cafes',
+ 'child' => 'children',
+ 'cookie' => 'cookies',
+ 'corpus' => 'corpuses',
+ 'cow' => 'cows',
+ 'ganglion' => 'ganglions',
+ 'genie' => 'genies',
+ 'genus' => 'genera',
+ 'graffito' => 'graffiti',
+ 'hoof' => 'hoofs',
+ 'loaf' => 'loaves',
+ 'man' => 'men',
+ 'money' => 'monies',
+ 'mongoose' => 'mongooses',
+ 'move' => 'moves',
+ 'mythos' => 'mythoi',
+ 'niche' => 'niches',
+ 'numen' => 'numina',
+ 'occiput' => 'occiputs',
+ 'octopus' => 'octopuses',
+ 'opus' => 'opuses',
+ 'ox' => 'oxen',
+ 'penis' => 'penises',
+ 'person' => 'people',
+ 'sex' => 'sexes',
+ 'soliloquy' => 'soliloquies',
+ 'testis' => 'testes',
+ 'trilby' => 'trilbys',
+ 'turf' => 'turfs'
+ )
+ );
+
+ /**
+ * Singular inflector rules
+ *
+ * @var array
+ */
+ private static $singular = array(
+ 'rules' => array(
+ '/(s)tatuses$/i' => '\1\2tatus',
+ '/^(.*)(menu)s$/i' => '\1\2',
+ '/(quiz)zes$/i' => '\\1',
+ '/(matr)ices$/i' => '\1ix',
+ '/(vert|ind)ices$/i' => '\1ex',
+ '/^(ox)en/i' => '\1',
+ '/(alias)(es)*$/i' => '\1',
+ '/(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',
+ '/ouses$/' => 'ouse',
+ '/([^a])uses$/' => '\1us',
+ '/([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',
+ '/(drive)s$/i' => '\1',
+ '/([^fo])ves$/i' => '\1fe',
+ '/(^analy)ses$/i' => '\1sis',
+ '/(analy|diagno|^ba|(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',
+ '/(c)hildren$/i' => '\1\2hild',
+ '/(n)ews$/i' => '\1\2ews',
+ '/eaus$/' => 'eau',
+ '/^(.*us)$/' => '\\1',
+ '/s$/i' => ''
+ ),
+ 'uninflected' => array(
+ '.*[nrlm]ese', '.*deer', '.*fish', '.*measles', '.*ois', '.*pox', '.*sheep', '.*ss'
+ ),
+ 'irregular' => array(
+ 'foes' => 'foe',
+ 'waves' => 'wave',
+ 'curves' => 'curve'
+ )
+ );
+
+ /**
+ * Words that should not be inflected
+ *
+ * @var array
+ */
+ private static $uninflected = array(
+ 'Amoyese', 'bison', 'Borghese', 'bream', 'breeches', 'britches', 'buffalo', 'cantus',
+ 'carp', 'chassis', 'clippers', 'cod', 'coitus', 'Congoese', 'contretemps', 'corps',
+ 'debris', 'diabetes', 'djinn', 'eland', 'elk', 'equipment', 'Faroese', 'flounder',
+ 'Foochowese', 'gallows', 'Genevese', 'Genoese', 'Gilbertese', 'graffiti',
+ 'headquarters', 'herpes', 'hijinks', 'Hottentotese', 'information', 'innings',
+ 'jackanapes', 'Kiplingese', 'Kongoese', 'Lucchese', 'mackerel', 'Maltese', '.*?media',
+ 'mews', 'moose', 'mumps', 'Nankingese', 'news', 'nexus', 'Niasese',
+ 'Pekingese', 'Piedmontese', 'pincers', 'Pistoiese', 'pliers', 'Portuguese',
+ 'proceedings', 'rabies', 'rice', 'rhinoceros', 'salmon', 'Sarawakese', 'scissors',
+ 'sea[- ]bass', 'series', 'Shavese', 'shears', 'siemens', 'species', 'swine', 'testes',
+ 'trousers', 'trout', 'tuna', 'Vermontese', 'Wenchowese', 'whiting', 'wildebeest',
+ 'Yengeese'
+ );
+
+ /**
+ * Method cache array.
+ *
+ * @var array
+ */
+ private static $cache = array();
+
+ /**
+ * The initial state of Inflector so reset() works.
+ *
+ * @var array
+ */
+ private static $initialState = array();
+
+ /**
* Convert word in to the format for a Doctrine table name. Converts 'ModelName' to 'model_name'
*
* @param string $word Word to tableize
@@ -69,4 +226,164 @@ public static function camelize($word)
{
return lcfirst(self::classify($word));
}
-}
+
+ /**
+ * Clears Inflectors inflected value caches. And resets the inflection
+ * rules to the initial values.
+ *
+ * @return void
+ */
+ public static function reset()
+ {
+ if (empty(self::$initialState)) {
+ self::$initialState = get_class_vars('Inflector');
+ return;
+ }
+ foreach (self::$initialState as $key => $val) {
+ if ($key != 'initialState') {
+ self::${$key} = $val;
+ }
+ }
+ }
+
+ /**
+ * Adds custom inflection $rules, of either 'plural' or 'singular' $type.
+ *
+ * ### Usage:
+ *
+ * {{{
+ * Inflector::rules('plural', array('/^(inflect)or$/i' => '\1ables'));
+ * Inflector::rules('plural', array(
+ * 'rules' => array('/^(inflect)ors$/i' => '\1ables'),
+ * 'uninflected' => array('dontinflectme'),
+ * 'irregular' => array('red' => 'redlings')
+ * ));
+ * }}}
+ *
+ * @param string $type The type of inflection, either 'plural' or 'singular'
+ * @param array $rules Array of rules to be added.
+ * @param boolean $reset If true, will unset default inflections for all
+ * new rules that are being defined in $rules.
+ * @return void
+ */
+ public static function rules($type, $rules, $reset = false)
+ {
+ foreach ($rules as $rule => $pattern) {
+ if (is_array($pattern)) {
+ if ($reset) {
+ self::${$type}[$rule] = $pattern;
+ } else {
+ if ($rule === 'uninflected') {
+ self::${$type}[$rule] = array_merge($pattern, self::${$type}[$rule]);
+ } else {
+ self::${$type}[$rule] = $pattern + self::${$type}[$rule];
+ }
+ }
+ unset($rules[$rule], self::${$type}['cache' . ucfirst($rule)]);
+ if (isset(self::${$type}['merged'][$rule])) {
+ unset(self::${$type}['merged'][$rule]);
+ }
+ if ($type === 'plural') {
+ self::$cache['pluralize'] = self::$cache['tableize'] = array();
+ } elseif ($type === 'singular') {
+ self::$cache['singularize'] = array();
+ }
+ }
+ }
+ self::${$type}['rules'] = $rules + self::${$type}['rules'];
+ }
+
+ /**
+ * Return $word in plural form.
+ *
+ * @param string $word Word in singular
+ * @return string Word in plural
+ */
+ public static function pluralize($word)
+ {
+ if (isset(self::$cache['pluralize'][$word])) {
+ return self::$cache['pluralize'][$word];
+ }
+
+ if (!isset(self::$plural['merged']['irregular'])) {
+ self::$plural['merged']['irregular'] = self::$plural['irregular'];
+ }
+
+ if (!isset(self::$plural['merged']['uninflected'])) {
+ self::$plural['merged']['uninflected'] = array_merge(self::$plural['uninflected'], self::$uninflected);
+ }
+
+ if (!isset(self::$plural['cacheUninflected']) || !isset(self::$plural['cacheIrregular'])) {
+ self::$plural['cacheUninflected'] = '(?:' . implode('|', self::$plural['merged']['uninflected']) . ')';
+ self::$plural['cacheIrregular'] = '(?:' . implode('|', array_keys(self::$plural['merged']['irregular'])) . ')';
+ }
+
+ if (preg_match('/(.*)\\b(' . self::$plural['cacheIrregular'] . ')$/i', $word, $regs)) {
+ self::$cache['pluralize'][$word] = $regs[1] . substr($word, 0, 1) . substr(self::$plural['merged']['irregular'][strtolower($regs[2])], 1);
+ return self::$cache['pluralize'][$word];
+ }
+
+ if (preg_match('/^(' . self::$plural['cacheUninflected'] . ')$/i', $word, $regs)) {
+ self::$cache['pluralize'][$word] = $word;
+ return $word;
+ }
+
+ foreach (self::$plural['rules'] as $rule => $replacement) {
+ if (preg_match($rule, $word)) {
+ self::$cache['pluralize'][$word] = preg_replace($rule, $replacement, $word);
+ return self::$cache['pluralize'][$word];
+ }
+ }
+ }
+
+ /**
+ * Return $word in singular form.
+ *
+ * @param string $word Word in plural
+ * @return string Word in singular
+ */
+ public static function singularize($word)
+ {
+ if (isset(self::$cache['singularize'][$word])) {
+ return self::$cache['singularize'][$word];
+ }
+
+ if (!isset(self::$singular['merged']['uninflected'])) {
+ self::$singular['merged']['uninflected'] = array_merge(
+ self::$singular['uninflected'],
+ self::$uninflected
+ );
+ }
+
+ if (!isset(self::$singular['merged']['irregular'])) {
+ self::$singular['merged']['irregular'] = array_merge(
+ self::$singular['irregular'],
+ array_flip(self::$plural['irregular'])
+ );
+ }
+
+ if (!isset(self::$singular['cacheUninflected']) || !isset(self::$singular['cacheIrregular'])) {
+ self::$singular['cacheUninflected'] = '(?:' . join('|', self::$singular['merged']['uninflected']) . ')';
+ self::$singular['cacheIrregular'] = '(?:' . join('|', array_keys(self::$singular['merged']['irregular'])) . ')';
+ }
+
+ if (preg_match('/(.*)\\b(' . self::$singular['cacheIrregular'] . ')$/i', $word, $regs)) {
+ self::$cache['singularize'][$word] = $regs[1] . substr($word, 0, 1) . substr(self::$singular['merged']['irregular'][strtolower($regs[2])], 1);
+ return self::$cache['singularize'][$word];
+ }
+
+ if (preg_match('/^(' . self::$singular['cacheUninflected'] . ')$/i', $word, $regs)) {
+ self::$cache['singularize'][$word] = $word;
+ return $word;
+ }
+
+ foreach (self::$singular['rules'] as $rule => $replacement) {
+ if (preg_match($rule, $word)) {
+ self::$cache['singularize'][$word] = preg_replace($rule, $replacement, $word);
+ return self::$cache['singularize'][$word];
+ }
+ }
+ self::$cache['singularize'][$word] = $word;
+ return $word;
+ }
+}
186 tests/Doctrine/Tests/Common/Util/InflectorTest.php
View
@@ -0,0 +1,186 @@
+<?php
+
+namespace Doctrine\Tests\Common\Util
+{
+ use Doctrine\Tests\DoctrineTestCase;
+ use Doctrine\Common\Util\Inflector;
+
+ class InflectorTest extends DoctrineTestCase
+ {
+
+ /**
+ * Singular & Plural test data. Returns an array of sample words.
+ *
+ * @return array
+ */
+ public function dataSampleWords() {
+ Inflector::reset();
+ // in the format array('singular', 'plural')
+ return array(
+ array('categoria', 'categorias'),
+ array('house', 'houses'),
+ array('powerhouse', 'powerhouses'),
+ array('Bus', 'Buses'),
+ array('bus', 'buses'),
+ array('menu', 'menus'),
+ array('news', 'news'),
+ array('food_menu', 'food_menus'),
+ array('Menu', 'Menus'),
+ array('FoodMenu', 'FoodMenus'),
+ array('quiz', 'quizzes'),
+ array('matrix_row', 'matrix_rows'),
+ array('matrix', 'matrices'),
+ array('vertex', 'vertices'),
+ array('index', 'indices'),
+ array('Alias', 'Aliases'),
+ array('Media', 'Media'),
+ array('NodeMedia', 'NodeMedia'),
+ array('alumnus', 'alumni'),
+ array('bacillus', 'bacilli'),
+ array('cactus', 'cacti'),
+ array('focus', 'foci'),
+ array('fungus', 'fungi'),
+ array('nucleus', 'nuclei'),
+ array('octopus', 'octopuses'),
+ array('radius', 'radii'),
+ array('stimulus', 'stimuli'),
+ array('syllabus', 'syllabi'),
+ array('terminus', 'termini'),
+ array('virus', 'viri'),
+ array('person', 'people'),
+ array('glove', 'gloves'),
+ array('crisis', 'crises'),
+ array('tax', 'taxes'),
+ array('wave', 'waves'),
+ array('bureau', 'bureaus'),
+ array('cafe', 'cafes'),
+ array('roof', 'roofs'),
+ array('foe', 'foes'),
+ array('cookie', 'cookies'),
+ array('', ''),
+ );
+ }
+
+ /**
+ * testInflectingSingulars method
+ *
+ * @dataProvider dataSampleWords
+ * @return void
+ */
+ public function testInflectingSingulars($singular, $plural) {
+ $this->assertEquals($singular, Inflector::singularize($plural), "'$plural' should be singularized to '$singular'");
+ }
+
+ /**
+ * testInflectingPlurals method
+ *
+ * @dataProvider dataSampleWords
+ * @return void
+ */
+ public function testInflectingPlurals($singular, $plural) {
+ $this->assertEquals($plural, Inflector::pluralize($singular), "'$singular' should be pluralized to '$plural'");
+ }
+
+ /**
+ * testCustomPluralRule method
+ *
+ * @return void
+ */
+ public function testCustomPluralRule() {
+ Inflector::reset();
+ Inflector::rules('plural', array('/^(custom)$/i' => '\1izables'));
+ $this->assertEquals(Inflector::pluralize('custom'), 'customizables');
+
+ Inflector::rules('plural', array('uninflected' => array('uninflectable')));
+ $this->assertEquals(Inflector::pluralize('uninflectable'), 'uninflectable');
+
+ Inflector::rules('plural', array(
+ 'rules' => array('/^(alert)$/i' => '\1ables'),
+ 'uninflected' => array('noflect', 'abtuse'),
+ 'irregular' => array('amaze' => 'amazable', 'phone' => 'phonezes')
+ ));
+ $this->assertEquals(Inflector::pluralize('noflect'), 'noflect');
+ $this->assertEquals(Inflector::pluralize('abtuse'), 'abtuse');
+ $this->assertEquals(Inflector::pluralize('alert'), 'alertables');
+ $this->assertEquals(Inflector::pluralize('amaze'), 'amazable');
+ $this->assertEquals(Inflector::pluralize('phone'), 'phonezes');
+ }
+
+ /**
+ * testCustomSingularRule method
+ *
+ * @return void
+ */
+ public function testCustomSingularRule() {
+ Inflector::reset();
+ Inflector::rules('singular', array('/(eple)r$/i' => '\1', '/(jente)r$/i' => '\1'));
+
+ $this->assertEquals(Inflector::singularize('epler'), 'eple');
+ $this->assertEquals(Inflector::singularize('jenter'), 'jente');
+
+ Inflector::rules('singular', array(
+ 'rules' => array('/^(bil)er$/i' => '\1', '/^(inflec|contribu)tors$/i' => '\1ta'),
+ 'uninflected' => array('singulars'),
+ 'irregular' => array('spins' => 'spinor')
+ ));
+
+ $this->assertEquals(Inflector::singularize('inflectors'), 'inflecta');
+ $this->assertEquals(Inflector::singularize('contributors'), 'contributa');
+ $this->assertEquals(Inflector::singularize('spins'), 'spinor');
+ $this->assertEquals(Inflector::singularize('singulars'), 'singulars');
+ }
+
+ /**
+ * test that setting new rules clears the inflector caches.
+ *
+ * @return void
+ */
+ public function testRulesClearsCaches() {
+ Inflector::reset();
+ $this->assertEquals(Inflector::singularize('Bananas'), 'Banana');
+ $this->assertEquals(Inflector::pluralize('Banana'), 'Bananas');
+
+ Inflector::rules('singular', array(
+ 'rules' => array('/(.*)nas$/i' => '\1zzz')
+ ));
+ $this->assertEquals('Banazzz', Inflector::singularize('Bananas'), 'Was inflected with old rules.');
+
+ Inflector::rules('plural', array(
+ 'rules' => array('/(.*)na$/i' => '\1zzz'),
+ 'irregular' => array('corpus' => 'corpora')
+ ));
+ $this->assertEquals(Inflector::pluralize('Banana'), 'Banazzz', 'Was inflected with old rules.');
+ $this->assertEquals(Inflector::pluralize('corpus'), 'corpora', 'Was inflected with old irregular form.');
+ }
+
+ /**
+ * Test resetting inflection rules.
+ *
+ * @return void
+ */
+ public function testCustomRuleWithReset() {
+ Inflector::reset();
+ $uninflected = array('atlas', 'lapis', 'onibus', 'pires', 'virus', '.*x');
+ $pluralIrregular = array('as' => 'ases');
+
+ Inflector::rules('singular', array(
+ 'rules' => array('/^(.*)(a|e|o|u)is$/i' => '\1\2l'),
+ 'uninflected' => $uninflected,
+ ), true);
+
+ Inflector::rules('plural', array(
+ 'rules' => array(
+ '/^(.*)(a|e|o|u)l$/i' => '\1\2is',
+ ),
+ 'uninflected' => $uninflected,
+ 'irregular' => $pluralIrregular
+ ), true);
+
+ $this->assertEquals(Inflector::pluralize('Alcool'), 'Alcoois');
+ $this->assertEquals(Inflector::pluralize('Atlas'), 'Atlas');
+ $this->assertEquals(Inflector::singularize('Alcoois'), 'Alcool');
+ $this->assertEquals(Inflector::singularize('Atlas'), 'Atlas');
+ }
+ }
+}
+
Something went wrong with that request. Please try again.