daily pastebin goal
58%
SHARE
TWEET

Untitled

a guest Aug 10th, 2018 50 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. Wordwrap / Cut Text in HTML string
  2. public function textWrap($string, $width)
  3. {
  4.     $dom = new DOMDocument();
  5.     $dom->loadHTML($string);
  6.     foreach ($dom->getElementsByTagName('*') as $elem)
  7.     {
  8.         foreach ($elem->childNodes as $node)
  9.         {
  10.             if ($node->nodeType === XML_TEXT_NODE)
  11.             {
  12.                 $text = trim($node->nodeValue);
  13.                 $length = mb_strlen($text);
  14.                 $width -= $length;
  15.                 if($width <= 0)
  16.                 {
  17.                     // Here, I would like to delete all next nodes
  18.                     // and cut the current nodeValue and finally return the string
  19.                 }
  20.             }
  21.         }
  22.     }
  23. }
  24.    
  25. <p>
  26.         <span class="Underline"><span class="Bold">Test to be cut</span></span>
  27.    </p><p>Some text</p>
  28.    
  29. <p>
  30.     <span class="Underline"><span class="Bold">Test to</span></span>
  31. </p>
  32.    
  33. $htmlFragment = <<<HTML
  34. <p>
  35.         <span class="Underline"><span class="Bold">Test to be cut</span></span>
  36.    </p><p>Some text </p>
  37. HTML;
  38.  
  39. $dom = new DOMDocument();
  40. $dom->loadHTML($htmlFragment);
  41. $parent = $dom->getElementsByTagName('body')->item(0);
  42. if (!$parent)
  43. {
  44.     throw new Exception('Parent element not found.');
  45. }
  46.    
  47. $range = new TextRange($parent);
  48.  
  49. // find position where to cut the HTML textual represenation
  50. // by looking for a word or the at least matching whitespace
  51. // with a regular expression.
  52. $width = 17;
  53. $pattern = sprintf('~^.{0,%d}(?<=S)(?=s)|^.{0,%1$d}(?=s)~su', $width);
  54. $r = preg_match($pattern, $range, $matches);
  55. if (FALSE === $r)
  56. {
  57.     throw new Exception('Wordcut regex failed.');
  58. }
  59. if (!$r)
  60. {
  61.     throw new Exception(sprintf('Text "%s" is not cut-able (should not happen).', $range));
  62. }
  63.    
  64. // chop-off the textnodes to make a cut in DOM possible
  65. $range->split($matches[0]);
  66. $nodes = $range->getNodes();
  67. $cutPosition = end($nodes);
  68.    
  69. // obtain list of elements to remove with xpath
  70. if (FALSE === $cutPosition)
  71. {
  72.     // if there is no node, delete all parent children
  73.     $cutPosition = $parent;
  74.     $xpath = 'child::node()';
  75. }
  76. else
  77. {
  78.     $xpath = 'following::node()';
  79. }
  80.    
  81. // execute xpath
  82. $xp = new DOMXPath($dom);
  83. $remove = $xp->query($xpath, $cutPosition);
  84. if (!$remove)
  85. {
  86.     throw new Exception('XPath query failed to obtain elements to remove');
  87. }
  88.  
  89. // remove nodes
  90. foreach($remove as $node)
  91. {
  92.     $node->parentNode->removeChild($node);
  93. }
  94.  
  95. // inner HTML (PHP >= 5.3.6)
  96. foreach($parent->childNodes as $node)
  97. {
  98.     echo $dom->saveHTML($node);
  99. }
  100.    
  101. <p>
  102.         <span class="Underline"><span class="Bold">Test to</span></span></p>
  103.    
  104. ...
  105. $range = new TextRange($parent);
  106. $trimmer = new TextRangeTrimmer($range);
  107. $trimmer->trim();
  108. ...
  109.    
  110. class TextRangeTrimmer
  111. {
  112.     /**
  113.      * @var TextRange
  114.      */
  115.     private $range;
  116.  
  117.     /**
  118.      * @var array
  119.      */
  120.     private $charlist;
  121.  
  122.     public function __construct(TextRange $range, Array $charlist = NULL)
  123.     {
  124.         $this->range = $range;
  125.         $this->setCharlist($charlist);      
  126.     }
  127.     /**
  128.      * @param array $charlist list of UTF-8 encoded characters
  129.      * @throws InvalidArgumentException
  130.      */
  131.     public function setCharlist(Array $charlist = NULL)
  132.     {
  133.          if (NULL === $charlist)
  134.             $charlist = str_split(" tnrx0B")
  135.         ;
  136.  
  137.         $list = array();
  138.  
  139.         foreach($charlist as $char)
  140.         {
  141.             if (!is_string($char))
  142.             {
  143.                 throw new InvalidArgumentException('Not an Array of strings.');
  144.             }
  145.             if (strlen($char))
  146.             {
  147.                 $list[] = $char;
  148.             }
  149.         }
  150.  
  151.         $this->charlist = array_flip($list);
  152.     }
  153.     /**
  154.      * @return array characters
  155.      */
  156.     public function getCharlist()
  157.     {
  158.         return array_keys($this->charlist);
  159.     }
  160.     public function trim()
  161.     {
  162.         if (!$this->charlist) return;
  163.         $this->ltrim();
  164.         $this->rtrim();
  165.     }
  166.     /**
  167.      * number of consecutive charcters of $charlist from $start to $direction
  168.      *
  169.      * @param array $charlist
  170.      * @param int $start offset
  171.      * @param int $direction 1: forward, -1: backward
  172.      * @throws InvalidArgumentException
  173.      */
  174.     private function lengthOfCharacterSequence(Array $charlist, $start, $direction = 1)
  175.     {
  176.         $start = (int) $start;              
  177.         $direction = max(-1, min(1, $direction));
  178.         if (!$direction) throw new InvalidArgumentException('Direction must be 1 or -1.');
  179.  
  180.         $count = 0;
  181.         for(;$char = $this->range->getCharacter($start), $char !== ''; $start += $direction, $count++)
  182.             if (!isset($charlist[$char])) break;
  183.  
  184.         return $count;
  185.     }
  186.     public function ltrim()
  187.     {
  188.         $count = $this->lengthOfCharacterSequence($this->charlist, 0);
  189.  
  190.         if ($count)
  191.         {
  192.             $remainder = $this->range->split($count);
  193.             foreach($this->range->getNodes() as $textNode)
  194.             {
  195.                 $textNode->parentNode->removeChild($textNode);
  196.             }
  197.             $this->range->setNodes($remainder->getNodes());
  198.         }
  199.  
  200.     }
  201.     public function rtrim()
  202.     {
  203.         $count = $this->lengthOfCharacterSequence($this->charlist, -1, -1);
  204.  
  205.         if ($count)
  206.         {
  207.             $chop = $this->range->split(-$count);
  208.             foreach($chop->getNodes() as $textNode)
  209.             {
  210.                 $textNode->parentNode->removeChild($textNode);
  211.             }
  212.         }
  213.     }
  214. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top