Changeset 125253 in spip-zone


Ignore:
Timestamp:
Jun 20, 2020, 7:11:11 AM (3 weeks ago)
Author:
JLuc
Message:

text_truncate était généreusement foireux

fixes #3

Location:
_plugins_/spip-bonux/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • _plugins_/spip-bonux/trunk

    • Property subgit:lock:e350597a9b5e15349b00a32bbc61f221a5e33930 deleted
    • Property subgit:lock:e8fa5e8de134fc9ff988073a49b3714894d8d805 set to 2020-06-20T09:11:16.279
  • _plugins_/spip-bonux/trunk/spip_bonux_options.php

    r117935 r125253  
    1 <?php
    2 /**
    3  * Plugin Spip-Bonux
    4  * Le plugin qui lave plus SPIP que SPIP
    5  * (c) 2008 Mathieu Marcillaud, Cedric Morin, Tetue
    6  * Licence GPL
    7  *
    8  */
    9 
    10 if (!defined('_ECRIRE_INC_VERSION')) {
    11         return;
    12 }
    13 
    14 // Proposer array_column
    15 if (!function_exists('array_column')) {
    16         function array_column($input = null, $columnKey = null, $indexKey = null) {
    17                 if (!function_exists('_array_column')) {
    18                         include_spip('lib/array_column/_array_column');
    19                 }
    20                 return _array_column($input, $columnKey, $indexKey);
    21         }
    22 }
    23 
    24 
    25 if (!defined('_PREVISU_TEMPORAIRE_ACTIVE')) {
    26         define('_PREVISU_TEMPORAIRE_ACTIVE', true);
    27 }
    28 
    29 if (_request('var_mode')=='preview'
    30         and _PREVISU_TEMPORAIRE_ACTIVE
    31         and $cle = _request('var_relecture')
    32 ) {
    33         include_spip('spip_bonux_fonctions');
    34         if (previsu_verifier_cle_temporaire($cle)) {
    35                 include_spip('inc/autoriser');
    36                 autoriser_exception('previsualiser', '', 0);
    37                 define('_VAR_PREVIEW_EXCEPTION', true);
    38         }
    39 }
    40 
    41 function spip_bonux_affichage_final($flux) {
    42         if (_PREVISU_TEMPORAIRE_ACTIVE and defined('_VAR_PREVIEW') and _VAR_PREVIEW and !empty($GLOBALS['html'])) {
    43                 $p = stripos($flux, '</body>');
    44                 $url_relecture = parametre_url(self(), 'var_mode', 'preview', '&');
    45                 $js = '';
    46                 if (!defined('_VAR_PREVIEW_EXCEPTION')) {
    47                         include_spip('plugins/installer');
    48                         if (spip_version_compare($GLOBALS['spip_version_branche'], '3.2.0-beta3', '>=')) {
    49                                 include_spip('inc/securiser_action');
    50                                 $url_relecture = parametre_url($url_relecture, 'var_previewtoken', calculer_token_previsu(url_absolue($url_relecture)), '&');
    51                         } else {
    52                                 $url_relecture = parametre_url($url_relecture, 'var_relecture', previsu_cle_temporaire(), '&');
    53                         }
    54                         $label = 'Relecture temporaire';
    55                 } else {
    56                         $label = _T('previsualisation');
    57                         $js = "jQuery('.spip-previsu').html('Relecture temporaire');";
    58                 }
    59                 $js .= "jQuery('#spip-admin').append('<a class=\"spip-admin-boutons review_link\" href=\"$url_relecture\">$label</a>');";
    60                 $js = "jQuery(function(){ $js });";
    61                 $js = "<script>$js</script>";
    62                 $flux = substr_replace($flux, $js, $p, 0);
    63         }
    64         return $flux;
    65 }
    66 
    67 if (!function_exists('_T_ou_typo')) {
    68         /**
    69          * une fonction qui regarde si $texte est une chaine de langue
    70          * de la forme <:qqch:>
    71          * si oui applique _T()
    72          * si non applique typo() suivant le mode choisi
    73          *
    74          * @param mixed $valeur
    75          *     Une valeur à tester. Si c'est un tableau, la fonction s'appliquera récursivement dessus.
    76          * @param string $mode_typo
    77          *     Le mode d'application de la fonction typo(), avec trois valeurs possibles "toujours", "jamais" ou "multi".
    78          * @return mixed
    79          *     Retourne la valeur éventuellement modifiée.
    80          */
    81         function _T_ou_typo($valeur, $mode_typo = 'toujours') {
    82                 if (!in_array($mode_typo, array('toujours', 'multi', 'jamais'))) {
    83                         $mode_typo = 'toujours';
    84                 }
    85 
    86                 // Si la valeur est bien une chaine (et pas non plus un entier déguisé)
    87                 if (is_string($valeur) and !is_numeric($valeur)) {
    88                         // Si on est en >=3.2, on peut extraire les <:chaine:>
    89                         $version = explode('.',$GLOBALS['spip_version_branche']);
    90                         $extraction_chaines = (($version[0] > 3 or $version[1] >= 2) ? true : false);
    91                         // Si la chaine est du type <:truc:> on passe à _T()
    92                         if (strpos($valeur, '<:') !== false
    93                           and preg_match('/^\<:([^>]*?):\>$/', $valeur, $match)) {
    94                                 $valeur = _T($match[1]);
    95                         } else {
    96                                 // Sinon on la passe a typo() si c'est pertinent
    97                                 if (
    98                                         $mode_typo === 'toujours'
    99                                         or ($mode_typo === 'multi' and strpos($valeur, '<multi>') !== false)
    100                                         or ($extraction_chaines
    101                                           and $mode_typo === 'multi'
    102                                           and strpos($valeur, '<:') !== false
    103                                           and include_spip('inc/filtres')
    104                                           and preg_match(_EXTRAIRE_IDIOME, $valeur))
    105                                 ) {
    106                                         include_spip('inc/texte');
    107                                         $valeur = typo($valeur);
    108                                 }
    109                         }
    110                 }
    111                 // Si c'est un tableau, on réapplique la fonction récursivement
    112                 elseif (is_array($valeur)) {
    113                         foreach ($valeur as $cle => $valeur2) {
    114                                 $valeur[$cle] = _T_ou_typo($valeur2, $mode_typo);
    115                         }
    116                 }
    117 
    118                 return $valeur;
    119         }
    120 }
    121 /**
    122  * Insère toutes les valeurs du tableau $arr2 après (ou avant) $cle dans le tableau $arr1.
    123  * Si $cle n'est pas trouvé, les valeurs de $arr2 seront ajoutés à la fin de $arr1.
    124  *
    125  * La fonction garde autant que possible les associations entre les clés. Elle fonctionnera donc aussi bien
    126  * avec des tableaux à index numérique que des tableaux associatifs.
    127  * Attention tout de même, elle utilise array_merge() donc les valeurs de clés étant en conflits seront écrasées.
    128  *
    129  * @param array $arr1 Tableau dans lequel se fera l'insertion
    130  * @param unknown_type $cle Clé de $arr1 après (ou avant) laquelle se fera l'insertion
    131  * @param array $arr2 Tableau contenant les valeurs à insérer
    132  * @param bool $avant Indique si l'insertion se fait avant la clé (par défaut c'est après)
    133  * @return array Retourne le tableau avec l'insertion
    134  */
    135 if (!function_exists('spip_array_insert')) {
    136 function spip_array_insert($arr1, $cle, $arr2, $avant = false) {
    137         $index = array_search($cle, array_keys($arr1));
    138         if ($index === false) {
    139                 $index = count($arr1); // insert @ end of array if $key not found
    140         } else {
    141                 if (!$avant) {
    142                         $index++;
    143                 }
    144         }
    145         $fin = array_splice($arr1, $index);
    146         return array_merge($arr1, $arr2, $fin);
    147 }
    148 }
    149 
    150 /*
    151  * Une fonction extrêmement pratique, mais qui n'est disponible qu'à partir de PHP 5.3 !
    152  * cf. http://www.php.net/manual/fr/function.array-replace-recursive.php
    153  */
    154 if (!function_exists('array_replace_recursive')) {
    155         function array_replace_recursive($array, $array1) {
    156                 function recurse($array, $array1) {
    157                         foreach ($array1 as $key => $value) {
    158                                 // create new key in $array, if it is empty or not an array
    159                                 if (!isset($array[$key]) || (isset($array[$key]) && !is_array($array[$key]))) {
    160                                         $array[$key] = array();
    161                                 }
    162                                 // overwrite the value in the base array
    163                                 if (is_array($value)) {
    164                                         $value = recurse($array[$key], $value);
    165                                 }
    166                                 $array[$key] = $value;
    167                         }
    168                         return $array;
    169                 }
    170 
    171                 // handle the arguments, merge one by one
    172                 $args = func_get_args();
    173                 $array = $args[0];
    174                 if (!is_array($array)) {
    175                         return $array;
    176                 }
    177 
    178                 for ($i = 1; $i < count($args); $i++) {
    179                         if (is_array($args[$i])) {
    180                                 $array = recurse($array, $args[$i]);
    181                         }
    182                 }
    183                 return $array;
    184         }
    185 }
    186 
    187 if (!function_exists('text_truncate')) {
    188 /**
    189 * Truncates text.
    190 *
    191 * Cuts a string to the length of $length and replaces the last characters
    192 * with the ending if the text is longer than length.
    193 *
    194 * ### Options:
    195 *
    196 * - `ending` Will be used as Ending and appended to the trimmed string
    197 * - `exact` If false, $text will not be cut mid-word
    198 * - `html` If true, HTML tags would be handled correctly
    199 *
    200 * @param string  $text String to truncate.
    201 * @param integer $length Length of returned string, including ellipsis.
    202 * @param array $options An array of html attributes and options.
    203 * @return string Trimmed string.
    204 * @access public
    205 * @link http://book.cakephp.org/view/1469/Text#truncate-1625
    206 */
    207 function text_truncate($text, $length = 100, $options = array()) {
    208         $default = array(
    209                 'ending' => '...', 'exact' => true, 'html' => false
    210         );
    211         $options = array_merge($default, $options);
    212         extract($options);
    213 
    214         if ($html) {
    215                 if (mb_strlen(preg_replace('/<.*?>/', '', $text)) <= $length) {
    216                         return $text;
    217                 }
    218                 $totalLength = mb_strlen(strip_tags($ending));
    219                 $openTags = array();
    220                 $truncate = '';
    221 
    222                 preg_match_all('/(<\/?([\w+]+)[^>]*>)?([^<>]*)/', $text, $tags, PREG_SET_ORDER);
    223                 foreach ($tags as $tag) {
    224                         if (!preg_match('/img|br|input|hr|area|base|basefont|col|frame|isindex|link|meta|param/s', $tag[2])) {
    225                                 if (preg_match('/<[\w]+[^>]*>/s', $tag[0])) {
    226                                         array_unshift($openTags, $tag[2]);
    227                                 } else if (preg_match('/<\/([\w]+)[^>]*>/s', $tag[0], $closeTag)) {
    228                                         $pos = array_search($closeTag[1], $openTags);
    229                                         if ($pos !== false) {
    230                                                 array_splice($openTags, $pos, 1);
    231                                         }
    232                                 }
    233                         }
    234                         $truncate .= $tag[1];
    235 
    236                         $contentLength = mb_strlen(preg_replace('/&[0-9a-z]{2,8};|&#[0-9]{1,7};|&#x[0-9a-f]{1,6};/i', ' ', $tag[3]));
    237                         if ($contentLength + $totalLength > $length) {
    238                                 $left = $length - $totalLength;
    239                                 $entitiesLength = 0;
    240                                 if (preg_match_all('/&[0-9a-z]{2,8};|&#[0-9]{1,7};|&#x[0-9a-f]{1,6};/i', $tag[3], $entities, PREG_OFFSET_CAPTURE)) {
    241                                         foreach ($entities[0] as $entity) {
    242                                                 if ($entity[1] + 1 - $entitiesLength <= $left) {
    243                                                         $left--;
    244                                                         $entitiesLength += mb_strlen($entity[0]);
    245                                                 } else {
    246                                                         break;
    247                                                 }
    248                                         }
    249                                 }
    250                                 $truncate .= mb_substr($tag[3], 0, $left + $entitiesLength);
    251                                 break;
    252                         } else {
    253                                 $truncate .= $tag[3];
    254                                 $totalLength += $contentLength;
    255                         }
    256                         if ($totalLength >= $length) {
    257                                 break;
    258                         }
    259                 }
    260         } else {
    261                 if (mb_strlen($text) <= $length) {
    262                         return $text;
    263                 } else {
    264                         $truncate = mb_substr($text, 0, $length - mb_strlen($ending));
    265                 }
    266         }
    267         if (!$exact) {
    268                 $spacepos = mb_strrpos($truncate, ' ');
    269                 if (isset($spacepos)) {
    270                         if ($html) {
    271                                 $bits = mb_substr($truncate, $spacepos);
    272                                 preg_match_all('/<\/([a-z]+)>/', $bits, $droppedTags, PREG_SET_ORDER);
    273                                 if (!empty($droppedTags)) {
    274                                         foreach ($droppedTags as $closingTag) {
    275                                                 if (!in_array($closingTag[1], $openTags)) {
    276                                                         array_unshift($openTags, $closingTag[1]);
    277                                                 }
    278                                         }
    279                                 }
    280                         }
    281                         $truncate = mb_substr($truncate, 0, $spacepos);
    282                 }
    283         }
    284         $truncate .= $ending;
    285 
    286         if ($html) {
    287                 foreach ($openTags as $tag) {
    288                         $truncate .= '</'.$tag.'>';
    289                 }
    290         }
    291 
    292         return $truncate;
    293 }
    294 }
     1  <?php
     2  /**
     3   * Plugin Spip-Bonux
     4   * Le plugin qui lave plus SPIP que SPIP
     5   * (c) 2008 Mathieu Marcillaud, Cedric Morin, Tetue
     6   * Licence GPL
     7   *
     8   */
     9
     10  if (!defined('_ECRIRE_INC_VERSION')) {
     11      return;
     12  }
     13
     14  // Proposer array_column
     15  if (!function_exists('array_column')) {
     16      function array_column($input = null, $columnKey = null, $indexKey = null) {
     17          if (!function_exists('_array_column')) {
     18              include_spip('lib/array_column/_array_column');
     19          }
     20          return _array_column($input, $columnKey, $indexKey);
     21      }
     22  }
     23
     24
     25  if (!defined('_PREVISU_TEMPORAIRE_ACTIVE')) {
     26      define('_PREVISU_TEMPORAIRE_ACTIVE', true);
     27  }
     28
     29  if (_request('var_mode')=='preview'
     30      and _PREVISU_TEMPORAIRE_ACTIVE
     31      and $cle = _request('var_relecture')
     32  ) {
     33      include_spip('spip_bonux_fonctions');
     34      if (previsu_verifier_cle_temporaire($cle)) {
     35          include_spip('inc/autoriser');
     36          autoriser_exception('previsualiser', '', 0);
     37          define('_VAR_PREVIEW_EXCEPTION', true);
     38      }
     39  }
     40
     41  function spip_bonux_affichage_final($flux) {
     42      if (_PREVISU_TEMPORAIRE_ACTIVE and defined('_VAR_PREVIEW') and _VAR_PREVIEW and !empty($GLOBALS['html'])) {
     43          $p = stripos($flux, '</body>');
     44          $url_relecture = parametre_url(self(), 'var_mode', 'preview', '&');
     45          $js = '';
     46          if (!defined('_VAR_PREVIEW_EXCEPTION')) {
     47              include_spip('plugins/installer');
     48              if (spip_version_compare($GLOBALS['spip_version_branche'], '3.2.0-beta3', '>=')) {
     49                  include_spip('inc/securiser_action');
     50                  $url_relecture = parametre_url($url_relecture, 'var_previewtoken', calculer_token_previsu(url_absolue($url_relecture)), '&');
     51              } else {
     52                  $url_relecture = parametre_url($url_relecture, 'var_relecture', previsu_cle_temporaire(), '&');
     53              }
     54              $label = 'Relecture temporaire';
     55          } else {
     56              $label = _T('previsualisation');
     57              $js = "jQuery('.spip-previsu').html('Relecture temporaire');";
     58          }
     59          $js .= "jQuery('#spip-admin').append('<a class=\"spip-admin-boutons review_link\" href=\"$url_relecture\">$label</a>');";
     60          $js = "jQuery(function(){ $js });";
     61          $js = "<script>$js</script>";
     62          $flux = substr_replace($flux, $js, $p, 0);
     63      }
     64      return $flux;
     65  }
     66
     67  if (!function_exists('_T_ou_typo')) {
     68      /**
     69       * une fonction qui regarde si $texte est une chaine de langue
     70       * de la forme <:qqch:>
     71       * si oui applique _T()
     72       * si non applique typo() suivant le mode choisi
     73       *
     74       * @param mixed $valeur
     75       *     Une valeur à tester. Si c'est un tableau, la fonction s'appliquera récursivement dessus.
     76       * @param string $mode_typo
     77       *     Le mode d'application de la fonction typo(), avec trois valeurs possibles "toujours", "jamais" ou "multi".
     78       * @return mixed
     79       *     Retourne la valeur éventuellement modifiée.
     80       */
     81      function _T_ou_typo($valeur, $mode_typo = 'toujours') {
     82          if (!in_array($mode_typo, array('toujours', 'multi', 'jamais'))) {
     83              $mode_typo = 'toujours';
     84          }
     85
     86          // Si la valeur est bien une chaine (et pas non plus un entier déguisé)
     87          if (is_string($valeur) and !is_numeric($valeur)) {
     88              // Si on est en >=3.2, on peut extraire les <:chaine:>
     89              $version = explode('.',$GLOBALS['spip_version_branche']);
     90              $extraction_chaines = (($version[0] > 3 or $version[1] >= 2) ? true : false);
     91              // Si la chaine est du type <:truc:> on passe à _T()
     92              if (strpos($valeur, '<:') !== false
     93                and preg_match('/^\<:([^>]*?):\>$/', $valeur, $match)) {
     94                  $valeur = _T($match[1]);
     95              } else {
     96                  // Sinon on la passe a typo() si c'est pertinent
     97                  if (
     98                      $mode_typo === 'toujours'
     99                      or ($mode_typo === 'multi' and strpos($valeur, '<multi>') !== false)
     100                      or ($extraction_chaines
     101                        and $mode_typo === 'multi'
     102                        and strpos($valeur, '<:') !== false
     103                        and include_spip('inc/filtres')
     104                        and preg_match(_EXTRAIRE_IDIOME, $valeur))
     105                  ) {
     106                      include_spip('inc/texte');
     107                      $valeur = typo($valeur);
     108                  }
     109              }
     110          }
     111          // Si c'est un tableau, on réapplique la fonction récursivement
     112          elseif (is_array($valeur)) {
     113              foreach ($valeur as $cle => $valeur2) {
     114                  $valeur[$cle] = _T_ou_typo($valeur2, $mode_typo);
     115              }
     116          }
     117
     118          return $valeur;
     119      }
     120  }
     121  /**
     122   * Insère toutes les valeurs du tableau $arr2 après (ou avant) $cle dans le tableau $arr1.
     123   * Si $cle n'est pas trouvé, les valeurs de $arr2 seront ajoutés à la fin de $arr1.
     124   *
     125   * La fonction garde autant que possible les associations entre les clés. Elle fonctionnera donc aussi bien
     126   * avec des tableaux à index numérique que des tableaux associatifs.
     127   * Attention tout de même, elle utilise array_merge() donc les valeurs de clés étant en conflits seront écrasées.
     128   *
     129   * @param array $arr1 Tableau dans lequel se fera l'insertion
     130   * @param unknown_type $cle Clé de $arr1 après (ou avant) laquelle se fera l'insertion
     131   * @param array $arr2 Tableau contenant les valeurs à insérer
     132   * @param bool $avant Indique si l'insertion se fait avant la clé (par défaut c'est après)
     133   * @return array Retourne le tableau avec l'insertion
     134   */
     135  if (!function_exists('spip_array_insert')) {
     136  function spip_array_insert($arr1, $cle, $arr2, $avant = false) {
     137      $index = array_search($cle, array_keys($arr1));
     138      if ($index === false) {
     139          $index = count($arr1); // insert @ end of array if $key not found
     140      } else {
     141          if (!$avant) {
     142              $index++;
     143          }
     144      }
     145      $fin = array_splice($arr1, $index);
     146      return array_merge($arr1, $arr2, $fin);
     147  }
     148  }
     149
     150  /*
     151   * Une fonction extrêmement pratique, mais qui n'est disponible qu'à partir de PHP 5.3 !
     152   * cf. http://www.php.net/manual/fr/function.array-replace-recursive.php
     153   */
     154  if (!function_exists('array_replace_recursive')) {
     155      function array_replace_recursive($array, $array1) {
     156          function recurse($array, $array1) {
     157              foreach ($array1 as $key => $value) {
     158                  // create new key in $array, if it is empty or not an array
     159                  if (!isset($array[$key]) || (isset($array[$key]) && !is_array($array[$key]))) {
     160                      $array[$key] = array();
     161                  }
     162                  // overwrite the value in the base array
     163                  if (is_array($value)) {
     164                      $value = recurse($array[$key], $value);
     165                  }
     166                  $array[$key] = $value;
     167              }
     168              return $array;
     169          }
     170
     171          // handle the arguments, merge one by one
     172          $args = func_get_args();
     173          $array = $args[0];
     174          if (!is_array($array)) {
     175              return $array;
     176          }
     177
     178          for ($i = 1; $i < count($args); $i++) {
     179              if (is_array($args[$i])) {
     180                  $array = recurse($array, $args[$i]);
     181              }
     182          }
     183          return $array;
     184      }
     185  }
     186
     187  if (!function_exists('text_truncate')) {
     188  /**
     189  * Truncates text.
     190  *
     191  * Cuts a string to the length of $length and replaces the last characters
     192  * with the ending if the text is longer than length.
     193  *
     194  * ### Options:
     195  *
     196  * - `ending` Will be used as Ending and appended to the trimmed string
     197  * - `exact` If false, $text will not be cut mid-word
     198  * - `html` If true, HTML tags would be handled correctly
     199  *
     200  * @param string  $text String to truncate.
     201  * @param integer $length Length of returned string, including ellipsis.
     202  * @param array $options An array of html attributes and options.
     203  * @return string Trimmed string.
     204  * @access public
     205  * @link http://book.cakephp.org/view/1469/Text#truncate-1625
     206  */
     207  function text_truncate($text, $length = 100, $options = array()) {
     208      $default = array(
     209          'ending' => '...', 'exact' => true, 'html' => false
     210      );
     211      $options = array_merge($default, $options);
     212      extract($options);
     213
     214      $html = $options['html'];
     215      $exact = $options['exact'];
     216      $ending = $options['ending'];
     217
     218      if ($html) {
     219          if (mb_strlen(preg_replace('/<.*?>/', '', $text)) <= $length) {
     220              return $text;
     221          }
     222          $totalLength = mb_strlen(strip_tags($ending));
     223          $openTags = array();
     224          $truncate = '';
     225
     226          preg_match_all('/(<\/?([\w+]+)[^>]*>)?([^<>]*)/', $text, $tags, PREG_SET_ORDER);
     227          foreach ($tags as $tag) {
     228              if (!preg_match('/img|br|input|hr|area|base|basefont|col|frame|isindex|link|meta|param/s', $tag[2])) {
     229                  if (preg_match('/<[\w]+[^>]*>/s', $tag[0])) {
     230                      array_unshift($openTags, $tag[2]);
     231                  } else if (preg_match('/<\/([\w]+)[^>]*>/s', $tag[0], $closeTag)) {
     232                      $pos = array_search($closeTag[1], $openTags);
     233                      if ($pos !== false) {
     234                          array_splice($openTags, $pos, 1);
     235                      }
     236                  }
     237              }
     238              $truncate .= $tag[1];
     239
     240              $contentLength = mb_strlen(preg_replace('/&[0-9a-z]{2,8};|&#[0-9]{1,7};|&#x[0-9a-f]{1,6};/i', ' ', $tag[3]));
     241              if ($contentLength + $totalLength > $length) {
     242                  $left = $length - $totalLength;
     243                  $entitiesLength = 0;
     244                  if (preg_match_all('/&[0-9a-z]{2,8};|&#[0-9]{1,7};|&#x[0-9a-f]{1,6};/i', $tag[3], $entities, PREG_OFFSET_CAPTURE)) {
     245                      foreach ($entities[0] as $entity) {
     246                          if ($entity[1] + 1 - $entitiesLength <= $left) {
     247                              $left--;
     248                              $entitiesLength += mb_strlen($entity[0]);
     249                          } else {
     250                              break;
     251                          }
     252                      }
     253                  }
     254                  $truncate .= mb_substr($tag[3], 0, $left + $entitiesLength);
     255                  break;
     256              } else {
     257                  $truncate .= $tag[3];
     258                  $totalLength += $contentLength;
     259              }
     260              if ($totalLength >= $length) {
     261                  break;
     262              }
     263          }
     264      } else {
     265          if (mb_strlen($text) <= $length) {
     266              return $text;
     267          } else {
     268              $truncate = mb_substr($text, 0, $length - mb_strlen($ending));
     269          }
     270      }
     271      if (!$exact) {
     272          $spacepos = mb_strrpos($truncate, ' ');
     273          if (isset($spacepos)) {
     274              if ($html) {
     275                  $bits = mb_substr($truncate, $spacepos);
     276                  preg_match_all('/<\/([a-z]+)>/', $bits, $droppedTags, PREG_SET_ORDER);
     277                  if (!empty($droppedTags)) {
     278                      foreach ($droppedTags as $closingTag) {
     279                          if (!in_array($closingTag[1], $openTags)) {
     280                              array_unshift($openTags, $closingTag[1]);
     281                          }
     282                      }
     283                  }
     284              }
     285              $truncate = mb_substr($truncate, 0, $spacepos);
     286          }
     287      }
     288      $truncate .= $ending;
     289
     290      if ($html) {
     291          foreach ($openTags as $tag) {
     292              $truncate .= '</'.$tag.'>';
     293          }
     294      }
     295
     296      return $truncate;
     297  }
     298  }
Note: See TracChangeset for help on using the changeset viewer.