Skip to content

Instantly share code, notes, and snippets.

@m-radzikowski
Created July 2, 2013 19:13
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save m-radzikowski/5912196 to your computer and use it in GitHub Desktop.
Save m-radzikowski/5912196 to your computer and use it in GitHub Desktop.
Twig Filter for Symfony 2 - truncate HTML string without stripping tags after reach the minimum length of displayed text
<?php
/**
* Twig Filter for Symfony 2 - truncate HTML string without stripping tags after reach the minimum length of displayed text
* Truncates only first-level tags after reach the minimum, so returned text will be >= minimum
* Works well with (only?) utf-8 encoding.
*
* Installation:
* 1. Add this file to your bundle into src/Acme/DemoBundle/Twig/TruncateHtmlExtension.php
* 2. Update namespace, if your bundle isn't Acme/DemoBundle
* 3. Register it in app/config.yml:
* services:
* truncatehtml.twig.extension:
* class: Acme/DemoBundle\Twig\TruncateHtmlExtension
* tags:
* - { name: twig.extension }
*
* Usage:
* {{ htmlstring|truncatehtml(500) }}
* There's no need to use raw filter.
*/
namespace My\FrontendBundle\Twig;
class TruncateHtmlExtension extends \Twig_Extension {
public function getName() {
return 'truncatehtml';
}
public function getFilters() {
return array('truncatehtml' => new \Twig_Filter_Method($this, 'truncatehtml', array('is_safe' => array('html'))));
}
public function truncatehtml($html, $minimum) {
$oldDocument = new \DomDocument();
$html = mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8');
$oldDocument->loadHTML('<div>'.$html.'</div>');
// remove DOCTYPE, HTML and BODY tags
$oldDocument->removeChild($oldDocument->firstChild);
$oldDocument->replaceChild($oldDocument->firstChild->firstChild->firstChild, $oldDocument->firstChild);
$currentLength = 0; // displayed text length (without markup)
$newDocument = new \DomDocument();
foreach($oldDocument->documentElement->childNodes as $node) {
if($node->nodeType != 3) { // not text node
$imported = $newDocument->importNode($node, true);
$newDocument->appendChild($imported); // copy original node to output document
$currentLength += strlen(html_entity_decode($imported->nodeValue));
if ($currentLength >= $minimum) // check if the minimum is reached
break;
}
}
$output = $newDocument->saveHTML();
return html_entity_decode($output);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment