: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
<script id="tf_vars" data-no-optimize="1" data-noptimize="1" data-no-minify="1" data-cfasync="false" defer="defer" src="data:text/javascript;base64,<?php echo base64_encode($inline_js)?>"></script>
$wp_scripts->registered['themify-main-script']->extra['data'] = $inline_js=self::$wc_data=null;
do_action('tf_load_styles');
self::$localiztion = array();
* Copy of WP_Scripts::localize() except it uses JSON_UNESCAPED_SLASHES
* @documented in wp-includes/class.wp.scripts.php
public static function localize_script(string $handle,string $object_name,array $l10n) {
if ('jquery' === $handle) {
if (is_array($l10n) && isset($l10n['l10n_print_after'])) { // back compat, preserve the code in 'l10n_print_after' if present.
$after = $l10n['l10n_print_after'];
unset($l10n['l10n_print_after']);
foreach ((array) $l10n as $key => $value) {
if (!is_scalar($value)) {
$l10n[$key] = html_entity_decode((string) $value, ENT_QUOTES, 'UTF-8');
$script = "var $object_name = " . wp_json_encode($l10n, JSON_UNESCAPED_SLASHES) . ';';
$data = $wp_scripts->get_data($handle, 'data');
$script = "$data\n$script";
return $wp_scripts->add_data($handle, 'data', $script);
public static function before_footer() {
if (themify_is_woocommerce_active()) {
remove_action('wp_footer', 'wc_no_js');
if (self::$themeVersion !== null && !is_admin()) {
self::add_css('theme-style', THEME_URI . '/style.css', null, self::$themeVersion);
if (self::$mediaMaxWidth !== false) {
self::add_css('themify-media-queries', THEME_URI . '/media-queries.css', null, self::$themeVersion, '(max-width:' . self::$mediaMaxWidth . 'px)');
if (isset(self::$theme_css_support['wc'])) {
self::add_css('tf_theme_wc', THEME_URI . '/styles/wc/woocommerce.css', null, self::$themeVersion);
if (isset(self::$theme_css_support['wc_single_product']) && (isset(self::$wc_shortcode_type['product']) || is_product())) {
self::loadThemeWCStyleModule('single/product');
if ((isset(self::$theme_css_support['wc_account']) || isset(self::$theme_css_support['wc_register_form'])) && (isset(self::$wc_shortcode_type['account']) || is_account_page())) {
if (is_user_logged_in()) {
if(isset(self::$theme_css_support['wc_account'])){
self::loadThemeWCStyleModule('pages/account');
} elseif(isset(self::$theme_css_support['wc_register_form'])) {
self::loadThemeWCStyleModule('pages/register-form');
if (isset(self::$theme_css_support['wc_checkout']) && (isset(self::$wc_shortcode_type['checkout']) || is_checkout())) {
self::loadThemeWCStyleModule('pages/checkout');
if (isset(self::$theme_css_support['wc_cart']) && is_cart()) {
self::loadThemeWCStyleModule('pages/cart');
self::$wc_shortcode_type = null;
if (function_exists('themify_theme_enqueue_footer')) {
themify_theme_enqueue_footer();
if (is_rtl() && isset(self::$theme_css_support['rtl'])) {
self::add_css('theme-style-rtl', THEME_URI . '/rtl.css', null, self::$themeVersion);
themify_enqueue_framework_assets();
// Themify child base styling
$modified = filemtime(get_stylesheet_directory() . '/style.css');
if ($modified === false) {
self::add_css('theme-style-child', get_stylesheet_uri(), null, self::$themeVersion . $modified);
$custom_css = get_template_directory() . '/custom_style.css';
if (is_file($custom_css)) {
$modified = filemtime($custom_css);
if ($modified === false) {
self::add_css('custom-style', THEME_URI . '/custom_style.css', null, THEMIFY_VERSION . $modified);
if (is_admin_bar_showing() && is_file(self::$THEME_CSS_MODULES_DIR . 'admin-bar.css')) {
self::loadThemeStyleModule('admin-bar', false, true);
if (class_exists('Themify_Builder',false) && Themify_Builder_Model::is_front_builder_activate() === true && is_file(self::$THEME_CSS_MODULES_DIR . 'builder-active.css')) {
self::loadThemeStyleModule('builder-active', false, true);
public static function wp_footer() {
if (!empty(self::$css['in_footer'])) {
foreach (self::$css['in_footer'] as $k => $v) {
$m = isset($v['m']) ? ' media="' . $v['m'] . '"' : '';
$href .= strpos($href, '?') === false ? '?' : '&';
$href .= 'ver=' . $v['v'];
<link rel="preload" href="<?php echo $href ?>" as="style"<?php echo $m ?>><link id="<?php echo $k ?>-css" rel="stylesheet" href="<?php echo $href ?>"<?php echo $m ?>>
if (self::$themeVersion !== null) {
echo "\n\n", themify_get('setting-footer_html', '', true);
add_action('shutdown',array(__CLASS__,'buffer_end'),-99999999);
public static function buffer_end():void{
private static function getBuffer(string $body):string{
$exist = $hasFonts = false;
self::$css = apply_filters('themify_main_concate', self::$css);
self::$css['mobile_concate'] = apply_filters('themify_mobile_concate', self::$css['mobile_concate']);
foreach (self::$css as $k => $v) {
if ($k !== 'in_footer' && $k !== 'mobile_concate') {
if (isset(self::$css['woocommerce-general']) && strpos($body, 'star-rating') !== false) {
self::addPreLoadMedia(dirname(self::$css['woocommerce-general']['s'],2) . '/fonts/star.woff', 'preload', 'font', null, null, 'high');
$isDevMode=themify_is_dev_mode() && (!class_exists('Themify_Builder_Model',false) || !Themify_Builder_Model::is_front_builder_activate());
if(self::$concateFile===null){
$key .= implode('', array_keys(self::$css['mobile_concate']));
self::$concateFile .= 'themify-' . $key . '.css';
$exist = Themify_Filesystem::is_file(self::$concateFile);
$regenerate = !apply_filters('themify_concate_css', !$isDevMode, self::$concateFile); //opposite logic for backward compatibility
$isDeleted = Themify_Filesystem::is_file(self::$concateFile . 'del');
$regenerate = $regenerate === true || $isDeleted === true;
if ($regenerate === true) {
if ($isDeleted === true) {
Themify_Filesystem::delete(self::$concateFile . 'del','f');
// Add theme and fw version
$replace = array(THEMIFY_URI, home_url());
if (self::$themeVersion !== null) {
$theme_name = (is_child_theme() ? $theme->parent()->Name : $theme->display('Name')) . ' ' . self::$themeVersion . ' ';
$str = PHP_EOL . '/* ' . $theme_name . 'framework ' . THEMIFY_VERSION . ' */' . $str . PHP_EOL;
$str = '@charset "UTF-8";' . $str;
if($isDevMode===true && self::$themeVersion!==null && (self::$concateFile===null || themify_is_concate_disabled())){
foreach (self::$css as $k => $v) {
if ($k !== 'in_footer' && $k !== 'mobile_concate') {
$content = $key !== ''? Themify_Filesystem::get_file_content($v['s']) : null;
$content = strtr($content,
"url('fonts/"=>"url({'$dir}/fonts/",
"url('images/"=>"url('{$dir}/images/",
"url(fonts/"=>"url({$dir}/fonts/",
"url(images/"=>"url({$dir}/images/"
if ($k === 'woocommerce-general') {
$content = str_replace('@font-face{', '@font-face{font-display:swap;', $content);
$content = '@media ' . $v['m'] . '{' . PHP_EOL . $content . PHP_EOL . '}';
$str .= PHP_EOL . '/*' . str_replace($replace, '', $v['s']) . '*/' . PHP_EOL . $content;
elseif (!Themify_Filesystem::get_file_content($v['s'], true)) {
if (isset(self::$preLoadMedia[$k])) {
unset(self::$preLoadMedia[$k]);
$media = isset($v['m'])?' media="'.$v['m'].'"':'';
$output .= '<link rel="preload" href="' . $v['s'] . '?ver=' . $v['v'] . '" as="style"'.$media.'>' . "\n" . '<link id="' . $k . '-css" rel="stylesheet" href="' . $v['s'] . '?ver=' . $v['v'] . '"'.$media.'>' . "\n";
if (!empty(self::$css['mobile_concate'])) {
$media = 'screen and (max-width:' . self::$mobileMenuActive . 'px)';
$mobileStr = PHP_EOL . '/* START MOBILE MENU CSS */' . PHP_EOL . '@media ' . $media . '{';
foreach (self::$css['mobile_concate'] as $k => $v) {
$content = $key !== '' ? Themify_Filesystem::get_file_content($v) : null;
$mobileStr .= PHP_EOL . '/*' . str_replace($replace, '', $v) . '*/' . PHP_EOL . trim($content);
if (isset(self::$preLoadMedia[$k])) {
unset(self::$preLoadMedia[$k]);
$output .= '<link rel="preload" href="' . $v . '?ver=' . self::$themeVersion . '" media="' . $media . '" as="style"><link id="tf-mobile-' . $k . '-css" rel="stylesheet" href="' . $v . '?ver=' . self::$themeVersion . '" media="' . $media . '">';
unset(self::$css['mobile_concate'], $content);
$mobileStr .= PHP_EOL . '}' . PHP_EOL . '/* END MOBILE MENU CSS */';
if ($key !== '' && (empty(self::$concateFile) || (($regenerate === true || !Themify_Filesystem::is_file(self::$concateFile))))) {
if(!file_put_contents(self::$concateFile.'tmp', $str) || Themify_Filesystem::rename(self::$concateFile.'tmp',self::$concateFile)===false){//tmp file need because file_put_contents isn't atomic(another process can read not ready file),locking file(LOCK_EX) is slow,that is why we are using rename(it is atomic)
Themify_Filesystem::delete(self::$concateFile.'tmp','f');
if ( true === apply_filters( 'themify_enable_lazyload', true ) ) {
$body = themify_make_lazy($body);
$path = self::getPreLoad();
if (self::$disableGoogleFontsLoad === null) {
$path.= self::loadGoogleFonts();
$upload_dir = themify_upload_dir();
$href = str_replace($upload_dir['basedir'], $upload_dir['baseurl'], self::$concateFile);
$path .= '<link rel="preload" fetchpriority="high" href="' . $href . '" as="style"><link fetchpriority="high" id="themify_concate-css" rel="stylesheet" href="' . $href . '">';
$path .= $output.'<style id="themify_concate-css"></style>';//need when dev mode is enabled
self::$concateFile = null;
if (strpos($body, 'fonts.googleapis.com') !== false) {
$path .= '<link rel="dns-prefetch" href="https://fonts.gstatic.com">';
if (strpos($body, '//www.youtube.com/embed') !== false) {
$path .= '<link rel="preconnect" href="https://www.youtube.com">';
if (strpos($body, '//player.vimeo.com/video') !== false) {
$path .= '<link rel="preconnect" href="https://player.vimeo.com">';
if (themify_get('setting-ga_m_id', '', true) !== '' || strpos($body, 'googletagmanager.com') !== false) {
$path .= '<link rel="preconnect" href="https://www.google-analytics.com">';
if (self::$themeVersion !== null && ($custom_css = themify_get('setting-custom_css', false, true))) {
$path.='<!--custom css:start--><style>'. $custom_css.'</style><!--custom css:end-->';
self::$css = self::$googleFonts = self::$preLoadMedia = $rep=array();
if(strpos($body,'<!--tf_svg_holder-->')!==false){
$rep['<!--tf_svg_holder-->']=self::loadIcons(false);
$rep['</body>']=self::loadIcons(false).'</body>';
if(strpos($body,'<!--tf_css_position-->')!==false){
$rep['<!--tf_css_position-->']=$path;
$rep['</head>']=$path.'</head>';
return strtr($body,$rep);
public static function loadIcons(bool $echo = true) {
$fonts = Themify_Icon_Font::get_used_icons();
$svg = '<svg id="tf_svg" style="display:none"><defs>';
foreach ($fonts as $k => $v) {
$w = isset($v['vw']) ? $v['vw'] : '32';
$h = isset($v['vh']) ? $v['vh'] : '32';
$p = isset($v['is_fontello']) ? ' transform="matrix(1 0 0 -1 0 ' . $h . ')"' : '';
$svg .= '<symbol id="tf-' . $k . '" viewBox="0 0 ' . $w . ' ' . $h . '"><path d="' . $v['p'] . '"' . $p . '/></symbol>';
$st .= '.tf_fa.tf-' . $k . '{width:' . $v['w'] . 'em}';
$svg .= '<style id="tf_fonts_style">' . $st . '</style>';
private static function get_webp_support():string {
return PHP_EOL . '#BEGIN_WEBP_OUTPUT_BY_THEMIFY
# serves a .webp image instead of jpg/png
RewriteCond %{HTTP_ACCEPT} image/webp
RewriteCond %{REQUEST_FILENAME} ^(.+)\.(jpe?g|jpg|png|gif)$
RewriteRule ^(.+)\.(jpe?g|jpg|png|gif)$ $1.webp [T=image/webp,E=accept:1]
Header append Vary Accept env=REQUEST_image
#END_WEBP_OUTPUT_BY_THEMIFY
private static function get_gzip_htaccess():string {
return PHP_EOL . '#BEGIN_GZIP_OUTPUT_BY_THEMIFY
AddType "text/javascript" .gz
AddType "image/svg+xml" .gz
AddType "application/json" .gz
# Serve pre-compressed gzip assets
RewriteCond %{HTTP:Accept-Encoding} gzip
RewriteCond %{REQUEST_FILENAME}.gz -f
RewriteRule ^(.*)$ $1.gz [QSA,L]
#END_GZIP_OUTPUT_BY_THEMIFY
private static function get_mod_rewrite():string {
return PHP_EOL . '#BEGIN_GZIP_COMPRESSION_BY_THEMIFY
AddType application/x-gzip .gz .tgz
AddEncoding x-gzip .gz .tgz
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/x-javascript
AddOutputFilterByType DEFLATE application/x-httpd-php
AddOutputFilterByType DEFLATE application/x-httpd-fastphp
AddOutputFilterByType DEFLATE image/svg+xml
AddOutputFilterByType DEFLATE image/svg
# Make sure proxies don\'t deliver the wrong content
Header append Vary User-Agent env=!dont-vary
ExpiresByType image/jpg "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/gif "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/webp "access plus 1 year"
ExpiresByType image/apng "access plus 1 year"
ExpiresByType image/svg+xml "access plus 1 year"
ExpiresByType image/svg "access plus 1 year"
ExpiresByType image/ico "access plus 1 year"
ExpiresByType image/x-icon "access plus 1 year"
ExpiresByType application/gzip "access plus 1 year"
ExpiresByType text/css "access plus 1 year"
ExpiresByType text/x-component "access plus 1 year"
ExpiresByType text/javascript "access plus 1 year"
ExpiresByType text/x-javascript "access plus 1 year"
ExpiresByType application/pdf "access plus 1 month"
ExpiresByType application/javascript "access plus 1 year"
ExpiresByType application/x-javascript "access plus 1 year"
ExpiresByType application/json "access plus 1 year"
ExpiresByType application/ld+json "access plus 1 year"
ExpiresByType application/xml "access plus 0 seconds"
ExpiresByType text/xml "access plus 0 seconds"
ExpiresByType application/x-web-app-manifest+json "access plus 0 seconds"
ExpiresByType text/cache-manifest "access plus 0 seconds"
ExpiresByType audio/ogg "access plus 4 months"
ExpiresByType audio/mp3 "access plus 4 months"
ExpiresByType video/mp4 "access plus 4 months"
ExpiresByType video/ogg "access plus 4 months"
ExpiresByType video/webm "access plus 4 months"
ExpiresByType application/atom+xml "access plus 1 day"
ExpiresByType application/rss+xml "access plus 1 day"
ExpiresByType application/font-woff "access plus 1 year"
ExpiresByType application/vnd.ms-fontobject "access plus 1 year"
ExpiresByType application/x-font-ttf "access plus 1 year"
ExpiresByType font/opentype "access plus 1 year"
ExpiresByType font/woff "access plus 1 year"
ExpiresByType font/woff2 "access plus 1 year"
ExpiresByType font/application/x-font-woff2 "access plus 1 year"
ExpiresByType application/font-woff2 "access plus 1 year"
#Alternative caching using Apache`s "mod_headers", if it`s installed.
#Caching of common files - ENABLED
<FilesMatch "\.(pdf|xls|rar|zip|tgz|tar|html|txt)$">
Header set Cache-Control "max-age=2628000, public"
<FilesMatch "\.(jpg|jpeg|gif|png|webp|apng|svg|js|mjs|css|mp3|ogg|mpe?g|avi|gz|woff|woff2|eot|ttf|mp4|doc|ico|ogv|svgz|otf|rss|ppt|mid|midi|wav|bmp|rtf|json|jsonld)$">
Header set Cache-Control "max-age=31536000, public"
Header set Connection keep-alive
mod_gzip_item_include file \.(html?|txt|css|js|php|pl)$
mod_gzip_item_include handler ^cgi-script$
mod_gzip_item_include mime ^text/.*
mod_gzip_item_include mime ^application/x-javascript.*
mod_gzip_item_exclude mime ^image/.*
mod_gzip_item_exclude rspheader ^Content-Encoding:.*gzip.*
# If your server don`t support ETags deactivate with "None" (and remove header)
#END_GZIP_COMPRESSION_BY_THEMIFY' . PHP_EOL;
public static function rewrite_htaccess($gzip = false, $webp = false,$browser=false) {