Html.php
public static function transformRootRelativeUrlsToAbsolute($html, $scheme_and_host) {
    assert('empty(array_diff(array_keys(parse_url($scheme_and_host)), ["scheme", "host", "port"]))', '$scheme_and_host contains scheme, host and port at most.');
    assert('isset(parse_url($scheme_and_host)["scheme"])', '$scheme_and_host is absolute and hence has a scheme.');
    assert('isset(parse_url($scheme_and_host)["host"])', '$base_url is absolute and hence has a host.');

    $html_dom = Html::load($html);
    $xpath = new \DOMXpath($html_dom);

    // Update all root-relative URLs to absolute URLs in the given HTML.
    foreach (static::$uriAttributes as $attr) {
      foreach ($xpath->query("//*[starts-with(@$attr, '/') and not(starts-with(@$attr, '//'))]") as $node) {
        $node->setAttribute($attr, $scheme_and_host . $node->getAttribute($attr));
      }
      foreach ($xpath->query("//*[@srcset]") as $node) {
        // @see https://html.spec.whatwg.org/multipage/embedded-content.html#attr-img-srcset
        // @see https://html.spec.whatwg.org/multipage/embedded-content.html#image-candidate-string
        $image_candidate_strings = explode(',', $node->getAttribute('srcset'));
        $image_candidate_strings = array_map('trim', $image_candidate_strings);
        for ($i = 0; $i < count($image_candidate_strings); $i++) {
          $image_candidate_string = $image_candidate_strings[$i];
          if ($image_candidate_string[0] === '/' && $image_candidate_string[1] !== '/') {
            $image_candidate_strings[$i] = $scheme_and_host . $image_candidate_string;
          }
        }
        $node->setAttribute('srcset', implode(', ', $image_candidate_strings));
      }
    }
    return Html::serialize($html_dom);
  }
public static function transformRootRelativeUrlsToAbsolute($html, $scheme_and_host) {
    assert('empty(array_diff(array_keys(parse_url($scheme_and_host)), ["scheme", "host", "port"]))', '$scheme_and_host contains scheme, host and port at most.');
    assert('isset(parse_url($scheme_and_host)["scheme"])', '$scheme_and_host is absolute and hence has a scheme.');
    assert('isset(parse_url($scheme_and_host)["host"])', '$base_url is absolute and hence has a host.');

    $html_dom = Html::load($html);
    $xpath = new \DOMXpath($html_dom);

    // Update all root-relative URLs to absolute URLs in the given HTML.
    foreach (static::$uriAttributes as $attr) {
      foreach ($xpath->query("//*[starts-with(@$attr, '/') and not(starts-with(@$attr, '//'))]") as $node) {
        $node->setAttribute($attr, $scheme_and_host . $node->getAttribute($attr));
      }
      foreach ($xpath->query("//*[@srcset]") as $node) {
        // @see https://html.spec.whatwg.org/multipage/embedded-content.html#attr-img-srcset
        // @see https://html.spec.whatwg.org/multipage/embedded-content.html#image-candidate-string
        $image_candidate_strings = explode(',', $node->getAttribute('srcset'));
        $image_candidate_strings = array_map('trim', $image_candidate_strings);
        for ($i = 0; $i < count($image_candidate_strings); $i++) {
          $image_candidate_string = $image_candidate_strings[$i];
          if ($image_candidate_string[0] === '/' && $image_candidate_string[1] !== '/') {
            $image_candidate_strings[$i] = $scheme_and_host . $image_candidate_string;
          }
        }
        $node->setAttribute('srcset', implode(', ', $image_candidate_strings));
      }
    }
    return Html::serialize($html_dom);
  }
public static function transformRootRelativeUrlsToAbsolute ( $ html , $ scheme_and_host ) { assert ( 'empty(array_diff(array_keys(parse_url($scheme_and_host)), ["scheme", "host", "port"]))' , '$scheme_and_host contains scheme, host and port at most.' ) ; assert ( 'isset(parse_url($scheme_and_host)["scheme"])' , '$scheme_and_host is absolute and hence has a scheme.' ) ; assert ( 'isset(parse_url($scheme_and_host)["host"])' , '$base_url is absolute and hence has a host.' ) ; $ html_dom = Html :: load ( $ html ) ; $ xpath = new \ DOMXpath ( $ html_dom ) ; // Update all root-relative URLs to absolute URLs in the given HTML. foreach ( static :: $ uriAttributes as $ attr ) { foreach ( $ xpath -> query ( "//*[starts-with(@$attr, '/') and not(starts-with(@$attr, '//'))]" ) as $ node ) { $ node -> setAttribute ( $ attr , $ scheme_and_host . $ node -> getAttribute ( $ attr ) ) ; } foreach ( $ xpath -> query ( "//*[@srcset]" ) as $ node ) { // @see https://html.spec.whatwg.org/multipage/embedded-content.html#attr-img-srcset // @see https://html.spec.whatwg.org/multipage/embedded-content.html#image-candidate-string $ image_candidate_strings = explode ( ',' , $ node -> getAttribute ( 'srcset' ) ) ; $ image_candidate_strings = array_map ( 'trim' , $ image_candidate_strings ) ; for ( $ i = 0 ; $ i < count ( $ image_candidate_strings ) ; $ i ++ ) { $ image_candidate_string = $ image_candidate_strings [ $ i ] ; if ( $ image_candidate_string [ 0 ] === '/' && $ image_candidate_string [ 1 ] !== '/' ) { $ image_candidate_strings [ $ i ] = $ scheme_and_host . $ image_candidate_string ; } } $ node -> setAttribute ( 'srcset' , implode ( ', ' , $ image_candidate_strings ) ) ; } } return Html :: serialize ( $ html_dom ) ; }
Converts all root-relative URLs to absolute URLs.

Does not change any existing protocol-relative or absolute URLs. Does not
change other relative URLs because they would result in different absolute
URLs depending on the current path. For example: when the same content
containing such a relative URL (for example 'image.png'), is served from
its canonical URL (for example 'http://example.com/some-article') or from
a listing or feed (for example 'http://example.com/all-articles') their
"current path" differs, resulting in different absolute URLs:
'http://example.com/some-article/image.png' versus
'http://example.com/all-articles/image.png'. Only one can be correct.
Therefore relative URLs that are not root-relative cannot be safely
transformed and should generally be avoided.

Necessary for HTML that is served outside of a website, for example, RSS
and e-mail.

@param string $html
The partial (X)HTML snippet to load. Invalid markup will be corrected on
import.
@param string $scheme_and_host
The root URL, which has a URI scheme, host and optional port.

@return string
The updated (X)HTML snippet.
Converts all root - relative URLs to absolute URLs .