Parse HTML snippet, save all found <img> tags using media_handle_sideload(), return the HTML with changed <img> paths.

@param \DOMDocument $dom

@return array An array containing the \DOMDocument and the IDs of created attachments
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,
		];
	}
1220385
protected static function getNodes(DOMDocument $dom, $type)
	{
		$nodes  = [];
		$prefix = ($type === 'attribute') ? '@' : '';
		$xpath  = new DOMXPath($dom);

		// Get natural nodes
		foreach ($xpath->query('//' . $prefix . '*') as $node)
		{
			$nodes[] = [$node, $node->nodeName];
		}

		// Get XSL-generated nodes
		foreach ($xpath->query('//xsl:' . $type) as $node)
		{
			$nodes[] = [$node, $node->getAttribute('name')];
		}

		// Get xsl:copy-of nodes
		foreach ($xpath->query('//xsl:copy-of') as $node)
		{
			if (preg_match('/^' . $prefix . '(\\w+)$/', $node->getAttribute('select'), $m))
			{
				$nodes[] = [$node, $m[1]];
			}
		}

		return $nodes;
	}
1154951
public function canHandle(\DOMDocument $dom)
    {
        $result = false;
        $rootNodes = $dom->getElementsByTagName('rss');
        if ($rootNodes->length == 1) {
            $version = $rootNodes->item(0)->attributes->getNamedItem('version');
            $result = $version && fnmatch($this->getVersionPattern(), $version->nodeValue);
        }
        return $result;
    }
1035642
public function pullRemoteAssets(\DomDocument &$dom){
		$paths = [];
		foreach(['img' => 'src', 'script' => 'src', 'link' => 'href'] as $tag => $attr){
			foreach( $dom->getElementsByTagName($tag) as $elem ){
				$url = $elem->getAttribute($attr);
				if( !preg_match('/^(https?:)?\/\//', $url) ){
					continue;
				}
				// Get remote resource
				if( !($resource = $this->getRemote($url)) ){
					continue;
				}
				// Let's detect file mime
				list($basename) = explode('?', basename($url));
				$dir = Mime::getDestinationFolder($basename);
				if( 'Misc' === $dir ){
					// Oh, it might not have extension...
					if( $resource['info'] ){
						list($mime, $type) = explode('/', $resource['info']['content_type']);
						list($ext) = explode(';', $type);
						$new_dir = Mime::getDestinationFolder("hoge.{$ext}");
						if( $new_dir != $dir ){
							$dir = $new_dir;
							$basename = "{$basename}.{$ext}";
						}
					}
				}
				// O.K.
				$new_path = $dir.'/'.$basename;
				$elem->setAttribute($attr, '../'.$new_path);
				if( $this->distributor->write($resource['body'], 'OEBPS/'.$new_path) ){
					$paths[] = $new_path;
				}
			}
		}
		return $paths;
	}
1286592
private function writeDocument(\DOMDocument $dom)
    {
        $dom->formatOutput = true;
        $this->write($dom->saveXML());
    }
175124
public static function getDOM($str)
	{
		//create domdocument
		$dom = new DOMDocument();
		//load by file or string
		is_file($str) ? $dom->load($str) : $dom->loadXML($str);
		// return the DOMDoc
		return $dom;
	}
755813
protected function extractImages($html)
    {
        if (empty($html)) {
            return [];
        }

        $libxmlPreviousState = libxml_use_internal_errors(true);

        $dom = new DOMDocument;
        $dom->loadHTML($html);

        libxml_clear_errors();
        libxml_use_internal_errors($libxmlPreviousState);

        $images = [];

        //Gets all image tags
        foreach ($dom->getElementsByTagName('img') as $item) {
            $src = $item->getAttribute('src');

            if (in_array(strtolower(pathinfo($src, PATHINFO_EXTENSION)), ['gif', 'jpg', 'jpeg', 'png'])) {
                $images[] = $src;
            }
        }

        //Gets all Youtube videos
        if (preg_match_all('/\[youtube](.+?)\[\/youtube]/', $html, $items)) {
            foreach ($items[1] as $item) {
                $images[] = Youtube::getPreview($item);
            }
        }

        return $images;
    }
527800
public static function save(DOMDocument $dom)
	{
		$xml = self::innerXML($dom->documentElement);
		if (strpos($xml, 'xmlns:xsl') !== false)
		{
			$xml = preg_replace('((<[^>]+?) xmlns:xsl="' . self::XMLNS_XSL . '")', '$1', $xml);
		}

		return $xml;
	}
490279
protected function parseHtml($html)
    {
        $data = [
            'image' => '',
            'title' => '',
            'description' => '',
            'pictures' => [],
        ];

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

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

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

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

        if (empty($data['title'])) {
            /** @var \DOMElement $title */
            foreach ($doc->getElementsByTagName('title') as $title) {
                $data['title'] = $title->nodeValue;
            }
        }

        if (empty($data['description'])) {
            foreach ($doc->getElementsByTagName('meta') as $meta) {
                if ($meta->getAttribute('name') === 'description') {
                    $data['description'] = $meta->getAttribute('content');
                }
            }
        }

        foreach ($doc->getElementsByTagName('img') as $img) {
            $data['pictures'][] = $img->getAttribute('src');
        }

        return $data;
    }
