Add a QuickStringTrait::prioritizedString() method for joining, prioritizing, and trimming string parts.

This commit is contained in:
Michael Stenta 2022-01-19 09:44:16 -05:00
parent 278efbf27a
commit 5ef95da81f
3 changed files with 129 additions and 0 deletions

View File

@ -143,6 +143,12 @@ Available traits and the methods that they provide include:
- `QuickStringTrait`
- `trimString($value, $max_length, $suffix)` - Trims a string down to the
specified length, respecting word boundaries.
- `prioritizedString($strings, $priority_keys, $max_length, $suffix)` -
Concatenates strings together with some intelligence for prioritizing
certain parts when the full string will not fit within a maximum length.
Expects a keyed array of strings to concatenate together, along with an
optional array of keys that should be prioritized in case the full string
won't fit.
- `QuickTermTrait`
- `createTerm($values)` - Creates and returns a new term entity from an array
of values.

View File

@ -42,4 +42,93 @@ trait QuickStringTrait {
return reset($lines) . $suffix;
}
/**
* Concatenate prioritized strings together into one, respecting max length.
*
* @param array $strings
* An array of string values to include, in order of appearance. These
* strings will be concatenated with a space. This array can be optionally
* keyed to allow the $priority_keys argument to specify which strings
* should not be truncated (if possible).
* @param array $priority_keys
* An array of strings that correspond to keys in the $strings array which
* should be given higher priority. This is used if the total length of the
* generated string exceeds the maximum allowed length.
* @param int $max_length
* The maximum length of the final string. Defaults to 255.
* @param string $suffix
* A suffix to append to the end of the string, if it is trimmed.
* Defaults to an ellipsis ().
*
* @return string
* The joined, prioritized, and trimmed string.
*/
protected function prioritizedString(array $strings = [], array $priority_keys = [], int $max_length = 255, string $suffix = '…') {
// Trim each string and remove empty ones.
foreach ($strings as $key => $string) {
$strings[$key] = trim($string);
if (empty($strings[$key])) {
unset($strings[$key]);
}
}
// Concatenate all the strings together, separated by spaces.
$combined = implode(' ', $strings);
// If the full string fits, return it.
if (mb_strlen($combined) <= $max_length) {
return $combined;
}
// If no priority keys were specified, or all keys are priority, trim the
// combined string and return it.
if (empty($priority_keys) || count($strings) == count($priority_keys)) {
return $this->trimString($combined, $max_length, $suffix);
}
// Split strings into priority and non-priority.
$priority_strings = [];
$non_priority_strings = [];
foreach ($strings as $key => $value) {
if (in_array($key, $priority_keys)) {
$priority_strings[$key] = $value;
}
else {
$non_priority_strings[$key] = $value;
}
}
// If the priority strings alone will not fit, join and trim them alone.
$priority_string = implode(' ', $priority_strings);
if (mb_strlen($priority_string) > $max_length) {
return $this->trimString($priority_string, $max_length);
}
// Measure how many characters are left after accounting for priority
// strings and spaces between strings.
$remaining_length = $max_length - mb_strlen($priority_string) - count($non_priority_strings);
// Divide the remaining characters by the number of non-priority strings.
$non_priority_max_length = floor($remaining_length / count($non_priority_strings));
// If the maximum length of non-priority strings is greater than zero,
// trim each, concatenate the full string, perform a final trim, and return.
if (!empty($non_priority_max_length)) {
$parts = [];
foreach ($strings as $key => $value) {
if (in_array($key, $priority_keys)) {
$parts[] = $value;
}
else {
$parts[] = $this->trimString($value, $non_priority_max_length);
}
}
return $this->trimString(implode(' ', $parts), $max_length);
}
// Otherwise, trim and return the priority string.
return $this->trimString($priority_string, $max_length);
}
}

View File

@ -38,4 +38,38 @@ class QuickStringTest extends KernelTestBase {
$this->assertEquals($trimmed_extra_long_string, $name);
}
/**
* Test prioritizedString() method.
*/
public function testPrioritizedString() {
// Define simple name parts.
$parts = [
'foo' => 'Foo',
'bar' => 'Bar',
'baz' => 'Baz',
];
// Test simple name.
$name = $this->prioritizedString($parts);
$this->assertEquals('Foo Bar Baz', $name);
// Test simple maximum lengths.
$name = $this->prioritizedString($parts, [], 1);
$this->assertEquals('…', $name);
$name = $this->prioritizedString($parts, [], 5);
$this->assertEquals('Foo…', $name);
$name = $this->prioritizedString($parts, [], 10);
$this->assertEquals('Foo Bar…', $name);
// Test custom suffix.
$name = $this->prioritizedString($parts, [], 3, 'OO');
$this->assertEquals('FOO', $name);
// Test priority keys.
$priority_keys = ['foo', 'baz'];
$name = $this->prioritizedString($parts, $priority_keys, 10);
$this->assertEquals('Foo B… Baz', $name);
}
}