Merge pull request #9696 from chrometoasters/pulls/safer-dbtext-summary

FIX Use empty array as a fallback for preg_split within DBText summary
This commit is contained in:
Daniel Hensby 2021-06-03 08:07:51 +01:00 committed by GitHub
commit 12cffe0346
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 59 additions and 10 deletions

View File

@ -80,7 +80,7 @@ class DBText extends DBString
} }
// Do a word-search // Do a word-search
$words = preg_split('/\s+/u', $value); $words = preg_split('/\s+/u', $value) ?: [];
$sentences = 0; $sentences = 0;
foreach ($words as $i => $word) { foreach ($words as $i => $word) {
if (preg_match('/(!|\?|\.)$/', $word) && !preg_match('/(Dr|Mr|Mrs|Ms|Miss|Sr|Jr|No)\.$/i', $word)) { if (preg_match('/(!|\?|\.)$/', $word) && !preg_match('/(Dr|Mr|Mrs|Ms|Miss|Sr|Jr|No)\.$/i', $word)) {
@ -133,8 +133,8 @@ class DBText extends DBString
// Split on sentences (don't remove period) // Split on sentences (don't remove period)
$sentences = array_filter(array_map(function ($str) { $sentences = array_filter(array_map(function ($str) {
return trim($str); return trim($str);
}, preg_split('@(?<=\.)@', $value))); }, preg_split('@(?<=\.)@', $value) ?: []));
$wordCount = count(preg_split('#\s+#u', $sentences[0])); $wordCount = count(preg_split('#\s+#u', $sentences[0]) ?: []);
// if the first sentence is too long, show only the first $maxWords words // if the first sentence is too long, show only the first $maxWords words
if ($wordCount > $maxWords) { if ($wordCount > $maxWords) {
@ -149,7 +149,7 @@ class DBText extends DBString
// If more sentences to process, count number of words // If more sentences to process, count number of words
if ($sentences) { if ($sentences) {
$wordCount += count(preg_split('#\s+#u', $sentences[0])); $wordCount += count(preg_split('#\s+#u', $sentences[0]) ?: []);
} }
} while ($wordCount < $maxWords && $sentences && trim($sentences[0])); } while ($wordCount < $maxWords && $sentences && trim($sentences[0]));
@ -169,7 +169,7 @@ class DBText extends DBString
} }
// Split paragraphs and return first // Split paragraphs and return first
$paragraphs = preg_split('#\n{2,}#', $value); $paragraphs = preg_split('#\n{2,}#', $value) ?: [];
return reset($paragraphs); return reset($paragraphs);
} }

View File

@ -114,7 +114,7 @@ class DBTextTest extends SapphireTest
['The little brown fox jumped over the lazy cow.', 3, 'The little brown…'], ['The little brown fox jumped over the lazy cow.', 3, 'The little brown…'],
[' This text has white space around the ends ', 3, 'This text has…'], [' This text has white space around the ends ', 3, 'This text has…'],
// Words less than the limt word count don't get truncated, ellipsis not added // Words less than the limit word count don't get truncated, ellipsis not added
['Two words', 3, 'Two words'], // Two words shouldn't have an ellipsis ['Two words', 3, 'Two words'], // Two words shouldn't have an ellipsis
['These three words', 3, 'These three words'], // Three words shouldn't have an ellipsis ['These three words', 3, 'These three words'], // Three words shouldn't have an ellipsis
['One', 3, 'One'], // Neither should one word ['One', 3, 'One'], // Neither should one word
@ -216,7 +216,7 @@ class DBTextTest extends SapphireTest
} }
/** /**
* each test is in the format input, charactere limit, highlight, expected output * each test is in the format input, character limit, highlight, expected output
* *
* @return array * @return array
*/ */
@ -268,18 +268,53 @@ class DBTextTest extends SapphireTest
'both schön and können have umlauts', 'both schön and können have umlauts',
21, 21,
'', '',
// check non existant search term // check non-existent search term
'both schön and können…', 'both schön and können…',
] ]
];
}
/**
* each test is in the format input, word limit, add ellipsis (false or string), expected output
*
* @return array
*/
public function providerSummary()
{
return [
[
'This is some text. It is a test',
3,
false,
'This is some…',
],
[
// check custom ellipsis
'This is a test text in a longer sentence and a custom ellipsis.',
8,
'...', // regular dots instead of the ellipsis character
'This is a test text in a longer...',
],
[
'both schön and können have umlauts',
5,
false,
'both schön and können have…',
],
[
// check invalid UTF8 handling — input is an invalid UTF sequence, output should be empty string
"\xf0\x28\x8c\xbc",
50,
false,
'',
],
]; ];
} }
/** /**
* @dataProvider providerContextSummary * @dataProvider providerContextSummary
* @param string $originalValue Input * @param string $originalValue Input
* @param int $limit Numer of characters * @param int $limit Number of characters
* @param string $keywords Keywords to highlight * @param string $keywords Keywords to highlight
* @param string $expectedValue Expected output (XML encoded safely) * @param string $expectedValue Expected output (XML encoded safely)
*/ */
@ -352,4 +387,18 @@ class DBTextTest extends SapphireTest
$textObj = new DBText('Test'); $textObj = new DBText('Test');
$this->assertEquals('…', $textObj->defaultEllipsis()); $this->assertEquals('…', $textObj->defaultEllipsis());
} }
/**
* @dataProvider providerSummary
* @param string $originalValue Input
* @param int $words Number of words
* @param mixed $add Ellipsis (false for default or string for custom text)
* @param string $expectedValue Expected output (XML encoded safely)
*/
public function testSummary($originalValue, $words, $add, $expectedValue)
{
$text = DBField::create_field(DBText::class, $originalValue);
$result = $text->obj('Summary', [$words, $add])->forTemplate();
$this->assertEquals($expectedValue, $result);
}
} }