Merge pull request #9634 from open-sausages/pulls/4/ellipsis

BUG Use proper ellipsis character in the various summary method.
This commit is contained in:
Robbie Averill 2020-09-10 14:48:33 -07:00 committed by GitHub
commit de61681dec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 103 additions and 57 deletions

View File

@ -119,16 +119,16 @@ abstract class DBString extends DBField
* HTML tags in the string of text. * HTML tags in the string of text.
* *
* @param int $limit Number of characters to limit by * @param int $limit Number of characters to limit by
* @param string $add Ellipsis to add to the end of truncated string * @param string|false $add Ellipsis to add to the end of truncated string
* @return string * @return string
*/ */
public function LimitCharacters($limit = 20, $add = '...') public function LimitCharacters($limit = 20, $add = false)
{ {
$value = $this->Plain(); $value = $this->Plain();
if (mb_strlen($value) <= $limit) { if (mb_strlen($value) <= $limit) {
return $value; return $value;
} }
return mb_substr($value, 0, $limit) . $add; return $this->addEllipsis(mb_substr($value, 0, $limit), $add);
} }
/** /**
@ -137,10 +137,10 @@ abstract class DBString extends DBField
* from the field. * from the field.
* *
* @param int $limit Number of characters to limit by * @param int $limit Number of characters to limit by
* @param string $add Ellipsis to add to the end of truncated string * @param string|false $add Ellipsis to add to the end of truncated string
* @return string Plain text value with limited characters * @return string Plain text value with limited characters
*/ */
public function LimitCharactersToClosestWord($limit = 20, $add = '...') public function LimitCharactersToClosestWord($limit = 20, $add = false)
{ {
// Safely convert to plain text // Safely convert to plain text
$value = $this->Plain(); $value = $this->Plain();
@ -154,11 +154,14 @@ abstract class DBString extends DBField
$value = mb_substr($value, 0, $limit); $value = mb_substr($value, 0, $limit);
// If value exceeds limit, strip punctuation off the end to the last space and apply ellipsis // If value exceeds limit, strip punctuation off the end to the last space and apply ellipsis
$value = preg_replace( $value = $this->addEllipsis(
'/[^\w_]+$/', preg_replace(
'', '/[^\w_]+$/',
mb_substr($value, 0, mb_strrpos($value, " ")) '',
) . $add; mb_substr($value, 0, mb_strrpos($value, " "))
),
$add
);
return $value; return $value;
} }
@ -166,11 +169,11 @@ abstract class DBString extends DBField
* Limit this field's content by a number of words. * Limit this field's content by a number of words.
* *
* @param int $numWords Number of words to limit by. * @param int $numWords Number of words to limit by.
* @param string $add Ellipsis to add to the end of truncated string. * @param false $add Ellipsis to add to the end of truncated string.
* *
* @return string * @return string
*/ */
public function LimitWordCount($numWords = 26, $add = '...') public function LimitWordCount($numWords = 26, $add = false)
{ {
$value = $this->Plain(); $value = $this->Plain();
$words = explode(' ', $value); $words = explode(' ', $value);
@ -180,7 +183,7 @@ abstract class DBString extends DBField
// Limit // Limit
$words = array_slice($words, 0, $numWords); $words = array_slice($words, 0, $numWords);
return implode(' ', $words) . $add; return $this->addEllipsis(implode(' ', $words), $add);
} }
/** /**
@ -212,4 +215,28 @@ abstract class DBString extends DBField
{ {
return trim($this->RAW()); return trim($this->RAW());
} }
/**
* Swap add for defaultEllipsis if need be
* @param string $string
* @param false|string $add
* @return string
*/
private function addEllipsis(string $string, $add): string
{
if ($add === false) {
$add = $this->defaultEllipsis();
}
return $string . $add;
}
/**
* Get the default string to indicate that a string was cut off.
* @return string
*/
public function defaultEllipsis(): string
{
return _t(self::class . '.ELLIPSIS', '…');
}
} }

View File

@ -115,10 +115,10 @@ class DBText extends DBString
* Builds a basic summary, up to a maximum number of words * Builds a basic summary, up to a maximum number of words
* *
* @param int $maxWords * @param int $maxWords
* @param string $add * @param string|false $add
* @return string * @return string
*/ */
public function Summary($maxWords = 50, $add = '...') public function Summary($maxWords = 50, $add = false)
{ {
// Get plain-text version // Get plain-text version
$value = $this->Plain(); $value = $this->Plain();
@ -126,6 +126,11 @@ class DBText extends DBString
return ''; return '';
} }
// If no $elipsis string is provided, use the default one.
if ($add === false) {
$add = $this->defaultEllipsis();
}
// 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);
@ -176,16 +181,16 @@ class DBText extends DBString
* @param int $characters Number of characters in the summary * @param int $characters Number of characters in the summary
* @param string $keywords Supplied string ("keywords"). Will fall back to 'Search' querystring arg. * @param string $keywords Supplied string ("keywords"). Will fall back to 'Search' querystring arg.
* @param bool $highlight Add a highlight <mark> element around search query? * @param bool $highlight Add a highlight <mark> element around search query?
* @param string $prefix Prefix text * @param string|false $prefix Prefix text
* @param string $suffix Suffix text * @param string|false $suffix Suffix text
* @return string HTML string with context * @return string HTML string with context
*/ */
public function ContextSummary( public function ContextSummary(
$characters = 500, $characters = 500,
$keywords = null, $keywords = null,
$highlight = true, $highlight = true,
$prefix = "... ", $prefix = false,
$suffix = "..." $suffix = false
) { ) {
if (!$keywords) { if (!$keywords) {
@ -193,6 +198,14 @@ class DBText extends DBString
$keywords = isset($_REQUEST['Search']) ? $_REQUEST['Search'] : ''; $keywords = isset($_REQUEST['Search']) ? $_REQUEST['Search'] : '';
} }
if ($prefix === false) {
$prefix = $this->defaultEllipsis() . ' ';
}
if ($suffix === false) {
$suffix = $this->defaultEllipsis();
}
// Get raw text value, but XML encode it (as we'll be merging with HTML tags soon) // Get raw text value, but XML encode it (as we'll be merging with HTML tags soon)
$text = Convert::raw2xml($this->Plain()); $text = Convert::raw2xml($this->Plain());
$keywords = Convert::raw2xml($keywords); $keywords = Convert::raw2xml($keywords);

View File

@ -301,7 +301,7 @@ class DBFieldTest extends SapphireTest
foreach ($allFields as $stringField) { foreach ($allFields as $stringField) {
$stringField = DBString::create_field($stringField, $value); $stringField = DBString::create_field($stringField, $value);
for ($i = 1; $i < mb_strlen($value); $i++) { for ($i = 1; $i < mb_strlen($value); $i++) {
$expected = mb_substr($value, 0, $i) . '...'; $expected = mb_substr($value, 0, $i) . '';
$this->assertEquals($expected, $stringField->LimitCharacters($i)); $this->assertEquals($expected, $stringField->LimitCharacters($i));
} }
} }
@ -311,10 +311,10 @@ class DBFieldTest extends SapphireTest
$stringObj = DBString::create_field($stringField, $value); $stringObj = DBString::create_field($stringField, $value);
// Converted to plain text // Converted to plain text
$this->assertEquals('üåäö&ÜÅÄ...', $stringObj->LimitCharacters(8)); $this->assertEquals('üåäö&ÜÅÄ', $stringObj->LimitCharacters(8));
// But which will be safely cast in templates // But which will be safely cast in templates
$this->assertEquals('üåäö&amp;ÜÅÄ...', $stringObj->obj('LimitCharacters', [8])->forTemplate()); $this->assertEquals('üåäö&amp;ÜÅÄ', $stringObj->obj('LimitCharacters', [8])->forTemplate());
} }
$this->assertEquals('ÅÄÖ', DBText::create_field('Text', 'åäö')->UpperCase()); $this->assertEquals('ÅÄÖ', DBText::create_field('Text', 'åäö')->UpperCase());

View File

