: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
defined('ABSPATH') || exit;
* Description: Display any available widgets
class TB_Widget_Module extends Themify_Builder_Component_Module {
public static function init():void {
add_action('wp_ajax_tb_get_widget_items', array(__CLASS__, 'get_items'));
add_action('wp_ajax_module_widget_get_form', array(__CLASS__, 'widget_get_form'), 10);
add_action('tb_data_before_save', array(__CLASS__, 'before_builder_save'), 10, 2);
public static function get_module_name():string {
return __('Widget', 'themify');
public static function get_items() {
global $wp_widget_factory;
if (!empty($wp_widget_factory->widgets)) {
foreach ($wp_widget_factory->widgets as $widget) {
$class = get_class($widget);
$result[$class] = array('n' => $widget->name, 'b' => $widget->id_base);
if (!empty($widget->widget_options['description'])) {
$result[$class]['d'] = $widget->widget_options['description'];
$columns = array_column($result, 'n');
array_multisort($columns, SORT_ASC, $result);
die(json_encode($result));
* Get a widget's registered key in $wp_widget_factory from its classname.
* register_widget() works with WP_Widget instances too, in such cases the
* widget's key is a hashed string.
public static function get_widget_factory_name($classname) {
if (empty($classname) || !class_exists($classname,false)) {
global $wp_widget_factory;
if (isset($wp_widget_factory->widgets[$classname])) {
foreach ($wp_widget_factory->widgets as $key => $widget) {
if ($widget instanceof WP_Widget && get_class($widget) === $classname) {
public static function widget_get_form() {
check_ajax_referer('tf_nonce', 'nonce');
global $wp_widget_factory;
require_once ABSPATH . 'wp-admin/includes/widgets.php';
$widget_class = $_POST['load_class'];
if ($widget_class == '') {
$widget_class = str_replace('\\\\', '\\', $widget_class);
$instance = !empty($_POST['widget_instance']) && $_POST['widget_instance'] !== 'null' ? $_POST['widget_instance'] : array();
if ( is_string( $instance ) ) {
$instance = json_decode( $instance, true );
} catch( Exception $e ) {
$instance = TB_Widget_Module::sanitize_widget_instance($instance);
$widget_key = self::get_widget_factory_name($widget_class);
$widget = $wp_widget_factory->widgets[$widget_key];
$widget->number = next_widget_id_number($_POST['id_base']);
$instance = stripslashes_deep($instance);
if (empty($_POST['tpl_loaded']) && method_exists($widget, 'render_control_template_scripts')) {
require_once ABSPATH . WPINC . '/media-template.php';
$widget->render_control_template_scripts();
if ($widget->id_base !== 'text') {
wp_print_media_templates();
$template = ob_get_contents();
$widget->enqueue_admin_scripts();
$type = str_replace('_', '-', $widget->id_base) . '-widget';
if ($widget->id_base === 'text') {
wp_enqueue_script($type);
if (isset($wp_scripts->registered[$type])) {
$script = $wp_scripts->registered[$type];
if ($widget->id_base !== 'text' && !empty($wp_scripts->registered[$type]->deps)) {
foreach ($wp_scripts->registered[$type]->deps as $deps) {
$src[] = array('src' => self::resolve_script_path($wp_scripts->registered[$deps]->src));
$src[] = array('src' => self::resolve_script_path($script->src), 'extra' => !empty($script->extra) ? $script->extra : '');
$widget->form($instance);
do_action('in_widget_form', $widget, null, $instance);
$base_name = 'widget-' . $widget->id_base . '\[' . $widget->number . '\]';
$form = preg_replace("/{$base_name}/", '', $form); // remove extra names
$form = str_replace(array(
), '', $form); // remove extra [ & ] characters
* The widget-id is not used to save widget data, it is however needed for compatibility
* with how core renders the module forms.
$form = '<div class="widget open">
<div class="widget-inside">
<div class="widget-content">'
<input type="hidden" class="id_base" name="id_base" value="' . esc_attr($widget->id_base) . '" />
<input type="hidden" class="widget-id" name="widget-id" value="w_' . time() . '" />
<input type="hidden" class="widget-class" name="widget-class" value="' . $widget_class . '" />
private static function resolve_script_path($src) {
$content_url = defined('WP_CONTENT_URL') ? WP_CONTENT_URL : '';
if (!preg_match('|^(https?:)?//|', $src) && !( $content_url && 0 === strpos($src, $content_url) )) {
if (!($guessurl = site_url() )) {
$guessurl = wp_guess_url();
* Sanitize keys for widget fields
* This is required to provide backward compatibility with how widget data was saved.
public static function sanitize_widget_instance($instance) {
if (is_array($instance)) {
foreach ($instance as $key => $val) {
preg_match('/.*\[\d\]\[(.*)\]/', $key, $matches);
if (isset($matches[1])) {
$instance[$matches[1]] = $val;
* Render plain content for static content.
public static function get_static_content(array $module):string {
if (!isset($module['mod_settings'])) {
return isset($module['mod_settings']['class_widget']) && 'Themify_Social_Links' === $module['mod_settings']['class_widget']?self::social_links_plain_content():parent::get_static_content($module);
private static function social_links_plain_content():string {
if (function_exists('themify_get_data')){
$data = themify_get_data();
$field_ids = isset($data[$pre . 'field_ids']) ? json_decode($data[$pre . 'field_ids']) : false;
if (is_array($field_ids) || is_object($field_ids)) {
$is_exist = function_exists('icl_t');
foreach ($field_ids as $fid) {
$title_name = $pre . 'title_' . $fid;
$title_val = icl_t('Themify', $title_name, $data[$title_name]);
$title_val = isset($data[$title_name]) ? $data[$title_name] : '';
$link_name = $pre . 'link_' . $fid;
$link_val = isset($data[$link_name]) ? trim($data[$link_name]) : '';
$out .= sprintf('<li><a href="%s">%s</a></li>', esc_url($link_val), $title_val);
* Before Builder saves data, find all Widget modules and call
* WP_Widget::update() method on widget instance data.
public static function before_builder_save(array $builder_data, $post_id) {
if (!empty($builder_data)) {
if (strpos(json_encode($builder_data), 'class_widget') !== false) {
foreach ($builder_data as $row_index => $row) {
if (!empty($row['cols'])) {
foreach ($row['cols'] as $col_index => $column) {
if (!empty($column['modules'])) {
foreach ($column['modules'] as $module_index => $module) {
if (!empty($module['cols'])) {
foreach ($module['cols'] as $sub_column_index => $sub_column) {
if (!empty($sub_column['modules'])) {
foreach ($sub_column['modules'] as $sub_module_index => $sub_module) {
if (isset($sub_module['mod_name']) && $sub_module['mod_name'] === 'widget') {
$builder_data[$row_index]['cols'][$col_index]['modules'][$module_index]['cols'][$sub_column_index]['modules'][$sub_module_index] = self::call_widget_update($sub_module);
if (isset($module['mod_name']) && $module['mod_name'] === 'widget') {
$builder_data[$row_index]['cols'][$col_index]['modules'][$module_index] = self::call_widget_update($module);
* Takes a $module array, for "widget" modules will call WP_Widget::update() method
* on the widget instance data
private static function call_widget_update($module) {
if (!empty($module['mod_settings']['instance_widget'])) {
global $wp_widget_factory;
$widget_class = $module['mod_settings']['class_widget'];
if (isset($wp_widget_factory->widgets[$widget_class])) {
set_error_handler(function($errno, $errstr, $errfile, $errline) {
$instance = $wp_widget_factory->widgets[$widget_class]->update($module['mod_settings']['instance_widget'], array());
if (!isset($instance['widget-id']) && isset($module['mod_settings']['instance_widget']['widget-id'])) {
$instance['widget-id'] = $module['mod_settings']['instance_widget']['widget-id'];
if (isset($module['mod_settings']['instance_widget'][$key])) {
$instance[$key] = $module['mod_settings']['instance_widget'][$key];
$module['mod_settings']['instance_widget'] = $instance;
public static function widget_gallery_lightbox($markup) {
return str_replace('<a', '<a class="themify_lightbox"', $markup);
public static function get_styling_image_fields() : array {
'background_image' => '',
'b_i_w_t' => '.module .widgettitle'
public static function get_translatable_text_fields( $module ) : array {
return [ 'mod_title_widget' ];
TB_Widget_Module::init();