<?php
namespace App\Twig;
use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;
class TextExtension extends AbstractExtension
{
public function getFilters()
{
return array(
new TwigFilter('excerpt', array($this, 'excerptFilter')),
new TwigFilter('striptags', array($this, 'stripTagsFilter')),
new TwigFilter('metadescription', array($this, 'metaDescriptionFilter')),
new TwigFilter('base64_encode', array($this, 'base64Encode')),
new TwigFilter('unpad', array($this, 'unpad')),
);
}
public function unpad($str, $pad = '0') {
while(substr($str, 0, 1) == $pad){
$str = substr($str, 1);
}
return $str;
}
public function stripTagsFilter($str) {
$str = strip_tags($str);
$str = str_replace("\n", "", $str);
return str_replace("\r", "", $str);
}
public function metaDescriptionFilter($str) {
$str = strip_tags($str);
$str = str_replace(["\n","\r"], "", $str);
return $this->excerptFilter($str, 170);
}
public function base64Encode($str) {
return base64_encode($str);
}
public function excerptFilter($str, $length = 250, $suffixe = "...") {
if (strlen($str) <= $length) {
return $str;
}
//$texte = strip_tags($str,'<span><a><strong><em>');
$texte = strip_tags($str);
// Suppression des commentaires HTML
$texte = preg_replace('#<!--.*?-->#s', '', $texte);
// ----------------------------------
// longueur du texte brut sans html
$LongueurTexteBrutSansHtml = strlen(strip_tags($texte));
$MasqueHtmlSplit = '#</?([a-zA-Z1-6]+)(?: +[a-zA-Z]+="[^"]*")*( ?/)?>#';
$MasqueHtmlMatch = '#<(?:/([a-zA-Z1-6]+)|([a-zA-Z1-6]+)(?: +[a-zA-Z]+="[^"]*")*( ?/)?)>#';
$texte .= ' ';
// ----------------------------------
// Capture de tous les bouts de texte (en dehors des balises html)
$BoutsTexte = preg_split($MasqueHtmlSplit, $texte, -1, PREG_SPLIT_OFFSET_CAPTURE | PREG_SPLIT_NO_EMPTY);
// ----------------------------------
$NombreBouts = count($BoutsTexte);
if ($NombreBouts == 1) {
$longueur = strlen($texte);
// pour ne pas couper un mot, on va à l espace suivant
return substr($texte, 0, strpos($texte, ' ', $longueur > $length ? $length : $longueur)) . $suffixe;
}
// ----------------------------------
// Variable contenant la longueur des bouts de texte
$longueur = 0;
// ----------------------------------
// (position du dernier élément du tableau $chaines)
$indexDernierBout = $NombreBouts - 1;
// ----------------------------------
// Position par défaut de la césure au cas où la longueur du texte serait inférieure au nombre de caractères à sélectionner
// La position de la césure est égale à sa position [1] + la longueur du bout de texte [0] - 1 (dernier caractère)
$position = $BoutsTexte[$indexDernierBout][1] + strlen($BoutsTexte[$indexDernierBout][0]) - 1;
// ----------------------------------
$indexBout = $indexDernierBout;
$rechercheEspace = true;
// ----------------------------------
// Boucle parcourant l'array et ayant pour fonction d'incrémenter au fur et à mesure la longueur des morceaux de texte,
// et de calculer la position de césure de l'extrait dans le texte
foreach ($BoutsTexte as $index => $bout) {
$longueur += strlen($bout[0]);
// Si la longueur désirée de l'extrait à obtenir est atteinte
if ($longueur >= $length) {
// On calcule la position de césure du texte (position de chaîne + sa longueur -1 )
$position_fin_bout = $bout[1] + strlen($bout[0]) - 1;
// calcul de la position de césure
$position = $position_fin_bout - ($longueur - $length);
// On regarde si un espace est présent après la position dans le bout de texte
if (($positionEspace = strpos($bout[0], ' ', $position - $bout[1])) !== false) {
// Un espace est détecté dans le bout de texte APRÈS la position
$position = $bout[1] + $positionEspace;
$rechercheEspace = false;
}
// Si on ne se trouve pas sur le dernier élément
if ($index != $indexDernierBout)
$indexBout = $index + 1;
break;
}
}
// ----------------------------------
// Donc il n'y avait pas d'espace dans le bout de texte où la position de césure sert de référence
if ($rechercheEspace === true) {
// Recherche d'un espace dans les bouts de texte suivants
for ($i = $indexBout; $i <= $indexDernierBout; $i++) {
$position = $BoutsTexte[$i][1];
if (($positionEspace = strpos($BoutsTexte[$i][0], ' ')) !== false) {
$position += $positionEspace;
break;
}
}
}
// **********************************
// COUPE DU TEXTE pour le RÉSUMÉ
// **********************************
// On effectue la césure sur le texte suivant la position calculée
$texte = substr($texte, 0, $position);
// **********************************
// RECHERCHE DES BALISES HTML
// **********************************
// Récupération de toutes les balises du texte et de leur position (PREG_OFFSET_CAPTURE)
preg_match_all($MasqueHtmlMatch, $texte, $retour, PREG_OFFSET_CAPTURE);
// ----------------------------------
$BoutsTag = array();
// ----------------------------------
foreach ($retour[0] as $index => $tag) {
// Si on se trouve sur une balise unique, on passe au tour suivant
if (isset($retour[3][$index][0])) {
continue;
}
// Si le caractère slash n'est pas détecté en seconde position dans la balise entière, on est sur une balise ouvrante
if ($retour[0][$index][0][1] != '/') {
// On empile l'élément en début de l'array
array_unshift($BoutsTag, $retour[2][$index][0]);
}
// Donc balise fermante
else {
// suppression du premier élément de l'array
array_shift($BoutsTag);
}
}
if (!empty($BoutsTag)) {
foreach ($BoutsTag as $tag) {
$texte .= '</' . $tag . '>';
}
}
// ----------------------------------
// si le texte brut est plus long que $length : on ajoute [...] a la fin
if ($LongueurTexteBrutSansHtml > $length) {
$texte .= '...';
// si on a une balise fermante (/p ou /ul ou /div) a la fin :
$texte = str_replace('</p> [......]', ' ... </p>', $texte);
$texte = str_replace('</ul> [......]', ' ... </ul>', $texte);
$texte = str_replace('</div> [......]', ' ... </div>', $texte);
}
// ----------------------------------
// On renvoie le résumé du texte correctement formaté.
$bp = 0;
for ($i = 0; $i < strlen($texte); $i++) {
if (strcmp(substr($texte, $i, 3), "<p>") == 0) {
$bp++;
//echo "1";
}
if (strcmp(substr($texte, $i, 4), "</p>") == 0) {
$bp--;
//echo"2";
}
}
$res = '';
$balisep = '';
for ($j = 0; $j < $bp; $j++) {
$balisep = $balisep . "</p>";
}
$btable = 0;
for ($i = 0; $i < strlen($texte); $i++) {
if (strcmp(substr($texte, $i, 6), "<table") == 0) {
$btable++;
}
if (strcmp(substr($texte, $i, 8), "</table>") == 0) {
$btable--;
}
}
$res = '';
$balisetable = '';
for ($j = 0; $j < $btable; $j++) {
$balisetable = $balisetable . "</table>";
}
$return = $texte . $balisetable . $balisep;
//printr($texte); echo '<br>--------------------';
return $return;
}
private function checkTags($str) {
if ((strpos($str, '<b') !== false) && (strpos($str, '</b>') === false))
$str .= '</b>';
if ((strpos($str, '<a') !== false) && (strpos($str, '</a>') === false))
$str .= '</a>';
if ((strpos($str, '<strong') !== false) && (strpos($str, '</strong>') === false))
$str .= '</strong>';
if ((strpos($str, '<em') !== false) && (strpos($str, '</em>') === false))
$str .= '</em>';
$str .= 'test : ' . strpos('<strong', $str);
return $str;
}
public function getName()
{
return 'text_extension';
}
}