Captures the current working tree after theme slots, ArticleAccess, and the payment / paid-content plugins so subsequent work has a reviewable git history.
42 lines
1.1 KiB
PHP
42 lines
1.1 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Domain\Blog;
|
|
|
|
use Mews\Purifier\Facades\Purifier;
|
|
|
|
class HtmlTeaser
|
|
{
|
|
/**
|
|
* Build a teaser from already-rendered HTML.
|
|
*
|
|
* The result is always a plain-text excerpt and always withholds part of the
|
|
* body: when the configured limit covers the whole article we still cut it
|
|
* in half, so a gated article can never be served in full through a teaser.
|
|
*/
|
|
public function truncate(string $html, int $maxChars): string
|
|
{
|
|
if ($maxChars <= 0 || trim($html) === '') {
|
|
return '';
|
|
}
|
|
|
|
$text = html_entity_decode(strip_tags($html), ENT_QUOTES | ENT_HTML5, 'UTF-8');
|
|
$text = trim(preg_replace('/\s+/u', ' ', $text) ?? '');
|
|
|
|
if ($text === '') {
|
|
return '';
|
|
}
|
|
|
|
$length = mb_strlen($text);
|
|
$limit = min($maxChars, max(1, (int) floor($length / 2)));
|
|
|
|
$snippet = mb_substr($text, 0, $limit);
|
|
if ($limit < $length) {
|
|
$snippet .= '…';
|
|
}
|
|
|
|
return Purifier::clean('<p>'.e($snippet).'</p>', 'article');
|
|
}
|
|
}
|