HTTP/2 with Server Push and HTTP/1 compatible inline CSS

<?php
/**
 * Enqueue assets required by the theme.
 */
function pwcc_register_assets() {
  // Enqueue Stylesheet
  wp_enqueue_style(
    'pwcc-style',
    get_stylesheet_uri(),
    array(),
    '1.0',
    'all'
  );
  wp_style_add_data( 'pwcc-style', 'pwcc_critical', true );

  // Register Load CSS for later enqueueing if needed.
  wp_register_script(
    'pwcc-load-css',
    get_stylesheet_directory_uri() . '/loadcss.js',
    array( 'jquery' ),
    '1.2.0',
    true
  );
}
add_action( 'wp', 'pwcc_register_assets' );

/**
 * Detect if using the HTTP/2 Prootocol.
 *
 * This detects if the user's sesion is running over HTTP/2
 *
 * @return boolean Returns true if running HTTP/2
 */
function pwcc_is_http2() {
  if ( ! isset( $_SERVER['SERVER_PROTOCOL'] ) ) {
    return false;
  }

  switch ( strtolower( wp_unslash( $_SERVER['SERVER_PROTOCOL'] ) ) ) {
    case 'h2': // Falls through
    case 'http/2.0':
      return true;

    default:
      return false;
  }
}

/**
 * Set a cookied to indicate an asset is likely cached by the browser.
 *
 * @param string   $handle The handle by which the asset is known to WordPress.
 * @param string   $version The asset's version.
 * @return boolean Whether the cookie was able to be set.
 */
function pwcc_set_asset_cached( $handle, $version ) {
  $handle = base_convert( sha1( $handle ), 16, 36 );
  $version = base_convert( sha1( $version ), 16, 36 );

  $handle = substr( $handle, 0, 5 );
  $version = substr( $version, 0, 5 );

  return setcookie( 'pwcc_' . $handle, $version, 0, '/' );
}

/**
 * Check for coookie indicating asset is likely cached by the browser.
 *
 * @param string   $handle The handle by which the asset is known to WordPress.
 * @param string   $version The asset's version.
 * @return boolean Whether the file is likely to be cached.
 */
function pwcc_is_asset_cached( $handle, $version ) {
  $handle = base_convert( sha1( $handle ), 16, 36 );
  $version = base_convert( sha1( $version ), 16, 36 );

  $handle = substr( $handle, 0, 5 );
  $version = substr( $version, 0, 5 );

  if ( $version === $_COOKIE[ 'pwcc_' . $handle ] ) {
    return true;
  }
  return false;
}

/**
 * Set cookied indicating stylesheet is likely cached by the browser.
 *
 * @param string   $handle The handle by which the stylesheet is known to WordPress.
 * @return boolean Whether the cookie was able to be set.
 */
function pwcc_set_style_cached( $handle ) {
  global $wp_styles;

  if ( ! isset( $wp_styles->registered[ $handle ] ) ) {
    return false;
  }

  $handle .= '-css';

  $version = $wp_styles->registered[ $handle ]->ver;
  $version = $version ? $version : 'unknown';

  return pwcc_set_asset_cached( $handle, $version );
}

/**
 * Check for coookie indicating stylesheet is likely cached by the browser.
 *
 * @param string   $handle The handle by which the stylesheet is known to WordPress.
 * @return boolean Whether the file is likely to be cached.
 */
function pwcc_is_style_cached( $handle ) {
  global $wp_styles;

  if ( ! isset( $wp_styles->registered[ $handle ] ) ) {
    return false;
  }

  $handle .= '-css';

  $version = $wp_styles->registered[ $handle ]->ver;
  $version = $version ? $version : 'unknown';

  return pwcc_is_asset_cached( $handle, $version );
}

/**
 * Output HTTP Preload header for registed WordPress stylesheet.
 *
 * @param string   $handle Registered name of the Stylesheet.
 * @param boolean  $push   If the server should attempt to push the asset. Default true.
 * @return boolean true on success, false on failure.
 */
