Commit cf0c8c37 by Qiang Xue

Fixes #5983: Added `Inflector::sentence()`

parent 24108266
......@@ -40,6 +40,7 @@ Yii Framework 2 Change Log
- Enh #5770: Added more PHP error names for `ErrorException` (mongosoft)
- Enh #5806: Allow `Html::encode()` to be used when the application is not started (qiangxue)
- Enh #5954: `yii message` command now shows user friendly error if it's not able to parse source file (samdark)
- Enh #5983: Added `Inflector::sentence()` (pana1990, qiangxue)
- Enh: `Console::confirm()` now uses `Console::stdout()` instead of `echo` to be consistent with all other functions (cebe)
- Enh: `yii\rbac\DbManager` migration now uses database component specified in component settings instead of always using default `db` (samdark)
- Chg #3630: `yii\db\Command::queryInternal()` is now protected (samdark)
......
......@@ -566,60 +566,4 @@ class BaseArrayHelper
return true;
}
}
/**
* Converts the array to a comma-separated sentence where the last element
* is joined by the connector word.
*
* Below are some usage examples,
*
* ~~~
* // $array = ['Spain', 'France', 'Italy'];
* // working with array
* \yii\helpers\ArrayHelper::sentence($array);
* // output : Spain, France, and Italy
*
* // working with options to change the default behavior
* \yii\helpers\ArrayHelper::sentence($array, ['lastWordConnector' => ' or ']);
* // output : Spain, France or Italy
* ~~~
*
* @param array $array the array to be converted into an string
* @param array $options the options in terms of name-value pairs. The following options
* are specially handled:
*
* - wordsConnector: The sign or word used to join the elements in arrays with two or
* more elements. By default ', '.
*
* - twoWordsConnector: The sign or word used to join the elements in arrays with two
* elements. By default ' and '.
*
* - lastWordConnector: The sign or word used to join the last element in arrays with
* three or more elements. By default ', and '.
*
* @return string
*/
public static function sentence($array, $options = [])
{
$default_options = [
'wordsConnector' => ', ',
'twoWordsConnector' => ' and ',
'lastWordConnector' => ', and ',
];
$options = array_merge($default_options, $options);
$count = count($array);
switch ($count)
{
case 0:
return '';
case 1:
return $array[0];
case 2:
return $array[0] . $options['twoWordsConnector'] . $array[1];
default:
return implode($options['wordsConnector'], array_slice($array, 0, -1)) . $options['lastWordConnector'] . $array[$count - 1];
}
}
}
......@@ -488,4 +488,48 @@ class BaseInflector
return $number . 'th';
}
}
/**
* Converts a list of words into a sentence.
*
* Special treatment is done for the last few words. For example,
*
* ```php
* $words = ['Spain', 'France'];
* echo Inflector::sentence($words);
* // output: Spain and France
*
* $words = ['Spain', 'France', 'Italy'];
* echo Inflector::sentence($words);
* // output: Spain, France and Italy
*
* $words = ['Spain', 'France', 'Italy'];
* echo Inflector::sentence($words, ' & ');
* // output: Spain, France & Italy
* ```
*
* @param array $words the words to be converted into an string
* @param string $twoWordsConnector the string connecting words when there are only two
* @param string $lastWordConnector the string connecting the last two words. If this is null, it will
* take the value of `$twoWordsConnector`.
* @param string $connector the string connecting words other than those connected by
* $lastWordConnector and $twoWordsConnector
* @return string the generated sentence
*/
public static function sentence(array $words, $twoWordsConnector = ' and ', $lastWordConnector = null, $connector = ', ')
{
if ($lastWordConnector === null) {
$lastWordConnector = $twoWordsConnector;
}
switch (count($words)) {
case 0:
return '';
case 1:
return reset($words);
case 2:
return implode($twoWordsConnector, $words);
default:
return implode($connector, array_slice($words, 0, -1)) . $lastWordConnector . end($words);
}
}
}
......@@ -396,30 +396,4 @@ class ArrayHelperTest extends TestCase
$this->assertTrue(ArrayHelper::isIndexed([2 => 'a', 3 => 'b']));
$this->assertFalse(ArrayHelper::isIndexed([2 => 'a', 3 => 'b'], true));
}
public function testSentence()
{
$array = [];
$this->assertEquals('', ArrayHelper::sentence($array));
$array = ['Spain'];
$this->assertEquals('Spain', ArrayHelper::sentence($array));
$array = ['Spain', 'France'];
$this->assertEquals('Spain and France', ArrayHelper::sentence($array));
$array = ['Spain', 'France'];
$this->assertEquals('Spain or France', ArrayHelper::sentence($array, [
'twoWordsConnector' => ' or ',
]));
$array = ['Spain', 'France', 'Italy'];
$this->assertEquals('Spain, France, and Italy', ArrayHelper::sentence($array));
$array = ['Spain', 'France', 'Italy'];
$this->assertEquals('Spain - France - Italy', ArrayHelper::sentence($array, [
'wordsConnector' => ' - ',
'lastWordConnector' => ' - '
]));
}
}
......@@ -215,4 +215,34 @@ class InflectorTest extends TestCase
$this->assertEquals('111th', Inflector::ordinalize('111'));
$this->assertEquals('113th', Inflector::ordinalize('113'));
}
public function testSentence()
{
$array = [];
$this->assertEquals('', Inflector::sentence($array));
$array = ['Spain'];
$this->assertEquals('Spain', Inflector::sentence($array));
$array = ['Spain', 'France'];
$this->assertEquals('Spain and France', Inflector::sentence($array));
$array = ['Spain', 'France', 'Italy'];
$this->assertEquals('Spain, France and Italy', Inflector::sentence($array));
$array = ['Spain', 'France', 'Italy', 'Germany'];
$this->assertEquals('Spain, France, Italy and Germany', Inflector::sentence($array));
$array = ['Spain', 'France'];
$this->assertEquals('Spain or France', Inflector::sentence($array, ' or '));
$array = ['Spain', 'France', 'Italy'];
$this->assertEquals('Spain, France or Italy', Inflector::sentence($array, ' or '));
$array = ['Spain', 'France'];
$this->assertEquals('Spain and France', Inflector::sentence($array, ' and ', ' or ', ' - '));
$array = ['Spain', 'France', 'Italy'];
$this->assertEquals('Spain - France or Italy', Inflector::sentence($array, ' and ', ' or ', ' - '));
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment