Create New Item
Item Type
File
Folder
Item Name
Search file in folder and subfolders...
Are you sure want to rename?
File Manager
/
wp-content
/
plugins
/
bkp
/
jet-menu
/
includes
/
modules
/
dynamic-css
:
cherry-x-dynamic-css.php
Advanced Search
Upload
New Item
Settings
Back
Back Up
Advanced Editor
Save
<?php /** * Module allows to work with dynamically generated CSS. * * Version: 1.0.1 */ // If this file is called directly, abort. if ( ! defined( 'WPINC' ) ) { die; } if ( ! class_exists( 'CX_Dynamic_CSS' ) ) { /** * Dynamic CSS main class */ class CX_Dynamic_CSS { /** * Module arguments * * @var array */ public $args = array(); /** * Holder for processed variables array * * @var array */ public $variables = null; /** * Variable pattern * * @var array */ public $var_pattern = '/\$(([-_a-zA-Z0-9]+)(\[[\'\"]*([-_a-zA-Z0-9]+)[\'\"]*\])?({([a-z%]+)})?)/'; /** * Function pattern * * @var array */ public $func_pattern = '/@(([a-zA-Z_]+)\(([^@\)]*)?\))/'; /** * Collector instance holder * * @since 1.0.0 * @var object */ public $collector = null; /** * Reserved words list * * @since 1.0.0 * @var array */ public $css_reserved = array( 'media', 'supports', ); /** * Constructor for the module */ function __construct( $args ) { $this->args = wp_parse_args( $args, array( 'prefix' => 'blank', 'type' => 'theme_mod', 'parent_handles' => array( 'css' => false, 'js' => false, ), 'single' => true, 'css_files' => null, 'options_cb' => false, 'options' => array(), ) ); $this->init_dynamic_css(); $this->init_collector(); } /** * Initialize dynamic CSS with fallback compatibility. * * @since 1.0.0 * @return void */ public function init_dynamic_css() { $handle = isset( $this->args['parent_handles']['css'] ) ? $this->args['parent_handles']['css'] : false; /** * Not actual for now, required only for fallback compatibility. */ if ( ! $handle ) { add_action( 'wp_head', array( $this, 'print_inline_css' ), 99 ); } else { add_action( 'wp_enqueue_scripts', array( $this, 'add_inline_css' ), 99 ); } } /** * Adds inline CSS into queue * * @since 1.0.0 * @return void */ public function add_inline_css() { $handle = isset( $this->args['parent_handles']['css'] ) ? $this->args['parent_handles']['css'] : false; wp_add_inline_style( $handle, $this->get_inline_css() ); } /** * Initialize CSS collector class * * @since 1.0.0 * @return bool */ public function init_collector() { if ( null !== $this->collector ) { return true; } require_once 'inc/class-cx-dynamic-css-collector.php'; ob_start(); include 'assets/min/cx-css-collector.min.js'; $handler = ob_get_clean(); $handle = isset( $this->args['parent_handles']['js'] ) ? $this->args['parent_handles']['js'] : null; $this->collector = new CX_Dynamic_CSS_Collector( $handler, $handle ); add_action( 'wp_footer', array( $this->collector, 'print_style' ), 11 ); add_action( 'wp_footer', array( $this->collector, 'add_js_handler' ), 11 ); return true; } /** * Add new style to collector * * @since 1.0.0 * @param string $selector CSS selector to add styles for. * @param array $style Styles array to add. * @param array $media Media breakpoints. * @return void */ public function add_style( $selector, $style = array(), $media = array() ) { if ( ! $selector ) { return; } $this->collector->add_style( $selector, $style, $media ); } /** * Fix customizer preview variables. * * @param [type] $variables [description] * @return [type] [description] */ public function fix_customizer_preview_vars( $variables ) { $result = array(); foreach ( $variables as $name => $value ) { $result[ $name ] = get_theme_mod( $name ); } return $result; } /** * Get CSS variables into array * * @since 1.0.0 * @return array dynamic CSS variables */ public function get_css_varaibles() { if ( null !== $this->variables ) { return $this->variables; } if ( ! empty( $this->args['options_cb'] ) && is_callable( $this->args['options_cb'] ) ) { $this->variables = call_user_func( $this->args['options_cb'] ); if ( 'theme_mod' === $this->args['type'] && is_customize_preview() ) { $this->variables = $this->fix_customizer_preview_vars( $this->variables ); } /** * Filter result variables list with values * * @since 1.0.0 * @param array $variables default variables list. * @param array $this->args module arguments. */ $this->variables = apply_filters( 'cx_dynamic_css/variables', $this->variables, $this->args ); return $this->variables; } $variables = $this->get_standard_vars(); $var_list = ! empty( $this->args['options'] ) ? $this->args['options'] : array(); /** * Filter options names list to use it as varaibles * * @since 1.0.0 * @param array $var_list default variables list. * @param array $this->args module arguments. */ $var_list = apply_filters( 'cx_dynamic_css/var_list', $var_list, $this->args ); if ( empty( $var_list ) ) { return $variables; } $custom_vars = array(); foreach ( $var_list as $var ) { $custom_vars[ $var ] = $this->get_setting( $var ); } $variables = array_merge( $variables, $custom_vars ); /** * Filter result variables list with values * * @since 1.0.0 * @param array $variables default variables list. * @param array $this->args module arguments. */ $this->variables = apply_filters( 'cx_dynamic_css/variables', $variables, $this->args ); return $this->variables; } /** * Get current setting by name * * @since 1.0.0 * @return mixed */ public function get_setting( $name ) { $type = $this->args['type']; if ( 'theme_mod' == $type ) { $setting = get_theme_mod( $name ); return $setting; } if ( true != $this->args['single'] ) { $setting = get_option( $name ); return $setting; } $settings = get_option( $this->args['prefix'] ); if ( ! empty( $settings ) && isset( $settings[ $name ] ) ) { return $settings[ $name ]; } return false; } /** * Get standard WordPress variables from customizer - header image, background image etc. * * @since 1.0.0 * @return array */ public function get_standard_vars() { $standard_vars = array( 'header_image', 'background_image', 'background_repeat', 'background_position_x', 'background_attachment', ); $result = array(); foreach ( $standard_vars as $var ) { $result[ $var ] = get_theme_mod( $var ); } return $result; } /** * Get available functions into array * * @since 1.0.0 * @return array dynamic CSS variables */ public function get_css_functions() { require_once 'inc/class-cx-dynamic-css-utilities.php'; $utilities = CX_Dynamic_CSS_Utilities::get_instance(); $func_list = array( 'darken' => array( $utilities, 'color_darken' ), 'lighten' => array( $utilities, 'color_lighten' ), 'contrast' => array( $utilities, 'color_contrast' ), 'alpha' => array( $utilities, 'color_alpha' ), 'background' => array( $utilities, 'background_css' ), 'background_url' => array( $utilities, 'background_url' ), 'typography' => array( $utilities, 'get_typography_css' ), 'box' => array( $utilities, 'get_box_model_css' ), 'emph' => array( $utilities, 'element_emphasis' ), 'font_family' => array( $utilities, 'typography_font_family' ), 'font_size' => array( $utilities, 'typography_size' ), 'container_compare' => array( $utilities, 'container_width_compare' ), 'sum' => array( $utilities, 'simple_sum' ), 'diff' => array( $utilities, 'simple_diff' ), 'menu_toogle_endpoint' => array( $utilities, 'menu_toogle_endpoint' ), ); /** * Filter available CSS functions list * * @since 1.0.0 * @param array $func_list default functions list. * @param array $this->args module arguments. */ return apply_filters( 'cx_dynamic_css/func_list', $func_list, $this->args ); } /** * Parse CSS string and replasce varaibles and functions * * @since 1.0.0 * @param [type] $css CSS to parse. * @return string */ public function parse( $css ) { $replce_vars = preg_replace_callback( $this->var_pattern, array( $this, 'replace_vars' ), $css ); $replace_func = preg_replace_callback( $this->func_pattern, array( $this, 'replace_func' ), $replce_vars ); $result = preg_replace( '/\t|\r|\n|\s{2,}/', '', $replace_func ); return $result; } /** * Returns complied dynamic CSS string. * * @since 1.0.0 * @return string|bool false */ public function get_inline_css() { if ( ! $this->args['css_files'] ) { return false; } if ( ! is_array( $this->args['css_files'] ) ) { $this->args['css_files'] = array( $this->args['css_files'] ); } /** * Filter CSS reserved words list * * @since 1.0.0 * @var array */ $this->css_reserved = apply_filters( 'cx_dynamic_css/reserved_words_list', $this->css_reserved ); ob_start(); foreach ( $this->args['css_files'] as $file ) { if ( ! file_exists( $file ) ) { continue; } include $file; } /** * Allow to include custom dynamic CSS files * * @since 1.0.0 * @param array $this->args Current dynamic CSS arguments array. */ do_action( 'cx_dynamic_css/include_custom_files', $this->args ); $css = ob_get_clean(); $parsed_css = $this->parse( $css ); /** * Filter parsed dynamic CSS * * @since 1.0.0 * @param string $parsed_css default functions list. * @param array $this->args module arguments. */ $parsed_css = apply_filters( 'cx_dynamic_css/parsed_styles', $parsed_css, $this->args ); return $parsed_css; } /** * Print inline CSS after current theme stylesheet * * @since 1.0.0 * @return void|bool false */ public function print_inline_css() { $parsed_css = $this->get_inline_css(); if ( empty( $parsed_css ) ) { return false; } printf( '<style type="text/css">%s</style>', $parsed_css ); } /** * Callback function to replace CSS vars * * @since 1.0.0 * @param [string] $matches founded vars. */ function replace_vars( $matches ) { $not_found = '/* Variable not found */'; // check if variable name found if ( empty( $matches[2] ) ) { return $not_found; } $variables = $this->get_css_varaibles(); // check if var exists if ( ! array_key_exists( $matches[2], $variables ) ) { return $not_found; } $val = $variables[ $matches[2] ]; $maybe_units = ''; // check if we need to add units after value if ( ! empty( $matches[6] ) ) { $maybe_units = $matches[6]; } // check if we search for array val if ( ! empty( $matches[4] ) && is_array( $val ) && isset( $val[ $matches[4] ] ) ) { return $val[ $matches[4] ] . $maybe_units; } if ( ! is_array( $val ) ) { return $val . $maybe_units; } else { return $matches[0]; } } /** * Callback function to replace CSS functions * * @since 1.0.0 * @param [string] $matches founded dunction. */ function replace_func( $matches ) { $not_found = '/* Function does not exist */'; // check if functions name found if ( empty( $matches[2] ) ) { return $not_found; } $functions = $this->get_css_functions(); // check if function exists and is not CSS-reserved word if ( ! array_key_exists( $matches[2], $functions ) ) { if ( is_array( $this->css_reserved ) && in_array( $matches[2], $this->css_reserved ) ) { return $matches[0]; } else { return $not_found; } } $function = $functions[ $matches[2] ]; $args = isset( $matches[3] ) ? $matches[3] : array(); if ( empty( $args ) ) { $result = call_user_func( $function ); return $result; } if ( 'font_family' == $matches[2] ) { $result = call_user_func( $function, $args ); return $result; } $args = str_replace( ' ', '', $args ); $args = explode( ',', $args ); if ( ! is_callable( $function ) ) { return $not_found; } if ( ! empty( $args ) ) { $args = array_map( array( $this, 'prepare_args' ), $args ); } $result = call_user_func_array( $function, $args ); return $result; } /** * Filter user function arguments * * @since 1.0.0 */ function prepare_args( $item ) { $name = str_replace( '$', '', $item ); $variables = $this->get_css_varaibles(); if ( ! array_key_exists( $name, $variables ) ) { return $item; } return $variables[ $name ]; } } }