function pwcc_preload_style( $handle, $push = true ) {
  global $wp_styles;

  // Only preload if enqueued.
  if ( ! wp_style_is( $handle ) ) {
    return false;
  }

  $style = $wp_styles->registered[ $handle ];

  $nopush = '';
  if ( ! $push ) {
    $nopush = '; nopush';
  }

  $source = add_query_arg(
    'ver',
    $style->ver,
    $style->src
  );

  header( 'Link: <' . esc_url_raw( $source ) . '>; rel=preload; as=style' . $nopush );

  return true;
}

/**
 * Print the contents of a CSS file inline.
 *
 * If the file is printed inline, sets up data for the file to be preloaded and for loadCSS to be enqueued.
 *
 * @param  string  $handle  Registered name of the Stylesheet.
 * @return boolean true on success, false on failure.
 */
function pwcc_print_style_inline( $handle ) {
  global $wp_styles;

  if ( ! isset( $wp_styles->registered[ $handle ] ) ) {
    return false;
  }
  $style = $wp_styles->registered[ $handle ];

  $path_to_file = pwcc_wp_url_to_path( $style->src );

  if ( false === $path_to_file ) {
    // Could not find file.
    return false;
  }

  $inline_css = file_get_contents( $path_to_file );

  wp_add_inline_style( $handle, $inline_css );
  wp_style_add_data( $handle, 'pwcc_rel_preload', true );

  return true;
}

/**
 * Convert an assets URL to a path.
 *
 * Makes a best guess as to the path of an asset.
 *
 * @param string  $url  The URL to the asset.
 * @return string|boolean The path to the asset. False of failure.
 */
function pwcc_wp_url_to_path( $url ) {

  $url = remove_query_arg( 'ver', $url );

  $path = str_replace(
    array( trailingslashit( content_url() ), trailingslashit( includes_url() ) ),
    array( trailingslashit( WP_CONTENT_DIR ), trailingslashit( ABSPATH . WPINC ) ),
    $url
  );

  if ( ! file_exists( $path ) ) {
    return false;
  }

  return $path;
}

/**
 * Add HTTP Link headers required by server push.
 */
function pwcc_preload_http_headers() {
  global $wp_styles;

  foreach ( $wp_styles->registered as $style ) {
    if ( isset( $style->extra['pwcc_critical'] ) && $style->extra['pwcc_critical'] ) {
      if ( pwcc_is_style_cached( $style->handle ) ) {
        pwcc_preload_style( $style->handle, false );
      } else {
      // Server push (if available).
        pwcc_preload_style( $style->handle );
      }

      if ( ! pwcc_is_style_cached( $style->handle ) && ! pwcc_is_http2() ) {
        pwcc_print_style_inline( $style->handle );
        wp_enqueue_script( 'pwcc-load-css' );
      }

      pwcc_set_style_cached( $style->handle );
    }
  }
}
add_action( 'wp','pwcc_preload_http_headers', 20 );

/**
 * Replaces a stylesheet link tag with a preload tag.
 *
 * @param string $tag     The link tag as generated by WordPress.
 * @param string $handle  The handle by which the stylesheet is known to WordPress.
 * @param string $href    The URL to the stylesheet, including version number.
 * @param string $media   The media attribute of the stylesheet.
 * @return string The original tag wrapped in a noscript element, followed by the preload tag.
 */
function pwcc_filter_style_loader_tag( $tag, $handle, $href, $media ) {
  global $wp_styles;

  if ( ! isset( $wp_styles->registered[ $handle ] ) ) {
    return false;
  }
  $style = $wp_styles->registered[ $handle ];

  if ( ! isset( $style->extra['pwcc_rel_preload'] ) || ! $style->extra['pwcc_rel_preload'] ) {
    return $tag;
  }

  $rel = isset( $obj->extra['alt'] ) && $obj->extra['alt'] ? 'alternate stylesheet' : 'stylesheet';

  $tag = sprintf( '<noscript>%s</noscript>', $tag );
  $tag .= sprintf(
    '<link rel="preload" as="style" onload="%s" id="%s-css" href="%s" type="text/css" media="%s" />',
    "this.rel='" . esc_js( $rel ) . "'",
    esc_attr( $handle . ':preload' ),
    esc_url_raw( $href ),
    esc_attr( $media )
  );

  return $tag;
}
add_filter( 'style_loader_tag', 'pwcc_filter_style_loader_tag', 10, 4 );