src/Twig/TextExtension.php line 21

Open in your IDE?
  1. <?php
  2. namespace App\Twig;
  3. use Twig\Extension\AbstractExtension;
  4. use Twig\TwigFilter;
  5. class TextExtension extends AbstractExtension
  6. {
  7. public function getFilters()
  8. {
  9. return array(
  10. new TwigFilter('excerpt', array($this, 'excerptFilter')),
  11. new TwigFilter('striptags', array($this, 'stripTagsFilter')),
  12. new TwigFilter('metadescription', array($this, 'metaDescriptionFilter')),
  13. new TwigFilter('base64_encode', array($this, 'base64Encode')),
  14. new TwigFilter('unpad', array($this, 'unpad')),
  15. );
  16. }
  17. public function unpad($str, $pad = '0') {
  18. while(substr($str, 0, 1) == $pad){
  19. $str = substr($str, 1);
  20. }
  21. return $str;
  22. }
  23. public function stripTagsFilter($str) {
  24. $str = strip_tags($str);
  25. $str = str_replace("\n", "", $str);
  26. return str_replace("\r", "", $str);
  27. }
  28. public function metaDescriptionFilter($str) {
  29. $str = strip_tags($str);
  30. $str = str_replace(["\n","\r"], "", $str);
  31. return $this->excerptFilter($str, 170);
  32. }
  33. public function base64Encode($str) {
  34. return base64_encode($str);
  35. }
  36. public function excerptFilter($str, $length = 250, $suffixe = "...") {
  37. if (strlen($str) <= $length) {
  38. return $str;
  39. }
  40. // Échappe les "<" isolés (ex: "<3 ans") qui ne forment pas une balise HTML complète :
  41. // strip_tags() les interprète sinon comme une balise non fermée et supprime tout le
  42. // texte qui suit jusqu'à la fin de la chaîne, ce qui pouvait rendre l'extrait vide.
  43. $str = preg_replace('/<(?!\/?[a-zA-Z][a-zA-Z0-9]*(?:\s[^<>]*)?\/?>)/', '&lt;', $str);
  44. //$texte = strip_tags($str,'<span><a><strong><em>');
  45. $texte = strip_tags($str);
  46. // Suppression des commentaires HTML
  47. $texte = preg_replace('#<!--.*?-->#s', '', $texte);
  48. // ----------------------------------
  49. // longueur du texte brut sans html
  50. $LongueurTexteBrutSansHtml = strlen(strip_tags($texte));
  51. $MasqueHtmlSplit = '#</?([a-zA-Z1-6]+)(?: +[a-zA-Z]+="[^"]*")*( ?/)?>#';
  52. $MasqueHtmlMatch = '#<(?:/([a-zA-Z1-6]+)|([a-zA-Z1-6]+)(?: +[a-zA-Z]+="[^"]*")*( ?/)?)>#';
  53. $texte .= ' ';
  54. // ----------------------------------
  55. // Capture de tous les bouts de texte (en dehors des balises html)
  56. $BoutsTexte = preg_split($MasqueHtmlSplit, $texte, -1, PREG_SPLIT_OFFSET_CAPTURE | PREG_SPLIT_NO_EMPTY);
  57. // ----------------------------------
  58. $NombreBouts = count($BoutsTexte);
  59. if ($NombreBouts == 1) {
  60. $longueur = strlen($texte);
  61. // pour ne pas couper un mot, on va à l espace suivant
  62. return substr($texte, 0, strpos($texte, ' ', $longueur > $length ? $length : $longueur)) . $suffixe;
  63. }
  64. // ----------------------------------
  65. // Variable contenant la longueur des bouts de texte
  66. $longueur = 0;
  67. // ----------------------------------
  68. // (position du dernier élément du tableau $chaines)
  69. $indexDernierBout = $NombreBouts - 1;
  70. // ----------------------------------
  71. // 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
  72. // La position de la césure est égale à sa position [1] + la longueur du bout de texte [0] - 1 (dernier caractère)
  73. $position = $BoutsTexte[$indexDernierBout][1] + strlen($BoutsTexte[$indexDernierBout][0]) - 1;
  74. // ----------------------------------
  75. $indexBout = $indexDernierBout;
  76. $rechercheEspace = true;
  77. // ----------------------------------
  78. // Boucle parcourant l'array et ayant pour fonction d'incrémenter au fur et à mesure la longueur des morceaux de texte,
  79. // et de calculer la position de césure de l'extrait dans le texte
  80. foreach ($BoutsTexte as $index => $bout) {
  81. $longueur += strlen($bout[0]);
  82. // Si la longueur désirée de l'extrait à obtenir est atteinte
  83. if ($longueur >= $length) {
  84. // On calcule la position de césure du texte (position de chaîne + sa longueur -1 )
  85. $position_fin_bout = $bout[1] + strlen($bout[0]) - 1;
  86. // calcul de la position de césure
  87. $position = $position_fin_bout - ($longueur - $length);
  88. // On regarde si un espace est présent après la position dans le bout de texte
  89. if (($positionEspace = strpos($bout[0], ' ', $position - $bout[1])) !== false) {
  90. // Un espace est détecté dans le bout de texte APRÈS la position
  91. $position = $bout[1] + $positionEspace;
  92. $rechercheEspace = false;
  93. }
  94. // Si on ne se trouve pas sur le dernier élément
  95. if ($index != $indexDernierBout)
  96. $indexBout = $index + 1;
  97. break;
  98. }
  99. }
  100. // ----------------------------------
  101. // Donc il n'y avait pas d'espace dans le bout de texte où la position de césure sert de référence
  102. if ($rechercheEspace === true) {
  103. // Recherche d'un espace dans les bouts de texte suivants
  104. for ($i = $indexBout; $i <= $indexDernierBout; $i++) {
  105. $position = $BoutsTexte[$i][1];
  106. if (($positionEspace = strpos($BoutsTexte[$i][0], ' ')) !== false) {
  107. $position += $positionEspace;
  108. break;
  109. }
  110. }
  111. }
  112. // **********************************
  113. // COUPE DU TEXTE pour le RÉSUMÉ
  114. // **********************************
  115. // On effectue la césure sur le texte suivant la position calculée
  116. $texte = substr($texte, 0, $position);
  117. // **********************************
  118. // RECHERCHE DES BALISES HTML
  119. // **********************************
  120. // Récupération de toutes les balises du texte et de leur position (PREG_OFFSET_CAPTURE)
  121. preg_match_all($MasqueHtmlMatch, $texte, $retour, PREG_OFFSET_CAPTURE);
  122. // ----------------------------------
  123. $BoutsTag = array();
  124. // ----------------------------------
  125. foreach ($retour[0] as $index => $tag) {
  126. // Si on se trouve sur une balise unique, on passe au tour suivant
  127. if (isset($retour[3][$index][0])) {
  128. continue;
  129. }
  130. // Si le caractère slash n'est pas détecté en seconde position dans la balise entière, on est sur une balise ouvrante
  131. if ($retour[0][$index][0][1] != '/') {
  132. // On empile l'élément en début de l'array
  133. array_unshift($BoutsTag, $retour[2][$index][0]);
  134. }
  135. // Donc balise fermante
  136. else {
  137. // suppression du premier élément de l'array
  138. array_shift($BoutsTag);
  139. }
  140. }
  141. if (!empty($BoutsTag)) {
  142. foreach ($BoutsTag as $tag) {
  143. $texte .= '</' . $tag . '>';
  144. }
  145. }
  146. // ----------------------------------
  147. // si le texte brut est plus long que $length : on ajoute [...] a la fin
  148. if ($LongueurTexteBrutSansHtml > $length) {
  149. $texte .= '...';
  150. // si on a une balise fermante (/p ou /ul ou /div) a la fin :
  151. $texte = str_replace('</p> [......]', ' ... </p>', $texte);
  152. $texte = str_replace('</ul> [......]', ' ... </ul>', $texte);
  153. $texte = str_replace('</div> [......]', ' ... </div>', $texte);
  154. }
  155. // ----------------------------------
  156. // On renvoie le résumé du texte correctement formaté.
  157. $bp = 0;
  158. for ($i = 0; $i < strlen($texte); $i++) {
  159. if (strcmp(substr($texte, $i, 3), "<p>") == 0) {
  160. $bp++;
  161. //echo "1";
  162. }
  163. if (strcmp(substr($texte, $i, 4), "</p>") == 0) {
  164. $bp--;
  165. //echo"2";
  166. }
  167. }
  168. $res = '';
  169. $balisep = '';
  170. for ($j = 0; $j < $bp; $j++) {
  171. $balisep = $balisep . "</p>";
  172. }
  173. $btable = 0;
  174. for ($i = 0; $i < strlen($texte); $i++) {
  175. if (strcmp(substr($texte, $i, 6), "<table") == 0) {
  176. $btable++;
  177. }
  178. if (strcmp(substr($texte, $i, 8), "</table>") == 0) {
  179. $btable--;
  180. }
  181. }
  182. $res = '';
  183. $balisetable = '';
  184. for ($j = 0; $j < $btable; $j++) {
  185. $balisetable = $balisetable . "</table>";
  186. }
  187. $return = $texte . $balisetable . $balisep;
  188. //printr($texte); echo '<br>--------------------';
  189. return $return;
  190. }
  191. private function checkTags($str) {
  192. if ((strpos($str, '<b') !== false) && (strpos($str, '</b>') === false))
  193. $str .= '</b>';
  194. if ((strpos($str, '<a') !== false) && (strpos($str, '</a>') === false))
  195. $str .= '</a>';
  196. if ((strpos($str, '<strong') !== false) && (strpos($str, '</strong>') === false))
  197. $str .= '</strong>';
  198. if ((strpos($str, '<em') !== false) && (strpos($str, '</em>') === false))
  199. $str .= '</em>';
  200. $str .= 'test : ' . strpos('<strong', $str);
  201. return $str;
  202. }
  203. public function getName()
  204. {
  205. return 'text_extension';
  206. }
  207. }