Extract information from the <link> elements.

@param DOMDocument $html
511740
private function extractLinks(DOMDocument $html)
    {
        foreach ($html->getElementsByTagName('link') as $link) {
            if ($link->hasAttribute('rel') && $link->hasAttribute('href')) {
                $rel = trim(strtolower($link->getAttribute('rel')));
                $href = $link->getAttribute('href');

                if (empty($href)) {
                    continue;
                }

                switch ($rel) {
                    case 'favicon':
                    case 'favico':
                    case 'icon':
                    case 'shortcut icon':
                    case 'apple-touch-icon-precomposed':
                    case 'apple-touch-icon':
                        $this->bag->add('icons', $href);
                        break;

                    case 'image_src':
                        $this->bag->add('images', $href);
                        break;

                    case 'alternate':
                        switch ($link->getAttribute('type')) {
                            case 'application/atom+xml':
                            case 'application/json':
                            case 'application/rdf+xml':
                            case 'application/rss+xml':
                            case 'application/xml':
                            case 'text/xml':
                                $this->bag->add('feeds', $href);
                                break;
                        }
                        break;

                    default:
                        $this->bag->set($rel, $href);
                }
            }
        }
    }
170192
protected function transformRemoteLinksToLinks(DOMDocument $xml)
    {
        $xpath = new DOMXPath($xml);
        $xpath->registerNamespace('docbook', 'http://docbook.org/ns/docbook');

        foreach (array('ezembedinline', 'ezembed', 'link', 'ezlink') as $tagName) {
            $xpathExpression = "//docbook:{$tagName}[starts-with( @xlink:href, 'ezcontent://' ) or starts-with( @xlink:href, 'ezlocation://' )]";
            /** @var \DOMElement $element */
            foreach ($xpath->query($xpathExpression) as $element) {
                preg_match('~^(.+)://([^#]*)?(#.*|\\s*)?$~', $element->getAttribute('xlink:href'), $matches);
                list(, $scheme, $remoteId, $fragment) = $matches;

                if ($scheme === 'ezcontent') {
                    $object = eZContentObject::fetchByRemoteID($remoteId);
                    if (!$object instanceof eZContentObject) {
                        $element->parentNode->removeChild($element);
                        continue;
                    }

                    $href = "{$scheme}://{$object->attribute('id')}{$fragment}";
                } else {
                    $node = eZContentObjectTreeNode::fetchByRemoteID($remoteId);
                    if (!$node instanceof eZContentObjectTreeNode) {
                        $element->parentNode->removeChild($element);
                        continue;
                    }

                    $href = "{$scheme}://{$node->attribute('node_id')}{$fragment}";
                }

                $element->setAttribute('xlink:href', $href);
            }
        }
    }
439970
protected static function getEndPointFromDom(DOMDocument $html)
    {
        foreach (['link', 'meta'] as $tagName) {
            foreach ($html->getElementsByTagName($tagName) as $link) {
                $rel = trim(strtolower($link->getAttribute('rel')));
                $href = $link->getAttribute('href');

                if (empty($href)) {
                    continue;
                }

                if ($rel === 'alternate') {
                    switch (strtolower($link->getAttribute('type'))) {
                        case 'application/json+oembed':
                        case 'application/xml+oembed':
                        case 'text/json+oembed':
                        case 'text/xml+oembed':
                            return $href;
                    }
                }
            }
        }
    }
816958
protected function parseHtml($html)
    {
        $data = [
            'image' => '',
            'title' => '',
            'description' => ''
        ];

        libxml_use_internal_errors(true);
        $doc = new \DOMDocument();
        $doc->loadHTML($html);

        /** @var \DOMElement $meta */
        foreach ($doc->getElementsByTagName('meta') as $meta) {
            if ($meta->getAttribute('property') === 'og:image') {
                $data['image'] = $meta->getAttribute('content');
            }

            if ($meta->getAttribute('property') === 'og:title') {
                $data['title'] = $meta->getAttribute('content');
            }

            if ($meta->getAttribute('property') === 'og:description') {
                $data['description'] = $meta->getAttribute('content');
            }
        }

        return $data;
    }
496516
public function info($html)
    {
        $tags = array('{total}', '{start}', '{end}', '{page}', '{pages}');
        $code = array($this->total, $this->start() + 1, $this->end(), $this->get, $this->pages());

        return str_replace($tags, $code, $html);
    }
