tag = $tag;
parent::__construct();
}
/**
* Gets the inner html of this node.
*
* @return string
* @throws UnknownChildTypeException
*/
public function innerHtml(): string
{
if ( ! $this->hasChildren()) {
// no children
return '';
}
if ( ! is_null($this->innerHtml)) {
// we already know the result.
return $this->innerHtml;
}
$child = $this->firstChild();
$string = '';
// continue to loop until we are out of children
while ( ! is_null($child)) {
if ($child instanceof TextNode) {
$string .= $child->text();
} elseif ($child instanceof HtmlNode) {
$string .= $child->outerHtml();
} else {
throw new UnknownChildTypeException('Unknown child type "'.get_class($child).'" found in node');
}
try {
$child = $this->nextChild($child->id());
} catch (ChildNotFoundException $e) {
// no more children
$child = null;
}
}
// remember the results
$this->innerHtml = $string;
return $string;
}
/**
* Gets the html of this node, including it's own
* tag.
*
* @return string
*/
public function outerHtml(): string
{
// special handling for root
if ($this->tag->name() == 'root') {
return $this->innerHtml();
}
if ( ! is_null($this->outerHtml)) {
// we already know the results.
return $this->outerHtml;
}
$return = $this->tag->makeOpeningTag();
if ($this->tag->isSelfClosing()) {
// ignore any children... there should not be any though
return $return;
}
// get the inner html
$return .= $this->innerHtml();
// add closing tag
$return .= $this->tag->makeClosingTag();
// remember the results
$this->outerHtml = $return;
return $return;
}
/**
* Gets the text of this node (if there is any text). Or get all the text
* in this node, including children.
*
* @param bool $lookInChildren
* @return string
*/
public function text(bool $lookInChildren = false): string
{
if ($lookInChildren) {
if ( ! is_null($this->textWithChildren)) {
// we already know the results.
return $this->textWithChildren;
}
} elseif ( ! is_null($this->text)) {
// we already know the results.
return $this->text;
}
// find out if this node has any text children
$text = '';
foreach ($this->children as $child) {
/** @var AbstractNode $node */
$node = $child['node'];
if ($node instanceof TextNode) {
$text .= $child['node']->text;
} elseif ($lookInChildren &&
$node instanceof HtmlNode
) {
$text .= $node->text($lookInChildren);
}
}
// remember our result
if ($lookInChildren) {
$this->textWithChildren = $text;
} else {
$this->text = $text;
}
return $text;
}
/**
* Call this when something in the node tree has changed. Like a child has been added
* or a parent has been changed.
*/
protected function clear(): void
{
$this->innerHtml = null;
$this->outerHtml = null;
$this->text = null;
$this->textWithChildren = null;
if (is_null($this->parent) === false) {
$this->parent->clear();
}
}
/**
* Returns all children of this html node.
*
* @return array
*/
protected function getIteratorArray(): array
{
return $this->getChildren();
}
}