/home/arranoyd/public_html/wp-content/plugins/litespeed-cache/src/css.cls.php
<?php
/**
* The optimize css class.
*
* @since 2.3
* @package LiteSpeed
* @subpackage LiteSpeed/inc
* @author LiteSpeed Technologies <info@litespeedtech.com>
*/
namespace LiteSpeed ;
defined( 'WPINC' ) || exit ;
class CSS extends Base
{
protected static $_instance ;
const TYPE_GENERATE_CRITICAL = 'generate_critical' ;
protected $_summary;
/**
* Init
*
* @since 3.0
* @access protected
*/
protected function __construct()
{
$this->_summary = self::get_summary();
}
/**
* Output critical css
*
* @since 1.3
* @since 2.3 Migrated from optimize.cls
* @access public
*/
public static function prepend_ccss( $html_head )
{
// Get critical css for current page
// Note: need to consider mobile
$rules = self::get_instance()->_ccss() ;
// Append default critical css
$rules .= Conf::val( Base::O_OPTM_CCSS_CON ) ;
$html_head = '<style id="litespeed-optm-css-rules">' . $rules . '</style>' . $html_head ;
return $html_head ;
}
/**
* Check if there is a ccss cache folder
*
* @since 2.3
* @access public
*/
public static function has_ccss_cache()
{
return is_dir( LITESPEED_STATIC_DIR . '/ccss' ) ;
}
/**
* Generate realpath of ccss
*
* @since 2.3
* @access private
*/
private function _ccss_realpath( $ccss_type )
{
return LITESPEED_STATIC_DIR . "/ccss/$ccss_type.css" ;
}
/**
* Delete file-based cache folder
*
* @since 2.3
* @access public
*/
public function rm_cache_folder()
{
if ( file_exists( LITESPEED_STATIC_DIR . '/ccss' ) ) {
File::rrmdir( LITESPEED_STATIC_DIR . '/ccss' ) ;
}
// Clear CCSS in queue too
$this->_summary[ 'queue' ] = array() ;
$this->_summary[ 'curr_request' ] = 0 ;
self::save_summary();
Debug2::debug2( '[CSS] Cleared ccss queue' ) ;
}
/**
* The critical css content of the current page
*
* @since 2.3
* @access private
*/
private function _ccss()
{
// If don't need to generate CCSS, bypass
if ( ! Conf::val( Base::O_OPTM_CCSS_GEN ) ) {
Debug2::debug( '[CSS] bypassed ccss due to setting' ) ;
return '' ;
}
$ccss_type = $this->_which_css() ;
$ccss_file = $this->_ccss_realpath( $ccss_type ) ;
if ( file_exists( $ccss_file ) ) {
Debug2::debug2( '[CSS] existing ccss ' . $ccss_file ) ;
return File::read( $ccss_file ) ;
}
// Check if is already in a request, bypass current one
if ( ! empty( $this->_summary[ 'curr_request' ] ) && time() - $this->_summary[ 'curr_request' ] < 300 ) {
Debug2::debug( '[CCSS] Last request not done' );
return '' ;
}
global $wp ;
$request_url = home_url( $wp->request ) ;
// If generate in backend, log it and bypass
if ( Conf::val( Base::O_OPTM_CCSS_ASYNC ) ) {
// Store it to prepare for cron
if ( empty( $this->_summary[ 'queue' ] ) ) {
$this->_summary[ 'queue' ] = array() ;
}
$this->_summary[ 'queue' ][ $ccss_type ] = array(
'url' => $request_url,
'user_agent' => $_SERVER[ 'HTTP_USER_AGENT' ],
'is_mobile' => $this->_separate_mobile_ccss(),
) ;// Current UA will be used to request
Debug2::debug( '[CSS] Added queue [type] ' . $ccss_type . ' [url] ' . $request_url . ' [UA] ' . $_SERVER[ 'HTTP_USER_AGENT' ] ) ;
self::save_summary();
return '' ;
}
// generate on the fly
return $this->_generate_ccss( $request_url, $ccss_type, $_SERVER[ 'HTTP_USER_AGENT' ], $this->_separate_mobile_ccss() ) ;
}
/**
* Check if need to separate ccss for mobile
*
* @since 2.6.4
* @access private
*/
private function _separate_mobile_ccss()
{
return apply_filters( 'litespeed_is_mobile', false ) && Conf::val( Base::O_CACHE_MOBILE ) ;
}
/**
* Cron ccss generation
*
* @since 2.3
* @access private
*/
public static function cron_ccss( $continue = false )
{
$_instance = self::get_instance();
if ( empty( $_instance->_summary[ 'queue' ] ) ) {
return ;
}
// For cron, need to check request interval too
if ( ! $continue ) {
if ( ! empty( $_instance->_summary[ 'curr_request' ] ) && time() - $_instance->_summary[ 'curr_request' ] < 300 ) {
Debug2::debug( '[CCSS] Last request not done' );
return ;
}
}
foreach ( $_instance->_summary[ 'queue' ] as $k => $v ) {
Debug2::debug( '[CSS] cron job [type] ' . $k . ' [url] ' . $v[ 'url' ] . ( $v[ 'is_mobile' ] ? ' 📱 ' : '' ) . ' [UA] ' . $v[ 'user_agent' ] ) ;
$_instance->_generate_ccss( $v[ 'url' ], $k, $v[ 'user_agent' ], $v[ 'is_mobile' ] ) ;
// only request first one
if ( ! $continue ) {
return ;
}
}
}
/**
* Send to LiteSpeed CCSS API to generate CCSS
*
* @since 2.3
* @access private
*/
private function _generate_ccss( $request_url, $ccss_type, $user_agent, $is_mobile )
{
// Check if has credit to push
$allowance = Cloud::get_instance()->allowance( Cloud::SVC_CCSS );
if ( ! $allowance ) {
Debug2::debug( '[CCSS] ❌ No credit' );
Admin_Display::error( Error::msg( 'lack_of_quota' ) );
return;
}
$ccss_file = $this->_ccss_realpath( $ccss_type ) ;
// Update css request status
$this->_summary[ 'curr_request' ] = time() ;
self::save_summary();
// Generate critical css
$data = array(
'url' => $request_url,
'ccss_type' => $ccss_type,
'user_agent' => $user_agent,
'is_mobile' => $is_mobile ? 1 : 0,
) ;
Debug2::debug( '[CSS] Generating: ', $data ) ;
$json = Cloud::post( Cloud::SVC_CCSS, $data, 180 ) ;
if ( ! is_array( $json ) ) {
return false;
}
if ( empty( $json[ 'ccss' ] ) ) {
Debug2::debug( '[CSS] ❌ empty ccss' ) ;
$this->_popup_and_save( $ccss_type, $request_url );
return false ;
}
// Add filters
$ccss = apply_filters( 'litespeed_ccss', $json[ 'ccss' ], $ccss_type ) ;
// Write to file
File::save( $ccss_file, $ccss, true ) ;
// Save summary data
$this->_summary[ 'last_spent' ] = time() - $this->_summary[ 'curr_request' ] ;
$this->_summary[ 'last_request' ] = $this->_summary[ 'curr_request' ] ;
$this->_summary[ 'curr_request' ] = 0 ;
$this->_popup_and_save( $ccss_type, $request_url );
Debug2::debug( '[CSS] saved ccss ' . $ccss_file ) ;
Debug2::debug2( '[CSS] ccss con: ' . $ccss ) ;
return $ccss ;
}
/**
* Pop up the current request and save
*
* @since 3.0
*/
private function _popup_and_save( $ccss_type, $request_url )
{
if ( empty( $this->_summary[ 'ccss_type_history' ] ) ) {
$this->_summary[ 'ccss_type_history' ] = array() ;
}
$this->_summary[ 'ccss_type_history' ][ $ccss_type ] = $request_url ;
unset( $this->_summary[ 'queue' ][ $ccss_type ] ) ;
self::save_summary();
}
/**
* The critical css file for current page
*
* @since 2.3
* @access private
*/
private function _which_css()
{
$css = Utility::page_type() ;
$unique = false ;
// Check if in separate css type option
$separate_posttypes = Conf::val( Base::O_OPTM_CCSS_SEP_POSTTYPE ) ;
if ( ! empty( $separate_posttypes ) && in_array( $css, $separate_posttypes ) ) {
Debug2::debug( '[CSS] Hit separate posttype setting [type] ' . $css ) ;
$unique = true ;
}
$separate_uri = Conf::val( Base::O_OPTM_CCSS_SEP_URI ) ;
if ( ! empty( $separate_uri ) ) {
$result = Utility::str_hit_array( $_SERVER[ 'REQUEST_URI' ], $separate_uri ) ;
if ( $result ) {
Debug2::debug( '[CSS] Hit separate URI setting: ' . $result ) ;
$unique = true ;
}
}
if ( $unique ) {
$css .= '-' . md5( $_SERVER[ 'REQUEST_URI' ] ) ;
}
if ( $this->_separate_mobile_ccss() ) {
$css .= '.mobile' ;
}
return $css ;
}
/**
* Handle all request actions from main cls
*
* @since 2.3
* @access public
*/
public static function handler()
{
$instance = self::get_instance() ;
$type = Router::verify_type() ;
switch ( $type ) {
case self::TYPE_GENERATE_CRITICAL :
self::cron_ccss( true ) ;
break ;
default:
break ;
}
Admin::redirect() ;
}
}