@ -49,9 +49,9 @@ class DBHTMLTextTest extends SapphireTest
{ {
// HTML characters are stripped safely // HTML characters are stripped safely
return [ return [
['The little brown fox jumped over the lazy cow.', 'The little brown fox...'], ['The little brown fox jumped over the lazy cow.', 'The little brown fox'],
['<p>Short &amp; Sweet</p>', 'Short &amp; Sweet'], ['<p>Short &amp; Sweet</p>', 'Short &amp; Sweet'],
['This text contains &amp; in it', 'This text contains &amp;...'], ['This text contains &amp; in it', 'This text contains &amp;'],
]; ];
} }
@ -77,7 +77,7 @@ class DBHTMLTextTest extends SapphireTest
// HTML is converted safely to plain text // HTML is converted safely to plain text
return [ return [
// Standard words limited, ellipsis added if truncated // Standard words limited, ellipsis added if truncated
['<p>Lorem ipsum dolor sit amet</p>', 24, 'Lorem ipsum dolor sit...'], ['<p>Lorem ipsum dolor sit amet</p>', 24, 'Lorem ipsum dolor sit'],
// Complete words less than the character limit don't get truncated, ellipsis not added // Complete words less than the character limit don't get truncated, ellipsis not added
['<p>Lorem ipsum</p>', 24, 'Lorem ipsum'], ['<p>Lorem ipsum</p>', 24, 'Lorem ipsum'],
@ -88,10 +88,10 @@ class DBHTMLTextTest extends SapphireTest
['Nice &amp; Easy', 24, 'Nice &amp; Easy'], ['Nice &amp; Easy', 24, 'Nice &amp; Easy'],
// HTML is safely converted to plain text // HTML is safely converted to plain text
['<p>Lorem ipsum dolor sit amet</p>', 24, 'Lorem ipsum dolor sit...'], ['<p>Lorem ipsum dolor sit amet</p>', 24, 'Lorem ipsum dolor sit'],
['<p><span>Lorem ipsum dolor sit amet</span></p>', 24, 'Lorem ipsum dolor sit...'], ['<p><span>Lorem ipsum dolor sit amet</span></p>', 24, 'Lorem ipsum dolor sit'],
['<p>Lorem ipsum</p>', 24, 'Lorem ipsum'], ['<p>Lorem ipsum</p>', 24, 'Lorem ipsum'],
['Lorem &amp; ipsum dolor sit amet', 24, 'Lorem &amp; ipsum dolor sit...'] ['Lorem &amp; ipsum dolor sit amet', 24, 'Lorem &amp; ipsum dolor sit']
]; ];
} }
@ -151,12 +151,12 @@ class DBHTMLTextTest extends SapphireTest
[ [
'<p>A long paragraph should be cut off if limit is set</p>', '<p>A long paragraph should be cut off if limit is set</p>',
5, 5,
'A long paragraph should be...', 'A long paragraph should be',
], ],
[ [
'<p>No matter <i>how many <b>tags</b></i> are in it</p>', '<p>No matter <i>how many <b>tags</b></i> are in it</p>',
5, 5,
'No matter how many tags...', 'No matter how many tags',
], ],
[ [
'<p>A sentence is. nicer than hard limits</p>', '<p>A sentence is. nicer than hard limits</p>',
@ -299,7 +299,7 @@ class DBHTMLTextTest extends SapphireTest
'This is some text. It is a test', 'This is some text. It is a test',
20, 20,
'test', 'test',
'... text. It is a <mark>test</mark>' ' text. It is a <mark>test</mark>'
], ],
[ [
// Retains case of original string // Retains case of original string
@ -307,13 +307,13 @@ class DBHTMLTextTest extends SapphireTest
50, 50,
'some test', 'some test',
'This is <mark>some</mark> <mark>test</mark> text.' 'This is <mark>some</mark> <mark>test</mark> text.'
. ' <mark>Test</mark> <mark>test</mark> what if you have...' . ' <mark>Test</mark> <mark>test</mark> what if you have'
], ],
[ [
'Here is some text &amp; HTML included', 'Here is some text &amp; HTML included',
20, 20,
'html', 'html',
'... text &amp; <mark>HTML</mark> inc...' '… text &amp; <mark>HTML</mark> inc…'
], ],
[ [
'A dog ate a cat while looking at a Foobar', 'A dog ate a cat while looking at a Foobar',
@ -343,16 +343,16 @@ class DBHTMLTextTest extends SapphireTest
<p>with about more stuff after the line break</p>', <p>with about more stuff after the line break</p>',
35, 35,
'test', 'test',
'... really, this is a <mark>test</mark> sentence...' '… really, this is a <mark>test</mark> sentence…'
], ],
[ [
'<p>This is a lot of text before this but really, this is a test sentence</p> '<p>This is a lot of text before this but really, this is a test sentence</p>
<p>with about more stuff after the line break</p>', <p>with about more stuff after the line break</p>',
50, 50,
'with', 'with',
'... sentence<br /> ' sentence<br />
<br /> <br />
<mark>with</mark> about more stuff...' <mark>with</mark> about more stuff'
] ]
]; ];
} }
@ -442,7 +442,7 @@ class DBHTMLTextTest extends SapphireTest
); );
// Test summary methods // Test summary methods
$this->assertEquals( $this->assertEquals(
'Some content shortcode...', 'Some content shortcode',
$obj->Summary(3) $obj->Summary(3)
); );
$this->assertEquals( $this->assertEquals(
@ -450,7 +450,7 @@ class DBHTMLTextTest extends SapphireTest
$obj->LimitSentences(1) $obj->LimitSentences(1)
); );
$this->assertEquals( $this->assertEquals(
'Some content shortco...', 'Some content shortco',
$obj->LimitCharacters(20) $obj->LimitCharacters(20)
); );
} }
@ -598,7 +598,7 @@ class DBHTMLTextTest extends SapphireTest
$field->FirstSentence() $field->FirstSentence()
); );
$this->assertEquals( $this->assertEquals(
'Replaced short...', 'Replaced short',
$field->Summary(2) $field->Summary(2)
); );
$this->assertEquals( $this->assertEquals(

View File

@ -38,10 +38,10 @@ class DBTextTest extends SapphireTest
// Plain text values always encoded safely // Plain text values always encoded safely
// HTML stored in non-html fields is treated literally. // HTML stored in non-html fields is treated literally.
return [ return [
['The little brown fox jumped over the lazy cow.', 'The little brown fox...'], ['The little brown fox jumped over the lazy cow.', 'The little brown fox'],
['<p>Short & Sweet</p>', '&lt;p&gt;Short &amp; Sweet&lt;/p&gt;'], ['<p>Short & Sweet</p>', '&lt;p&gt;Short &amp; Sweet&lt;/p&gt;'],
['This text contains &amp; in it', 'This text contains &amp;...'], ['This text contains &amp; in it', 'This text contains &amp;'],
['Is an umault in schön?', 'Is an umault in schö...'], ['Is an umault in schön?', 'Is an umault in schö'],
]; ];
} }
@ -66,7 +66,7 @@ class DBTextTest extends SapphireTest
{ {
return [ return [
// Standard words limited, ellipsis added if truncated // Standard words limited, ellipsis added if truncated
['Lorem ipsum dolor sit amet', 24, 'Lorem ipsum dolor sit...'], ['Lorem ipsum dolor sit amet', 24, 'Lorem ipsum dolor sit'],
// Complete words less than the character limit don't get truncated, ellipsis not added // Complete words less than the character limit don't get truncated, ellipsis not added
['Lorem ipsum', 24, 'Lorem ipsum'], ['Lorem ipsum', 24, 'Lorem ipsum'],
@ -78,12 +78,12 @@ class DBTextTest extends SapphireTest
// HTML stored in non-html fields is treated literally. // HTML stored in non-html fields is treated literally.
// If storing HTML you should use DBHTMLText instead // If storing HTML you should use DBHTMLText instead
['<p>Lorem ipsum dolor sit amet</p>', 24, '&lt;p&gt;Lorem ipsum dolor...'], ['<p>Lorem ipsum dolor sit amet</p>', 24, '&lt;p&gt;Lorem ipsum dolor'],
['<p><span>Lorem ipsum dolor sit amet</span></p>', 24, '&lt;p&gt;&lt;span&gt;Lorem ipsum...'], ['<p><span>Lorem ipsum dolor sit amet</span></p>', 24, '&lt;p&gt;&lt;span&gt;Lorem ipsum'],
['<p>Lorem ipsum</p>', 24, '&lt;p&gt;Lorem ipsum&lt;/p&gt;'], ['<p>Lorem ipsum</p>', 24, '&lt;p&gt;Lorem ipsum&lt;/p&gt;'],
['Lorem &amp; ipsum dolor sit amet', 24, 'Lorem &amp;amp; ipsum dolor...'], ['Lorem &amp; ipsum dolor sit amet', 24, 'Lorem &amp;amp; ipsum dolor'],
['Is an umault in schön or not?', 22, 'Is an umault in schön...'], ['Is an umault in schön or not?', 22, 'Is an umault in schön'],
]; ];
} }
@ -111,8 +111,8 @@ class DBTextTest extends SapphireTest
{ {
return [ return [
// Standard words limited, ellipsis added if truncated // Standard words limited, ellipsis added if truncated
['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 limt 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
@ -122,15 +122,15 @@ class DBTextTest extends SapphireTest
// Text with special characters // Text with special characters
['Nice & Easy', 3, 'Nice &amp; Easy'], ['Nice & Easy', 3, 'Nice &amp; Easy'],
['One & Two & Three', 3, 'One &amp; Two...'], ['One & Two & Three', 3, 'One &amp; Two'],
// HTML stored in non-html fields is treated literally. // HTML stored in non-html fields is treated literally.
// If storing HTML you should use DBHTMLText instead // If storing HTML you should use DBHTMLText instead
['<p>Text inside a paragraph tag should also work</p>', 3, '&lt;p&gt;Text inside a...'], ['<p>Text inside a paragraph tag should also work</p>', 3, '&lt;p&gt;Text inside a'],
['<p>Two words</p>', 3, '&lt;p&gt;Two words&lt;/p&gt;'], ['<p>Two words</p>', 3, '&lt;p&gt;Two words&lt;/p&gt;'],
// Check UTF8 // Check UTF8
['Is an umault in schön or not?', 5, 'Is an umault in schön...'], ['Is an umault in schön or not?', 5, 'Is an umault in schön'],
]; ];
} }
@ -227,7 +227,7 @@ class DBTextTest extends SapphireTest
'This is some text. It is a test', 'This is some text. It is a test',
20, 20,
'test', 'test',
'... text. It is a <mark>test</mark>' ' text. It is a <mark>test</mark>'
], ],
[ [
// Retains case of original string // Retains case of original string
@ -235,13 +235,13 @@ class DBTextTest extends SapphireTest
50, 50,
'some test', 'some test',
'This is <mark>some</mark> <mark>test</mark> text.' 'This is <mark>some</mark> <mark>test</mark> text.'
. ' <mark>Test</mark> <mark>test</mark> what if you have...' . ' <mark>Test</mark> <mark>test</mark> what if you have'
], ],
[ [
'Here is some text & HTML included', 'Here is some text & HTML included',
20, 20,
'html', 'html',
'... text &amp; <mark>HTML</mark> inc...' '… text &amp; <mark>HTML</mark> inc…'
], ],
[ [
'A dog ate a cat while looking at a Foobar', 'A dog ate a cat while looking at a Foobar',
@ -262,14 +262,14 @@ class DBTextTest extends SapphireTest
21, 21,
'schön', 'schön',
// check UTF8 support // check UTF8 support
'both <mark>schön</mark> and können...', 'both <mark>schön</mark> and können',
], ],
[ [
'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 existant search term
'both schön and können...', 'both schön and können',
] ]
@ -346,4 +346,10 @@ class DBTextTest extends SapphireTest
$this->assertTrue(mb_check_encoding($textObj->FirstSentence(), 'UTF-8')); $this->assertTrue(mb_check_encoding($textObj->FirstSentence(), 'UTF-8'));
} }
public function testDefaultEllipsis()
{
$textObj = new DBText('Test');
$this->assertEquals('…', $textObj->defaultEllipsis());
}
} }