File "class-viewport.php"
Full Path: /home/timepamn/dailynetworth.org/wp-content/plugins/jetpack-boost-git/app/lib/class-viewport.php
File size: 7.75 KB
MIME-type: text/x-php
Charset: utf-8
<?php
/**
* Implements the Viewport functionality.
*
* @link https://automattic.com
* @since 1.0.0
* @package automattic/jetpack-boost
*/
namespace Automattic\Jetpack_Boost\Lib;
use Automattic\Jetpack\Device_Detection;
/**
* Class Viewport
*/
class Viewport {
/**
* Viewport cookie name.
*/
const VIEWPORT_COOKIE = 'jetpack_boost_w';
/**
* Mobile device identifier.
*/
const DEVICE_MOBILE = 'mobile';
/**
* Desktop identifier.
*/
const DEVICE_DESKTOP = 'desktop';
/**
* Default viewport sizes.
*/
const DEFAULT_VIEWPORT_SIZES = array(
0 => array(
'type' => 'phone',
'width' => 640,
'height' => 480,
),
1 => array(
'type' => 'tablet',
'width' => 1200,
'height' => 800,
),
2 => array(
'type' => 'desktop',
'width' => 1600,
'height' => 1050,
),
);
/**
* Default viewports.
*/
const DEFAULT_VIEWPORTS = array(
array(
'device_type' => 'mobile',
'viewport_id' => 0,
),
array(
'device_type' => 'desktop',
'viewport_id' => 2,
),
);
/**
* Runs the module.
*/
public static function init() {
if ( ! is_admin() ) {
add_action(
'wp_footer',
array( __CLASS__, 'viewport_tracker' )
);
}
}
/**
* Prints JS viewport dimensions tracker to the page.
*
* The purpose of the tracker is to measure the actual device viewport and store that value
* in a cookie that is then consumed by `get_viewport_size`. The dimensions are updated
* whenever the page is loaded, viewport resized or document shown (using Page Visibility API).
*
* This allows site admins to define and target more granular real-world viewports.
*
* First page load from a new device will result in a viewport size guessed based on the device
* type (mobile vs. desktop). See `get_default_viewport_size_for_device` for more context.
*/
public static function viewport_tracker() {
$domain = wp_parse_url( site_url(), PHP_URL_HOST );
$path = wp_parse_url( site_url(), PHP_URL_PATH );
if ( ! $path ) {
$path = '/';
}
$max_age = 10 * \YEAR_IN_SECONDS;
$script_source = <<<SCRIPT_SOURCE
( function(doc) {
var debouncer;
var measure = function() {
var cookieValue = Math.ceil( window.innerWidth / 10 ) + 'x' + Math.ceil( window.innerHeight / 10 );
doc.cookie = "%s=" + cookieValue + "; domain=%s; path=%s; Max-Age=%s";
}
window.addEventListener( 'resize', function() {
clearTimeout( debouncer );
debouncer = setTimeout( measure, 500 );
} );
doc.addEventListener( 'visibilitychange', function() {
if ( ! doc.hidden ) {
measure();
}
} );
measure();
} )(document);
SCRIPT_SOURCE;
$script_source = sprintf( $script_source, esc_js( self::VIEWPORT_COOKIE ), esc_js( $domain ), esc_js( $path ), esc_js( $max_age ) );
if ( ! Debug::is_debug_mode() ) {
$script_source = Minify::js( $script_source );
}
printf( '<script>%s</script>', $script_source ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
/**
* Gets the size of the current viewport.
*/
public static function get_viewport_size() {
$data = null;
$cookie_value = filter_input( INPUT_COOKIE, self::VIEWPORT_COOKIE );
if ( $cookie_value ) {
$raw_data = explode( 'x', $cookie_value );
if ( 2 === count( $raw_data ) ) {
$data = array(
'width' => intval( $raw_data[0] ) * 10,
'height' => intval( $raw_data[1] ) * 10,
);
}
} else {
$device_type = Device_Detection::is_phone() ? self::DEVICE_MOBILE : self::DEVICE_DESKTOP;
$data = self::get_default_viewport_size_for_device( $device_type );
}
return apply_filters( 'jetpack_boost_viewport_size', $data, self::VIEWPORT_COOKIE, $cookie_value );
}
/**
* Get all the configured viewport sizes.
*
* @return array Viewport widths and heights
*/
public static function get_default_viewport_sizes() {
return apply_filters( 'jetpack_boost_critical_css_viewport_sizes', self::DEFAULT_VIEWPORT_SIZES );
}
/**
* Get the default viewport size.
*
* @param string $device_type Device type.
*
* @return array Viewport width and height.
*/
public static function get_default_viewport_size_for_device( $device_type ) {
$viewport_sizes = apply_filters( 'jetpack_boost_critical_css_viewport_sizes', self::DEFAULT_VIEWPORT_SIZES );
$default_viewports = apply_filters( 'jetpack_boost_critical_css_default_viewports', self::DEFAULT_VIEWPORTS );
foreach ( $default_viewports as $default ) {
if ( $device_type === $default['device_type'] ) {
if ( isset( $viewport_sizes[ $default['viewport_id'] ] ) ) {
return $viewport_sizes[ $default['viewport_id'] ];
}
}
}
return self::get_max_viewport( $viewport_sizes );
}
/**
* Picks the narrowest defined viewport that is equal or wider than the passed width.
*
* When there are multiple defined viewports of identical width, picks the smallest
* height that's equal or taller than the passed height.
*
* Example for w:550 h:400 and defined viewport sizes: 400x300, 640x400, 640x480, 1050x900, 1900x1200
*
* - The smallest viewports that are wider than the current one are: 640x400, 640x480
* - The one with the smallest height that is equal or taller than the passed dimensions: 640x400
* - Returned [ 640, 480 ]
*
* @param int $width Width.
* @param int $height Height.
*
* @return array Viewport dimensions.
*/
public static function pick_viewport( $width, $height ) {
// Get defined viewport sizes.
$viewport_sizes = apply_filters( 'jetpack_boost_critical_css_viewport_sizes', self::DEFAULT_VIEWPORT_SIZES );
// Default to the widest viewport in case we don't match anything.
$best_size = self::get_max_viewport( $viewport_sizes );
foreach ( $viewport_sizes as $viewport_size ) {
// Skip viewports that are too narrow.
if ( $viewport_size['width'] < $width ) {
continue;
}
// Skip viewports that are wider than our best match.
if ( $viewport_size['width'] > $best_size['width'] ) {
continue;
}
// Pick viewports that are narrower than our best match.
if ( $viewport_size['width'] < $best_size['width'] ) {
$best_size = $viewport_size;
continue;
}
// Current viewport and the best match have the same width, let's decide based on height.
$current_is_tall_enough = $viewport_size['height'] >= $height;
$best_is_tall_enough = $best_size['height'] >= $height;
if ( $current_is_tall_enough && ! $best_is_tall_enough ) {
$best_size = $viewport_size; // Best match isn't tall enough, but the current match is.
continue;
}
if ( $current_is_tall_enough && $best_is_tall_enough && $viewport_size['height'] < $best_size['height'] ) {
$best_size = $viewport_size; // Both ARE tall enough, but the current match is shorter.
continue;
}
if ( ! $current_is_tall_enough && ! $best_is_tall_enough && $viewport_size['height'] > $best_size['height'] ) {
$best_size = $viewport_size; // Both ARE NOT tall enough, but the current match is taller.
continue;
}
}
return apply_filters( 'jetpack_boost_pick_viewport', $best_size, $width, $height, $viewport_sizes );
}
/**
* Reduce the viewports array and return the widest one.
*
* When there are multiple widest viewports, pick the tallest one from those.
*
* @param array $viewport_sizes Array of defined viewport sizes.
*
* @return array Viewport dimensions.
*/
public static function get_max_viewport( array $viewport_sizes ) {
$max_viewport = array_reduce(
$viewport_sizes,
function ( $carry, $item ) {
if ( $item['width'] > $carry['width'] ) {
$carry = $item;
} elseif ( $item['width'] === $carry['width'] ) {
if ( $item['height'] > $carry['height'] ) {
$carry = $item;
}
}
return $carry;
},
array(
'width' => 0,
'height' => 0,
)
);
return $max_viewport;
}
}