244160
private function parseAttributes(string $html): string
    {
        $remainingHtml = \mb_substr($html, mb_strlen($this->name) + 1);
        while (\mb_strpos($remainingHtml, '>') !== false && preg_match("/^\s*[\/]?>/", $remainingHtml) === 0) {
            $remainingHtml = $this->parseAttribute($remainingHtml);
        }

        return $remainingHtml;
    }
846378
protected static function getMainElement(\DOMDocument $html)
    {
        // <main>
        $content = $html->getElementsByTagName('main');

        if ($content->length !== 0) {
            return $content->item(0);
        }

        // Popular ids: #main, #content, #page
        $content = $html->getElementById('main') ?: $html->getElementById('content') ?: $html->getElementById('page');

        if ($content) {
            return $content;
        }

        // Wordpress ids: #post-*
        foreach ($html->getElementsByTagName('article') as $article) {
            if ($article->hasAttribute('id') && (strpos($article->getAttribute('id'), 'post-') === 0)) {
                return $article;
            }
        }

        // Returns <body> or <html>
        return $html->getElementsByTagName('body')->item(0) ?: $html->getElementsByTagName('html')->item(0);
    }
808533
private function extractText(DOMNode $node)
    {
        $text = '';

        if ($node->childNodes) {
            foreach ($node->childNodes as $child) {
                $text .= $this->extractText($child);
            }
        } else {
            $text .= $node->nodeValue . ' ';
        }

        return $text;
    }
439336
protected final function loadHTML(DOMDocument $dom, string $html)
   {
       try {
           $dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
       } catch (Throwable $e) {
           throw new RuntimeException("Can't load HTML: " . $e->getMessage());
       }
   }
778482
public function getHtml($xpath) {
    $elements = $this->findElement($xpath, 1);
    //allText works only with ONE element so it will be the first one
    return $this->browser->allHtml($elements["page_id"], $elements["ids"][0], "inner");
  }
8755
public function scrapeAndKneadImages( \DOMDocument $dom ) {

		$images = $dom->getElementsByTagName( 'img' );
		$attachments = [];

		foreach ( $images as $image ) {
			/** @var \DOMElement $image */
			// Fetch image, change src
			$src_old = $image->getAttribute( 'src' );
			$attachment_id = $this->fetchAndSaveUniqueImage( $src_old );
			if ( $attachment_id === -1 ) {
				// Do nothing because image is not hosted on the source Pb network
			} elseif ( $attachment_id ) {
				$image->setAttribute( 'src', $this->replaceImage( $attachment_id, $src_old, $image ) );
				$attachments[] = $attachment_id;
			} else {
				// Tag broken image
				$image->setAttribute( 'src', "{$src_old}#fixme" );
			}
		}

		return [
			'dom' => $dom,
			'attachments' => $attachments,
		];
	}
54900
protected function createDomDocument($html): \DOMDocument
    {
        $document = new \DOMDocument('1.0');
        $previousValue = libxml_use_internal_errors(true);
        libxml_clear_errors();
        $document->loadHTML($html);
        /** @var \LibXMLError[] $errors */
        $errors = libxml_get_errors();
        libxml_clear_errors();
        libxml_use_internal_errors($previousValue);

        foreach ($errors as $error) {
            if (LIBXML_ERR_ERROR === $error->level || LIBXML_ERR_FATAL === $error->level) {
                throw new SourceException(
                    sprintf('%s at %d:%d', trim($error->message), $error->line, $error->column),
                    $error->code
                );
            }
        }

        return $document;
    }
952752
public function extractFiles($html, $docRoot = null)
    {
        if (null === $docRoot) {
            $docRoot = $this->getDocRoot();
        }

        preg_match_all('/(href|src) *= *["\']([^"^\'^\?]+)/i', $html, $matches, PREG_SET_ORDER);

        foreach ($matches as $match) {
            if (strtolower($match[1]) == 'src') {
                $this->addJsFile($match[2], $docRoot);
            } else {
                $this->addCssFile($match[2], $docRoot);
            }
        }

        return $this;
    }
740876
private function extractLinks(ElementStructure $elementStructure)
    {
        $links = [];

        foreach ($elementStructure->getLanguages() as $language) {
            foreach ($elementStructure->getValues($language) as $elementStructureValue) {
                $field = $this->fieldRegistry->getField($elementStructureValue->getType());

                $links = array_merge($links, $this->linkExtractor->extract($elementStructureValue, $field));
            }
        }

        foreach ($elementStructure->getStructures() as $childStructure) {
            $links = array_merge($links, $this->extractLinks($childStructure));
        }

        return $links;
    }
