Files
roi-theme/wp-content/plugins/thrive-visual-editor/inc/classes/lightspeed/class-css.php
root a22573bf0b Commit inicial - WordPress Análisis de Precios Unitarios
- WordPress core y plugins
- Tema Twenty Twenty-Four configurado
- Plugin allow-unfiltered-html.php simplificado
- .gitignore configurado para excluir wp-config.php y uploads

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 21:04:30 -06:00

470 lines
13 KiB
PHP
Executable File

<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\Lightspeed;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
/**
* Class Css
*
* @package TCB\Lightspeed
*/
class Css {
private static $instances = [];
private $styles_loaded = [];
private $ID;
private $post;
public static function get_instance( $post_id = 0 ) {
if ( empty( self::$instances[ $post_id ] ) ) {
self::$instances[ $post_id ] = new self( $post_id );
}
return self::$instances[ $post_id ];
}
public function __construct( $post_id ) {
$this->ID = (int) $post_id;
$this->post = get_post( $this->ID );
}
/**
* Css file is saved because we change it every time
*
* @param string $type
* @param bool $regenerate
*
* @return mixed|string
*/
public function get_css_filename( $type = '', $regenerate = false ) {
$meta_key = '_tve_' . $type . '_css_file';
$filename = get_post_meta( $this->ID, $meta_key, true );
if ( $regenerate ) {
$filename = 'tcb-' . $type . '-css-' . $this->ID . '-' . time() . '.css';
update_post_meta( $this->ID, $meta_key, $filename );
}
return $filename;
}
/**
* Return the handle used for enqueue-ing the style for the current post
*
* @param string $type
*
* @return string
*/
public function get_style_handle( $type = '' ) {
return sprintf( 'tcb-style-%s-%s-%s', $type, $this->post->post_type, $this->ID );
}
/**
* Save css either in post meta or in individual file
*
* @param string $type
* @param string $css
*/
public function save_optimized_css( $type = 'base', $css = '' ) {
$inline_css_meta_key = "_tve_{$type}_inline_css";
if ( ! is_string( $css ) ) {
$css = '';
}
/* we want to keep the encoded open/close tag characters (they might be part of background SVGs) */
$css = str_replace( [ '%3C', '%3E' ], [ '[tcb-encoded-open-tag]', '[tcb-encoded-close-tag]' ], $css );
$css = sanitize_text_field( $css );
/* restore the encoded tag characters */
$css = str_replace( [ '[tcb-encoded-open-tag]', '[tcb-encoded-close-tag]' ], [ '%3C', '%3E' ], $css );
$css = tve_minify_css( $css );
$css = static::compat( $css, $this->ID );
switch ( $this->get_css_location( $type ) ) {
case 'file':
if ( ! $this->write_css_file( $type, $css ) ) {
/* as fallback, if we can't write the file, save the css in meta */
update_post_meta( $this->ID, $inline_css_meta_key, $css );
}
break;
case 'head':
case 'footer':
default:
update_post_meta( $this->ID, $inline_css_meta_key, $css );
break;
}
/* if no css is being saved, then remove the lightspeed version */
update_post_meta( $this->ID, Main::OPTIMIZATION_VERSION_META, empty( $css ) ? 0 : Main::LIGHTSPEED_VERSION );
}
/**
* Depending on settings, load post style
* > if nothing is set, load the the whole flat styles file
* > if css optimization is on, load only specific styles, either from post meta or from individual file
*
* @param string $type
* @param array $deps
*/
public function load_optimized_style( $type, $deps = [] ) {
if ( empty( $this->styles_loaded[ $type ] ) ) {
if ( $this->should_load_optimized_styles() ) {
$location = $this->get_css_location( $type );
if ( $location === 'file' ) {
/* if by any chance the file doesn't exist, load the css in head */
$file = $this->get_css_filename( $type );
if ( empty( $file ) || ! file_exists( Main::upload_dir( 'basedir' ) . $file ) ) {
$location = 'head';
}
}
switch ( $location ) {
case 'file':
if ( did_action( 'wp_head' ) ) {
echo $this->get_optimized_styles( 'file', $type );
} else {
$this->enqueue_style( $type, $deps );
}
break;
case 'head':
case 'footer':
$hook = 'wp_' . $location;
if ( tve_post_is_landing_page( $this->ID ) || did_action( $hook ) ) {
echo $this->get_optimized_styles( 'inline', $type );
} else {
add_action( $hook, function () use ( $type ) {
echo $this->get_optimized_styles( 'inline', $type );
}, 0 );
}
break;
case 'inline':
default:
echo $this->get_optimized_styles( 'inline', $type );
}
} else {
/* load thrive flat only if this post needs it. */
if ( static::should_load_flat() || ! Main::is_enabled() || Main::requires_architect_assets( $this->ID ) ) {
static::enqueue_flat();
}
/**
* Action called when we're not optimizing the css, just so we can take any other action needed
*
* @param $type string type of css that we wanted to display
* @param $post \WP_Post post object with all the information
*/
do_action( 'tcb_lightspeed_load_unoptimized_styles', $type, $this->post );
}
}
$this->styles_loaded[ $type ] = true;
}
/**
* Enqueue style based on type
*
* @param string $type
* @param array $deps
*/
public function enqueue_style( $type = '', $deps = [] ) {
wp_enqueue_style( $this->get_style_handle( $type ), Main::upload_dir( 'baseurl' ) . $this->get_css_filename( $type ), $deps );
}
/**
* Enqueue thrive flat styles
*/
public static function enqueue_flat() {
tve_enqueue_style( tve_get_style_enqueue_id(), static::get_flat_url( false ) );
}
/**
* Return the inline css for the current post
*
* @param string $type
*
* @return mixed|void
*/
public function get_inline_css( $type = 'base' ) {
$inline_css = get_post_meta( $this->ID, "_tve_{$type}_inline_css", true );
if ( ! is_string( $inline_css ) ) {
$inline_css = '';
}
$inline_css = static::get_compat_css( $inline_css, $this->ID );
/**
* Filters the inline css for the current post.
*
* @param $inline_css string the css that we want to use
* @param $type string type of css in case we have multiple saves for a single post
* @param $ID int ID of the current post
*
* @return string
*/
return apply_filters( 'tcb_lightspeed_inline_css', $inline_css, $type, $this->ID );
}
/**
* Run compat function on CSS
*
* @param $inline_css
* @param $id
*
* @return string
*/
public static function get_compat_css( $inline_css, $id = 0 ) {
$inline_css = Fonts::parse_google_fonts( $inline_css );
$inline_css = tve_minify_css( $inline_css );
$inline_css = static::compat( $inline_css, $id );
return $inline_css;
}
/**
* Render styles node for the current post
*
* @param string $location
* @param string $type
* @param boolean $optimize_on_load
*/
public function get_optimized_styles( $location = 'inline', $type = 'base', $optimize_on_load = true ) {
switch ( $location ) {
case 'file':
$styles = sprintf(
"<link rel='stylesheet' id='%s' href='%s' type='text/css' media='all' />",
$this->get_style_handle( $type ),
Main::upload_dir( 'baseurl' ) . $this->get_css_filename( $type )
);
break;
case 'inline':
default:
$styles = static:: get_inline_style_node( $this->get_style_handle( $type ), $this->get_inline_css( $type ), $optimize_on_load );
break;
}
return $styles;
}
/**
* Build a style node for CSS
*
* @param $handle
* @param $css
* @param $should_optimize
*
* @return string
*/
public static function get_inline_style_node( $handle, $css, $should_optimize = true ) {
return sprintf( '<style type="text/css" id="%s" %s class="tcb-lightspeed-style">%s</style>',
$handle,
$should_optimize ? ' onLoad="typeof window.lightspeedOptimizeStylesheet === \'function\' && window.lightspeedOptimizeStylesheet()"' : '',
$css );
}
/**
* Always load flat file in the editor and when we set a specific param
*
* @return bool
*/
public static function should_load_flat() {
$should_load_flat = isset( $_GET['force-flat'] ) || is_editor_page_raw( true );
/**
* Allow plugins to short-circuit the loading of optimized assets on certain pages
*
* @param boolean $should_load_flat if true, we'll load thrive_flat.css on the current request
*/
return apply_filters( 'tcb_lightspeed_should_load_flat', $should_load_flat );
}
/**
* General check to see if we load flat or we load optimized styles
*
* @return bool
*/
public function should_load_optimized_styles() {
return Main::has_optimized_assets( $this->ID ) && ! static::should_load_flat();
}
/**
* Save css in individual file
*
* @param string $type
* @param string $css
*
* @return boolean
*/
public function write_css_file( $type, $css ) {
$styles_dir = Main::upload_dir( 'basedir' );
/* remove old style files for this post */
foreach ( scandir( $styles_dir ) as $file ) {
if ( strpos( $file, 'tcb-' . $type . '-css-' . $this->ID . '-' ) === 0 ) {
unlink( $styles_dir . $file );
}
}
return \TCB_Utils::write_file( $styles_dir . $this->get_css_filename( $type, true ), wp_unslash( $css ) );
}
/**
* Each post reads from specific stylesheets and save styles
*
* @return mixed|void
*/
public function get_styles_to_optimize() {
$default_styles = [
'tve_style_family_tve_flt',
'tve_landing_page_base_css',
'the_editor_no_theme',
];
/**
* Filters used to decide for each post what styles need optimization and from what stylesheets
*
* @param array $default_styles array
* @param int $post_id
*
* @return array
*/
return apply_filters( 'tcb_lightspeed_styles_to_optimize', $default_styles, $this->ID );
}
/**
* If in some cases we just need the inline flat style file
*
* @return string
*/
public static function inline_flat_style() {
return sprintf(
'<link rel="stylesheet" id="%s-css" href="%s" type="text/css" media="all" onLoad="typeof window.lightspeedOptimizeFlat === \'function\' && window.lightspeedOptimizeFlat(this)" />',
tve_get_style_enqueue_id(),
static::get_flat_url()
);
}
/**
* Get the location of thrive flat
*
* @param bool $include_version
*
* @return string
*/
public static function get_flat_url( $include_version = true ) {
return tve_editor_css( 'thrive_flat.css' ) . ( $include_version ? '?v=' . TVE_VERSION : '' );
}
/**
* Add specific browser rules in case they weren't included
*
* @param string $css
* @param int $id
*
* @return string
*/
public static function compat( $css, $id ) {
/* fit-content for chrome vs. -moz-fit-content for firefox */
$css = preg_replace_callback( '/[;|{]([^:]*):(-moz-)?fit-content( !important)?/m', static function ( $matches ) {
$pre = stripos( $matches[0], '-moz' ) === false ? '-moz-' : '';
$is_important = strpos( $matches[0], 'important' );
return $matches[0] . ';' . $matches[1] . ':' . $pre . 'fit-content' . ( $is_important ? ' !important' : '' );
}, $css );
$css = preg_replace_callback( '/inset:([^;]*);/m', static function ( $matches ) {
/* there are cases where 'inset:' comes with a space after ':' */
$matched_values = explode( ' ', ltrim( $matches[1] ) );
switch ( count( $matched_values ) ) {
case 4:
/* inset:2.4em 3em 3em 5em; - top right bottom left */
list( $top, $right, $bottom, $left ) = $matched_values;
break;
case 3:
/* inset:5% 15px 10px; - top left/right bottom */
$top = $matched_values[0];
$left = $matched_values[1];
$right = $matched_values[1];
$bottom = $matched_values[2];
break;
case 2:
list( $top, $right ) = $matched_values;
/* inset:4px 8px; - top/bottom left/right */
list( $bottom, $left ) = $matched_values;
break;
/* inset:10px; - applied to all edges */
case 1:
default:
$top = $bottom = $left = $right = $matches[1];
break;
}
return
'top:' . $top . ';' .
'right:' . $right . ';' .
'bottom:' . $bottom . ';' .
'left:' . $left . ';';
}, $css );
$css = preg_replace_callback( '/mask-\w*:[^;]*;/m', static function ( $matches ) {
return $matches[0] . '-webkit-' . $matches[0];
}, $css );
/**
* Filters the inline css for the current post.
*
* @param $css string the css that we want to use
* @param $id int content ID
*
* @return string
*/
return apply_filters( 'tcb_lightspeed_css_compat', $css, $id );
}
/**
* Where should we display the css
*
* @param $type
*
* @return string
*/
public function get_css_location( $type ) {
/* this will allow controlling the location of stored CSS directly on client sites by defining this constant */
$css_location = defined( 'TVE_CSS_LOCATION' ) ? TVE_CSS_LOCATION : 'inline';
/**
* Filter the location of the css for the current type and post
*
* @param string $location file|inline|head|footer
* @param string $type
* @param int $post_id
*/
return apply_filters( 'tcb_lightspeed_css_location', $css_location, $type, $this->ID );
}
}