Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Wordwrap / Cut Text in HTML string
- public function textWrap($string, $width)
- {
- $dom = new DOMDocument();
- $dom->loadHTML($string);
- foreach ($dom->getElementsByTagName('*') as $elem)
- {
- foreach ($elem->childNodes as $node)
- {
- if ($node->nodeType === XML_TEXT_NODE)
- {
- $text = trim($node->nodeValue);
- $length = mb_strlen($text);
- $width -= $length;
- if($width <= 0)
- {
- // Here, I would like to delete all next nodes
- // and cut the current nodeValue and finally return the string
- }
- }
- }
- }
- }
- <p>
- <span class="Underline"><span class="Bold">Test to be cut</span></span>
- </p><p>Some text</p>
- <p>
- <span class="Underline"><span class="Bold">Test to</span></span>
- </p>
- $htmlFragment = <<<HTML
- <p>
- <span class="Underline"><span class="Bold">Test to be cut</span></span>
- </p><p>Some text </p>
- HTML;
- $dom = new DOMDocument();
- $dom->loadHTML($htmlFragment);
- $parent = $dom->getElementsByTagName('body')->item(0);
- if (!$parent)
- {
- throw new Exception('Parent element not found.');
- }
- $range = new TextRange($parent);
- // find position where to cut the HTML textual represenation
- // by looking for a word or the at least matching whitespace
- // with a regular expression.
- $width = 17;
- $pattern = sprintf('~^.{0,%d}(?<=S)(?=s)|^.{0,%1$d}(?=s)~su', $width);
- $r = preg_match($pattern, $range, $matches);
- if (FALSE === $r)
- {
- throw new Exception('Wordcut regex failed.');
- }
- if (!$r)
- {
- throw new Exception(sprintf('Text "%s" is not cut-able (should not happen).', $range));
- }
- // chop-off the textnodes to make a cut in DOM possible
- $range->split($matches[0]);
- $nodes = $range->getNodes();
- $cutPosition = end($nodes);
- // obtain list of elements to remove with xpath
- if (FALSE === $cutPosition)
- {
- // if there is no node, delete all parent children
- $cutPosition = $parent;
- $xpath = 'child::node()';
- }
- else
- {
- $xpath = 'following::node()';
- }
- // execute xpath
- $xp = new DOMXPath($dom);
- $remove = $xp->query($xpath, $cutPosition);
- if (!$remove)
- {
- throw new Exception('XPath query failed to obtain elements to remove');
- }
- // remove nodes
- foreach($remove as $node)
- {
- $node->parentNode->removeChild($node);
- }
- // inner HTML (PHP >= 5.3.6)
- foreach($parent->childNodes as $node)
- {
- echo $dom->saveHTML($node);
- }
- <p>
- <span class="Underline"><span class="Bold">Test to</span></span></p>
- ...
- $range = new TextRange($parent);
- $trimmer = new TextRangeTrimmer($range);
- $trimmer->trim();
- ...
- class TextRangeTrimmer
- {
- /**
- * @var TextRange
- */
- private $range;
- /**
- * @var array
- */
- private $charlist;
- public function __construct(TextRange $range, Array $charlist = NULL)
- {
- $this->range = $range;
- $this->setCharlist($charlist);
- }
- /**
- * @param array $charlist list of UTF-8 encoded characters
- * @throws InvalidArgumentException
- */
- public function setCharlist(Array $charlist = NULL)
- {
- if (NULL === $charlist)
- $charlist = str_split(" tnr x0B")
- ;
- $list = array();
- foreach($charlist as $char)
- {
- if (!is_string($char))
- {
- throw new InvalidArgumentException('Not an Array of strings.');
- }
- if (strlen($char))
- {
- $list[] = $char;
- }
- }
- $this->charlist = array_flip($list);
- }
- /**
- * @return array characters
- */
- public function getCharlist()
- {
- return array_keys($this->charlist);
- }
- public function trim()
- {
- if (!$this->charlist) return;
- $this->ltrim();
- $this->rtrim();
- }
- /**
- * number of consecutive charcters of $charlist from $start to $direction
- *
- * @param array $charlist
- * @param int $start offset
- * @param int $direction 1: forward, -1: backward
- * @throws InvalidArgumentException
- */
- private function lengthOfCharacterSequence(Array $charlist, $start, $direction = 1)
- {
- $start = (int) $start;
- $direction = max(-1, min(1, $direction));
- if (!$direction) throw new InvalidArgumentException('Direction must be 1 or -1.');
- $count = 0;
- for(;$char = $this->range->getCharacter($start), $char !== ''; $start += $direction, $count++)
- if (!isset($charlist[$char])) break;
- return $count;
- }
- public function ltrim()
- {
- $count = $this->lengthOfCharacterSequence($this->charlist, 0);
- if ($count)
- {
- $remainder = $this->range->split($count);
- foreach($this->range->getNodes() as $textNode)
- {
- $textNode->parentNode->removeChild($textNode);
- }
- $this->range->setNodes($remainder->getNodes());
- }
- }
- public function rtrim()
- {
- $count = $this->lengthOfCharacterSequence($this->charlist, -1, -1);
- if ($count)
- {
- $chop = $this->range->split(-$count);
- foreach($chop->getNodes() as $textNode)
- {
- $textNode->parentNode->removeChild($textNode);
- }
- }
- }
- }
Add Comment
Please, Sign In to add comment