26159
private function protectTags(HtmlDomParser $dom): HtmlDomParser
    {
        // init
        $counter = 0;

        foreach ($dom->find('script, style') as $element) {

            // skip external links
            if ($element->tag === 'script' || $element->tag === 'style') {
                $attributes = $element->getAllAttributes();
                if (isset($attributes['src'])) {
                    continue;
                }
            }

            $this->protectedChildNodes[$counter] = $element->text();
            $element->getNode()->nodeValue = '<' . $this->protectedChildNodesHelper . ' data-' . $this->protectedChildNodesHelper . '="' . $counter . '"></' . $this->protectedChildNodesHelper . '>';

            ++$counter;
        }

        foreach ($dom->find('code, nocompress') as $element) {
            if ($element->isRemoved()) {
                continue;
            }

            $this->protectedChildNodes[$counter] = $element->parentNode()->innerHtml();
            $element->getNode()->parentNode->nodeValue = '<' . $this->protectedChildNodesHelper . ' data-' . $this->protectedChildNodesHelper . '="' . $counter . '"></' . $this->protectedChildNodesHelper . '>';

            ++$counter;
        }

        foreach ($dom->find('//comment()') as $element) {
            $text = $element->text();

            // skip normal comments
            if (!$this->isConditionalComment($text)) {
                continue;
            }

            $this->protectedChildNodes[$counter] = '<!--' . $text . '-->';

            /* @var $node \DOMComment */
            $node = $element->getNode();
            $child = new \DOMText('<' . $this->protectedChildNodesHelper . ' data-' . $this->protectedChildNodesHelper . '="' . $counter . '"></' . $this->protectedChildNodesHelper . '>');
            /** @noinspection UnusedFunctionResultInspection */
            $element->getNode()->parentNode->replaceChild($child, $node);

            ++$counter;
        }

        return $dom;
    }
705511
public function toXML( DOMDocument $dom )
    {
        $blockNode = $dom->createElement( 'block' );

        foreach ( $this->attributes as $attrName => $attrValue )
        {
            switch ( $attrName )
            {
                case 'id':
                    $blockNode->setAttribute( 'id', 'id_' . $attrValue );
                    break;

                case 'action':
                    $blockNode->setAttribute( 'action', $attrValue );
                    break;

                case 'items':
                    foreach ( $this->attributes['items'] as $item )
                    {
                        $itemNode = $item->toXML( $dom );
                        if ( $itemNode )
                        {
                            $blockNode->appendChild( $itemNode );
                        }
                    }
                    break;

                case 'rotation':
                    $node = $dom->createElement( $attrName );
                    $blockNode->appendChild( $node );

                    foreach ( $attrValue as $arrayItemKey => $arrayItemValue )
                    {
                        $tmp = $dom->createElement( $arrayItemKey );
                        $tmpValue = $dom->createTextNode( $arrayItemValue );
                        $tmp->appendChild( $tmpValue );
                        $node->appendChild( $tmp );
                    }
                    break;

                case 'custom_attributes':
                    $node = $dom->createElement( $attrName );
                    $blockNode->appendChild( $node );

                    foreach ( $attrValue as $arrayItemKey => $arrayItemValue )
                    {
                        $tmp = $dom->createElement( $arrayItemKey );
                        $tmpValue = $dom->createTextNode( $arrayItemValue );
                        $tmp->appendChild( $tmpValue );
                        $node->appendChild( $tmp );
                    }
                    break;

                default:
                    $node = $dom->createElement( $attrName );
                    $nodeValue = $dom->createTextNode( $attrValue );
                    $node->appendChild( $nodeValue );
                    $blockNode->appendChild( $node );
                    break;
            }
        }

        return $blockNode;
    }
1222630
final public function importHTML($html)
	{
		$tmp_doc = new \DOMDocument('1.0', 'UTF-8');
		$tmp_doc->loadHTML($html);
		$nodes = array();
		foreach ($tmp_doc->documentElement->childNodes as $node) {
			array_push($nodes, $node);
			$this->appendChild($this->ownerDocument->importNode($node, true));
		}
		return $nodes;
	}