: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
* This file defines Global Styles
* Themify_Global_Styles class register post type for Global Styles and load them
* @package Themify_Builder
* @subpackage Themify_Builder/classes
if (!class_exists('Themify_Global_Styles',false)) :
* The Global Styles class.
* This class register post type for Global Styles and load them.
* @package Themify_Builder
* @subpackage Themify_Builder/classes
final class Themify_Global_Styles {
const SLUG = 'tglobal_style';
* Post Type Global Styles Object.
* @var object $used_styles .
public static $used_styles = array();
public static $isGlobalEditPage = false;
public static function init() {
self::register_global_style();
add_filter('themify_post_types', array(__CLASS__, 'extend_post_types'));
add_filter('themify_exclude_CPT_for_sidebar', array(__CLASS__, 'extend_post_types'));
add_action('wp_ajax_tb_save_custom_global_style', array(__CLASS__, 'save_custom_global_style_ajaxify'), 10);
add_action('wp_ajax_tb_delete_global_style', array(__CLASS__, 'delete_global_style_ajaxify'), 10);
add_action('wp_ajax_tb_restore_global_style', array(__CLASS__, 'restore_global_style_ajaxify'), 10);
add_filter('themify_builder_post_types_support', array(__CLASS__, 'add_builder_support'));
add_action('admin_enqueue_scripts', array(__CLASS__, 'enqueue_admin_scripts'), 25);
add_action('wp_ajax_tb_save_as_new_global_style', array(__CLASS__, 'save_as_new_ajax'), 10);
add_action('wp_ajax_tb_update_global_style', array(__CLASS__, 'update_live'), 10);
add_action('wp_ajax_tb_get_gs_posts', array(__CLASS__, 'get_posts_ajax'), 10);
add_action('wp_ajax_tb_import_gs_posts_ajax', array(__CLASS__, 'import_posts_ajax'), 10);
add_action('wp_ajax_tb_get_gs_post', array(__CLASS__, 'wp_ajax_tb_get_gs_post'));
add_filter('template_include', array(__CLASS__, 'template_singular_global_style'));
add_filter('themify_builder_active_vars', array(__CLASS__, 'localize_data'));
* Register Global Style Custom Post Type
private static function register_global_style() {
if (!class_exists('CPT',false)) {
include_once THEMIFY_DIR . '/CPT.php';
// create a template custom post type
'post_type_name' => self::SLUG,
'singular' => __('Global Style', 'themify'),
'plural' => __('Global Styles', 'themify')
'supports' => array('title'),
'exclude_from_search' => true,
'show_in_nav_menus' => false,
// define the columns to appear on the admin edit screen
'title' => __('Title', 'themify')
// use "pages" icon for post type
$cpt->menu_icon('dashicons-admin-page');
* Includes this custom post to array of cpts managed by Themify
static function extend_post_types(array $types):array {
unset($types[self::SLUG]);
* Global Style for Template (Editor).
static function template_singular_global_style(?string $original_template):?string {
if (is_singular(self::SLUG)) {
self::$isGlobalEditPage = true;
$original_template = THEMIFY_BUILDER_TEMPLATES_DIR . '/template-builder-editor.php';
return $original_template;
* Handle Ajax request for add new Global Style
static function save_custom_global_style_ajaxify() {
check_ajax_referer('tf_nonce', 'nonce');
if ( ! current_user_can( 'edit_posts' ) ) {
$data = $response = array();
if (isset($_POST['form_data'])) {
parse_str($_POST['form_data'], $data);
$insert_post = self::add_new($data);
if (false === $insert_post) {
$response['status'] = 'failed';
$response['msg'] = __('Something went wrong', 'themify');
$response['status'] = 'success';
$response['url'] = $insert_post['url'] . '#builder_active';
* Handle Ajax request for save as new global style from a module
static function save_as_new_ajax() {
check_ajax_referer('tf_nonce', 'nonce');
if (empty($_POST['title']) || empty($_POST['type']) || empty($_POST['styles'])) {
if ( ! current_user_can( 'edit_posts' ) ) {
'style-name' => $_POST['title'],
'style-type' => $_POST['type'],
'styles' => json_decode(stripslashes_deep($_POST['styles']), true)
$insert_post = self::add_new($args);
if (false === $insert_post) {
$response['status'] = 'failed';
$response['msg'] = __('Something went wrong', 'themify');
$response['status'] = 'success';
$response['post_data'] = $insert_post;
$response['msg'] = __('Global Style has been saved!', 'themify');
* Handle Ajax request for updating a global style
static function update_live() {
check_ajax_referer('tf_nonce', 'nonce');
if (empty($_POST['bid']) || empty($_POST['data'])) {
if ( ! current_user_can( 'edit_post', $_POST['bid'] ) ) {
ThemifyBuilder_Data_Manager::save_data(stripslashes_deep($_POST['data']), $_POST['bid']);
$response['status'] = 'success';
* Handle Ajax request for get global style posts
static function get_posts_ajax() {
check_ajax_referer('tf_nonce', 'nonce');
if ( ! current_user_can( 'edit_posts' ) ) {
$loaded = !empty($_POST['loaded']) ? $_POST['loaded'] : array();
if (!empty($_POST['s'])) {
$args['search'] = sanitize_text_field($_POST['s']);
$globalStyles = self::get_global_styles($args);
wp_send_json($globalStyles);
* Insert new Global Style
* @return Mixed return false if fails or array of info about inserted post if success
public static function add_new($args, $action = 'new') {
if (empty($args['style-name'])) {
$name = sanitize_text_field($args['style-name']);
$type = sanitize_text_field($args['style-type']);
if ($type === 'subcolumn') {
} elseif ($type === 'subrow') {
$module_type = 'row' === $type || 'column' === $type ? 'text' : $type;
$rowStyling = $colStyling = $moduleStyling = '{}';
if ('text' === $module_type) {
$default['content_text'] = '<h1>Heading 1</h1><h2>Heading 2</h2><h3>Heading 3</h3><h4>Heading 4</h4><p>This is a sample Text module.</p>';
if (!empty($args['styles'])) {
if (is_array($args['styles']) && !empty($args['styles'][0])) {
$args['styles'] = $args['styles'][0];
$args['styles'] = !empty($args['styles']['cols']) ? $args['styles']['cols'][0] : array();
if ($type === 'column' || $type === 'row') {
$args['styles'] = isset($args['styling']) ? $args['styling'] : array();
$args['styles'] = !empty($args['styles']['modules']) ? $args['styles']['modules'][0]['mod_settings'] : array();
if (empty($args['styles'])) {
$rowStyling = json_encode($args['styles']);
$colStyling = json_encode($args['styles']);
$args['styles'] = array_merge($default, $args['styles']);
$moduleStyling = json_encode($args['styles']);
$moduleStyling = json_encode($default);
if ('row' === $type || 'column' === $type) {
$moduleStyling = json_encode($default);
$builder_content = '[{"element_id":"row' . $id . '","styling":' . $rowStyling . ',"cols":[{"element_id":"col' . $id . '","grid_class":"col-full","styling":' . $colStyling . ',"modules":[{"element_id":"mod' . $id . '","mod_name":"' . $module_type . '","mod_settings":' . $moduleStyling . '}]}]}]';
if ('import' === $action) {
update_post_meta($new_id, 'themify_global_style_type', $type);
$new_id = wp_insert_post(array(
'post_status' => 'publish',
'post_type' => self::SLUG,
'post_name' => !empty($args['slug']) ? $args['slug'] : '',
'themify_global_style_type' => $type,
'hide_page_title' => 'yes'
if (!is_wp_error($new_id)) {
ThemifyBuilder_Data_Manager::save_data($builder_content, $new_id);
if (empty($args['slug'])) {
$post_slug = 'tb_gs' . $new_id . substr(uniqid(), 0, 3);
'post_name' => $post_slug
$post_slug = $args['slug'];
if ('import' === $action) {
'builder_data' => ThemifyBuilder_Data_Manager::get_data($new_id),
'url' => get_post_permalink($new_id),
'data' => ThemifyBuilder_Data_Manager::get_data($new_id),
//there was an error in the post insertion,
* Add Builder support to Global Style post type.
* @param array $post_types
static function add_builder_support(array $post_types):array {
$post_types[self::SLUG] = self::SLUG;
* Return Global Styles page content
public static function page_content() {
$page_status = empty($_GET['status']) ? 'publish' : sanitize_text_field($_GET['status']);
'status' => $page_status,
'paged' => isset($_GET['pagenum']) ? absint($_GET['pagenum']) : 1
$search = !empty($_GET['s']) ? sanitize_text_field($_GET['s']) : '';
$args['search'] = $search;
$globalStyles = self::get_global_styles($args);
if (!empty($globalStyles)) {
themify_enque_style('themify-builder-style', THEMIFY_BUILDER_URI . '/css/themify-builder-style.css', null, THEMIFY_VERSION, '', true);
themify_enque_style('themify-builder-style-rtl', THEMIFY_BUILDER_URI . '/css/themify-builder-style-rtl.css', null, THEMIFY_VERSION, '', true);
Themify_Enqueue_Assets::loadMainScript();
Themify_Builder::footer_js();
themify_enque_script('themify-builder-js', THEMIFY_BUILDER_URI . '/js/themify-builder-script.js');
<div id="tb_admin_gs_container" class="wrap">
<!-- Just used for admin notice placement-->
<h2 style="display: none;"></h2>
<h3 class="page-title"><?php _e('Global Styles', 'themify'); ?></h3>
<a href="#tb_new_gs_form"
class="page-title-action tb_add_new_gs"><?php _e('Add new', 'themify') ?></a>
<a href="#" class="page-title-action tb_import_gs"><?php _e('Import from file', 'themify') ?></a>
<div class="tb_gs_admin_page_header">
<div class="tb_gs_post_status">
<a <?php echo 'publish' === $page_status ? 'class="tb_gs_active_page"' : ''; ?>
href="<?php echo admin_url('admin.php?page=themify-global-styles&status=publish'); ?>"><?php _e('Published', 'themify'); ?></a>
<a <?php echo 'trash' === $page_status ? 'class="tb_gs_active_page"' : ''; ?>
href="<?php echo admin_url('admin.php?page=themify-global-styles&status=trash'); ?>"><?php _e('Trash', 'themify'); ?></a>
<div class="tb_gs_admin_search">
<input type="text" name="s" value="<?php echo!empty($search) ? esc_attr($search) : ''; ?>">
<input type="hidden" name="page" value="themify-global-styles">
<input type="hidden" name="status" value="<?php echo esc_attr($page_status); ?>">
<button type="submit"><?php _e('Search', 'themify'); ?></button>
<?php if (!empty($search)): ?>
<h3><?php echo sprintf(__('Search Results for %s', 'themify'), $search); ?></h3>
<div class="tb_admin_gs_list" data-list="<?php echo esc_attr($page_status); ?>">
<?php if (!empty($globalStyles)): ?>
foreach ($globalStyles as $style) :
Themify_Builder_Stylesheet::enqueue_stylesheet(false, $style['id']);
<div class="tb_gs_element">
<div class="tb_gs_thumbnail_container">
<span class="tb_admin_gs_type"><?php echo $style['type']; ?></span>
<?php if ( current_user_can( 'delete_post', $style['id'] ) ) : ?>
<a href="#" class="tb_remove_gs tf_close" data-id="<?php echo $style['id']; ?>"></a>
<?php if ('publish' === $page_status): ?>
<a href="#" target="_blank" class="tb_gs_export tb_export" data-title="<?php echo esc_attr($style['title']); ?>" data-id="<?php echo $style['id']; ?>"><?php echo themify_get_icon('export', 'ti'); ?></a>
<?php if ( current_user_can( 'delete_post', $style['id'] ) ) : ?>
<a href="#" class="tb_gs_restore" data-id="<?php echo $style['id']; ?>"><?php echo themify_get_icon('back-left', 'ti'); ?></a>
<div data-builder="<?php echo esc_url($style['url']); ?>#builder_active"
class="tb_gs_preview_container">
<a href="<?php echo 'publish' === $page_status ? esc_url($style['url']) . '#builder_active' : '#'; ?>"
class="tb_gs_preview_overlay"></a>
<?php echo $style['preview']; ?>
<span class="tb_admin_gs_title"><?php echo $style['title']; ?></span>
<p class="wp-heading-inline"><?php _e('No Global Styles found.', 'themify'); ?></p>
<?php self::add_new_form(); ?>
<?php self::pagination(); ?>
Themify_Builder_Stylesheet::load_styles();
private static function pagination():void {
$count_posts = wp_count_posts(self::SLUG);
if (isset($count_posts->publish)){
$total = $count_posts->publish;
$num_of_pages = ceil($total / $limit);
$page_links = paginate_links(array(
'base' => add_query_arg('pagenum', '%#%'),
'prev_text' => __('«', 'text-domain'),
'next_text' => __('»', 'text-domain'),
'total' => $num_of_pages,
'current' => isset($_GET['pagenum']) ? absint($_GET['pagenum']) : 1
echo '<div class="tablenav"><div class="tablenav-pages">' , $page_links , '</div></div>';
* Create add new Global Style form
private static function add_new_form():void {
$excludes = array('page-break', 'divider', 'widget', 'widgetized', 'layout-part', 'plain-text');
$modules=Themify_Builder_Component_Module::load_modules();
<div id="tb_new_gs_form">
<div class="tb_gs_form_header">
<span class="tb_gs_form_title"><?php _e('New Style', 'themify'); ?></span>
<div class="tb_gs_form_body">
<form id="tb_admin_new_gs">
<div class="tb_gs_input_container">
<label for="style-name"><?php _e('Style Name', 'themify'); ?></label>
<input type="text" id="style-name" name="style-name">
<div class="tb_gs_input_container">
<label for="style-type"><?php _e('Type', 'themify'); ?></label>
<div class="tb_gs_type_container">
<select id="style-type" name="style-type">
<option value="row"><?php _e('Row', 'themify'); ?></option>
<option value="column"><?php _e('Column', 'themify'); ?></option>
<?php foreach ($modules as $slug => $module): ?>
<?php if (!in_array($slug, $excludes, true)): ?>
<option value="<?php echo $slug; ?>"><?php echo $module::get_module_name($slug); ?></option>
<div class="tb_gs_form_footer">