1131233
public function extract($dom, $url)
    {
        $this->resetEmails();

        preg_match_all('/[a-z\d._%+-]+[a-z\d._%+-]+@[a-z\d.-]+\.[a-z]{2,4}\b/i', $dom, $matches);

        foreach ($matches[0] as $match) {
            if (filter_var($match, FILTER_VALIDATE_EMAIL)) {
                if ($this->endsWith(strtolower($match), $this->mediaExtensions)) {
                    continue;
                }
                $this->emails[] = $match;
            }
        }

        return $this->emails;
    }
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());
       }
   }
518777
private function parsePathsSettings(\DOMNode $paths) {

		if(is_null($this->paths)) {
			$this->paths = [];
		}

		foreach($paths->getElementsByTagName('path') as $path) {

			$id = $path->getAttribute('id');
			$subdir = $path->getAttribute('subdir') ?: '';

			if(!$id || !$subdir) {
				continue;
			}

			$subdir = '/' . trim($subdir, '/') . '/';

			// additional attributes are currently ignored

			$this->paths[$id] = ['subdir' => $subdir];

		}

	}
520740
public function all($tag) {
  $i = $this->image = new Image;
  $images = $this->get($tag, 'basename');
  $results = array();
  foreach($images as $image) {
   try {
    $results[] = $i->get($image['uid']);
   }
   catch(\Exception $e) {
    if ($e->getCode() != 403) {
     throw new \Exception($e);
    }
   }
  }
  return $results;
 }
570771
public static function save_svg(\DOMDocument $dom) {
		$svgs = $dom->getElementsByTagName('svg');
		if (! $svgs->length) {
			return '';
		}
		$svg = $svgs->item(0)->ownerDocument->saveXML(
			$svgs->item(0),
			\LIBXML_NOBLANKS
		);

		// Make sure if xmlns="" exists, it is correct. Can't alter
		// that with DOMDocument, and there is only one proper value.
		$svg = \preg_replace(
			'/xmlns\s*=\s*"[^"]*"/',
			'xmlns="' . constants::SVG_NAMESPACE . '"',
			$svg
		);

		// Remove XML, PHP, ASP, etc.
		$svg = \preg_replace('/<\?(.*)\?>/Us', '', $svg);
		$svg = \preg_replace('/<\%(.*)\%>/Us', '', $svg);

		if ((false !== \strpos($svg, '<?')) || (false !== \strpos($svg, '<%'))) {
			return '';
		}

		// Remove comments.
		$svg = \preg_replace('/<!--(.*)-->/Us', '', $svg);
		$svg = \preg_replace('/\/\*(.*)\*\//Us', '', $svg);

		if ((false !== \strpos($svg, '<!--')) || (false !== \strpos($svg, '/*'))) {
			return '';
		}

		// Find the start and end tags so we can cut out miscellaneous garbage.
		if (
			(false === ($start = mb::strpos($svg, '<svg'))) ||
			(false === ($end = mb::strrpos($svg, '</svg>')))
		) {
			return false;
		}
		$svg = mb::substr($svg, $start, ($end - $start + 6));

		return $svg;
	}
1287281
protected function scrapeAndKneadImages( \DOMDocument $doc ) {

		$images = $doc->getElementsByTagName( 'img' );
		foreach ( $images as $image ) {
			/** @var \DOMElement $image */
			// Fetch image, change src
			$old_src = $image->getAttribute( 'src' );
			$new_src = $this->fetchAndSaveUniqueImage( $old_src );
			if ( $new_src ) {
				// Replace with new image
				$image->setAttribute( 'src', $new_src );
			} else {
				// Tag broken image
				$image->setAttribute( 'src', "{$old_src}#fixme" );
			}
		}

		return $doc;
	}
746664
public function getTagsByXPath( $query )
	{
		$list	= array();
		$xpath	= new DomXPath( $this->document );
		$nodes	= $xpath->query( $query );
		foreach( $nodes as $node )
		{
			if( preg_match( "#/@[a-z]+$#i", $query ) )
				$node	= $node->textContent;
			$list[]	= $node;
		}
		return $list;
	}
1056688
function createLinksArray( $dom )
    {
        $links = array();
        $node = array();

        if ( $dom )
        {
            // Fetch all links and cache the url's
            $links = $dom->getElementsByTagName( "link" );
        }

        $linkIDArray = array();
        // Find all Link id's
        foreach ( $links as $link )
        {
            $linkIDValue = $link->getAttribute( 'url_id' );
            if ( !$linkIDValue )
            {
                continue;
            }
            if ( !in_array( $linkIDValue, $linkIDArray ) )
            {
                 $linkIDArray[] = $linkIDValue;
             }
        }

        if ( count( $linkIDArray ) > 0 )
        {
            $inIDSQL = implode( ', ', $linkIDArray );
            $db = eZDB::instance();
            $linkArray = $db->arrayQuery( "SELECT * FROM ezurl WHERE id IN ( $inIDSQL ) " );
            foreach ( $linkArray as $linkRow )
            {
                $this->LinkArray[$linkRow['id']] = $linkRow['url'];
            }
        }
    }