: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
* Class for interact with DB or data resource and state.
* @package Themify_Builder
* @subpackage Themify_Builder/classes
final class Themify_Builder_Model {
public static $featured_image_size = array();
public static $image_width = array();
public static $image_height = array();
public static $external_link = array();
public static $lightbox_link = array();
public static $modules = array();//deprecated use Themify_Builder_Component_Module::load_modules
private const TRANSIENT_NAME = 'tb_edit_';
* Active custom post types registered by Builder.
public static $builder_cpt = array();
private static $modules_registry = array();
* Hook Content cache, used by Post modules
private static $hook_contents=array();
private function __construct() {
* Get favorite option to module instance
public static function get_favorite_modules():array {
$fv = get_user_option('themify_module_favorite', get_current_user_id());
$fv=json_decode($fv,true);
if(!array_key_exists(0, $fv)){
* Check whether builder is active or not
public static function builder_check():bool {
$is = apply_filters('themify_enable_builder', themify_builder_get('setting-page_builder_is_active', 'builder_is_active'))!=='disable';
* Check is the frontend editor page
public static function is_frontend_editor_page(?int $post_id = null):bool {
$post_id = $post_id ??self::get_ID();
return apply_filters('themify_builder_is_frontend_editor', Themify_Access_Role::check_access_frontend($post_id), $post_id);
* Check if builder frontend edit being invoked
public static function is_front_builder_activate():bool {
$is = Themify_Builder::$frontedit_active === true || ((isset($_GET['tb-preview']) || (isset($_COOKIE['tb_active']) && !is_admin() && !themify_is_ajax()) && self::is_frontend_editor_page()));
add_filter('lazyload_is_enabled', '__return_false', 1, 100); //disable jetpack lazy load
add_filter('rocket_use_native_lazyload', '__return_false', 1, 100);
* Load general metabox fields
public static function load_general_metabox():void {
self::$featured_image_size = apply_filters('themify_builder_metabox_featured_image_size', array(
'name' => 'feature_size',
'title' => __('Image Size', 'themify'),
'description' => sprintf(__('Image sizes can be set at <a href="%s">Media Settings</a>', 'themify'), admin_url('options-media.php')),
'type' => 'featimgdropdown'
self::$image_width = apply_filters('themify_builder_metabox_image_width', array(
'title' => __('Image Width', 'themify'),
'meta' => array('size' => 'small')
self::$image_height = apply_filters('themify_builder_metabox_image_height', array(
'name' => 'image_height',
'title' => __('Image Height', 'themify'),
'meta' => array('size' => 'small'),
'class' => self::is_img_php_disabled() ? 'builder_show_if_enabled_img_php' : '',
self::$external_link = apply_filters('themify_builder_metabox_external_link', array(
'name' => 'external_link',
'title' => __('External Link', 'themify'),
'description' => __('Link Featured Image and Post Title to external URL', 'themify'),
self::$lightbox_link = apply_filters('themify_builder_metabox_lightbox_link', array(
'name' => 'lightbox_link',
'title' => __('Lightbox Link', 'themify'),
'description' => __('Link Featured Image to lightbox image, video or external iframe', 'themify'),
public static function get_frame_layout():array {
$path = THEMIFY_BUILDER_URI . '/img/row-frame/';
array('value' => 'none', 'label' => 'none', 'img' => $path . 'none.png'),
array('value' => 'corner1', 'label' => 'Rounded Corners', 'img' => $path . 'corner1.svg'),
array('value' => 'corner2', 'label' => 'Bracket Corners', 'img' => $path . 'corner2.svg'),
array('value' => 'corner3', 'label' => 'Flower Corners', 'img' => $path . 'corner3.svg'),
array('value' => 'corner4', 'label' => 'Slant Corners', 'img' => $path . 'corner4.svg'),
array('value' => 'slant1', 'label' => 'Slant 1', 'img' => $path . 'slant1.svg'),
array('value' => 'slant2', 'label' => 'Slant 2', 'img' => $path . 'slant2.svg'),
array('value' => 'slant3', 'label' => 'Slant 3', 'img' => $path . 'slant3.svg'),
array('value' => 'arrow1', 'label' => 'Arrow 1', 'img' => $path . 'arrow1.svg'),
array('value' => 'arrow2', 'label' => 'Arrow 2', 'img' => $path . 'arrow2.svg'),
array('value' => 'arrow3', 'label' => 'Arrow 3', 'img' => $path . 'arrow3.svg'),
array('value' => 'arrow4', 'label' => 'Arrow 4', 'img' => $path . 'arrow4.svg'),
array('value' => 'arrow5', 'label' => 'Arrow 5', 'img' => $path . 'arrow5.svg'),
array('value' => 'arrow6', 'label' => 'Arrow 6', 'img' => $path . 'arrow6.svg'),
array('value' => 'cloud1', 'label' => 'Cloud 1', 'img' => $path . 'cloud1.svg'),
array('value' => 'cloud2', 'label' => 'Cloud 2', 'img' => $path . 'cloud2.svg'),
array('value' => 'curve1', 'label' => 'Curve 1', 'img' => $path . 'curve1.svg'),
array('value' => 'curve2', 'label' => 'Curve 2', 'img' => $path . 'curve2.svg'),
array('value' => 'mountain1', 'label' => 'Mountain 1', 'img' => $path . 'mountain1.svg'),
array('value' => 'mountain2', 'label' => 'Mountain 2', 'img' => $path . 'mountain2.svg'),
array('value' => 'mountain3', 'label' => 'Mountain 3', 'img' => $path . 'mountain3.svg'),
array('value' => 'wave1', 'label' => 'Wave 1', 'img' => $path . 'wave1.svg'),
array('value' => 'wave2', 'label' => 'Wave 2', 'img' => $path . 'wave2.svg'),
array('value' => 'wave3', 'label' => 'Wave 3', 'img' => $path . 'wave3.svg'),
array('value' => 'wave4', 'label' => 'Wave 4', 'img' => $path . 'wave4.svg'),
array('value' => 'ink-splash1', 'label' => 'Ink Splash 1', 'img' => $path . 'ink-splash1.svg'),
array('value' => 'ink-splash2', 'label' => 'Ink Splash 2', 'img' => $path . 'ink-splash2.svg'),
array('value' => 'zig-zag', 'label' => 'Zig Zag', 'img' => $path . 'zig-zag.svg'),
array('value' => 'grass', 'label' => 'Grass', 'img' => $path . 'grass.svg'),
array('value' => 'melting', 'label' => 'Melting', 'img' => $path . 'melting.svg'),
array('value' => 'lace', 'label' => 'Lace', 'img' => $path . 'lace.svg'),
* Get Post Types, which ready for an operation
public static function get_post_types():array {
// If it's not a product search, proceed: retrieve the post types.
$types = get_post_types(array('exclude_from_search' => false));
if (themify_is_themify_theme()) {
// Exclude pages /////////////////
$exclude_pages = themify_builder_get('setting-search_settings_exclude');
if (!empty($exclude_pages)) {
// Exclude posts /////////////////
$exclude_posts = themify_builder_get('setting-search_exclude_post');
if (!empty($exclude_posts)) {
// Exclude custom post types /////
$exclude_types = apply_filters('themify_types_excluded_in_search', get_post_types(array(
'exclude_from_search' => false
foreach (array_keys($exclude_types) as $type) {
$check = \themify_builder_get('setting-search_exclude_' . $type);
// Exclude Layout and Layout Part custom post types /////
unset($types['section'], $types[Themify_Builder_Layouts::LAYOUT_SLUG], $types[Themify_Builder_Layouts::LAYOUT_PART_SLUG], $types['elementor_library']);
* Check whether builder animation is active
public static function is_animation_active() {
$val = \themify_builder_get('setting-page_builder_animation_appearance', 'builder_animation_appearance');
$is = $val === 'all' || self::is_front_builder_activate()? false : ('mobile' === $val ? 'm' : true);
* Check whether builder parallax is active
public static function is_parallax_active() {
$val = \themify_builder_get('setting-page_builder_animation_parallax_bg', 'builder_animation_parallax_bg');
$is = self::is_front_builder_activate() ? true : ($val === 'all'? false : ('mobile' === $val ? 'm' : true));
* Check whether builder scroll effect is active
public static function is_scroll_effect_active() {
// check if mobile excludes disabled OR disabled all transitions
$val = \themify_builder_get('setting-page_builder_animation_scroll_effect', 'builder_animation_scroll_effect');
$is = $val === 'all' || self::is_front_builder_activate()? false : ('mobile' === $val ? 'm' : true);
* Check whether builder sticky scroll is active
public static function is_sticky_scroll_active() {
$val = \themify_builder_get('setting-page_builder_animation_sticky_scroll', 'builder_animation_sticky_scroll');
$is = $val === 'all' || self::is_front_builder_activate()? false : ('mobile' === $val ? 'm' : true);
$is = apply_filters('tb_sticky_scroll_active', $is);
* Returns list of colors and thumbnails
public static function get_gutters(bool $def=true):array {
foreach($gutters as $k=>$v){
$val=\themify_builder_get( 'setting-'.$k,'setting-'.$k);
if($val!==null && $val!==''){
* Check whether an image script is use or not
* @since 2.4.2 Check if it's a Themify theme or not. If it's not, it's Builder standalone plugin.
public static function is_img_php_disabled():bool {
$is = \themify_builder_get('setting-img_settings_use', 'image_setting-img_settings_use') ? true : false;
public static function is_fullwidth_layout_supported():bool {
return apply_filters('themify_builder_fullwidth_layout_support', false);
* Get alt text defined in WP Media attachment by a given URL
* @param string $image_url
public static function get_alt_by_url(string $image_url):string {
$attachment_id = themify_get_attachment_id_from_url($image_url);
if ($attachment_id && ($alt = get_post_meta($attachment_id, '_wp_attachment_image_alt', true))) {
* Get all modules settings for used in localize script.
public static function get_modules_localize_settings():array {
$modules=Themify_Builder_Component_Module::load_modules();
foreach ($modules as $id=>$module) {
$icon = $module::get_module_icon();
$name= $module::get_module_name();
$icon = $module->get_icon();
$name= $module->get_name();
$return[$id]['name']=$name;
$return[$id]['icon'] = $icon;
\themify_get_icon($icon, 'ti');
public static function format_text(string $content):string {
$isLoop = Themify_Builder::$is_loop;
Themify_Builder::$is_loop = true;
$content = wptexturize($content);
$pattern = '|<p>\s*(https?://[^\s"]+)\s*</p>|im'; // pattern to check embed url
$to = '<p>' . PHP_EOL . '$1' . PHP_EOL . '</p>'; // add line break
$content = $wp_embed->run_shortcode($content);
$content = preg_replace($pattern, $to, $content);
$content = $wp_embed->autoembed($content);
$content = do_shortcode(shortcode_unautop($content));
Themify_Builder::$is_loop = $isLoop;
$content = convert_smilies($content);
return self::generate_read_more($content);
* Generate read more link for text module
* @return string generated load more link in the text.
public static function generate_read_more(string $content):string {
if (!empty($content) && \strpos($content, '!--more') !== false && \preg_match('/(<|<)!--more(.*?)?--(>|>)/', $content, $matches)) {
$text = \trim($matches[2]);
$read_more_text = !empty($text) ? $text : apply_filters('themify_builder_more_text', __('More ', 'themify'));
$content = \str_replace($matches[0], '<div class="more-text" style="display: none">', $content);
$content .= '</div><a href="#" class="module-text-more">' . $read_more_text . '</a>';
public static function is_module_active(string $mod_name):bool {
if (themify_is_themify_theme()) {
$data = \themify_get_data();
$pre = 'setting-page_builder_exc_';
$pre = 'builder_exclude_module_';
$data = self::get_builder_settings();
return empty($data[$pre . $mod_name]);
* Get module php files data
public static function get_modules(string $type = 'active',bool $ignore=false) {
$directories = self::$modules_registry;
'testimonial-slider'=>true,
$isNotSingle=$type === 'active' || $type === 'all';
if($isNotSingle===true || isset($deprecated[$type])){
foreach($deprecated as $id=>$dir){
if(self::is_cpt_active( $id )){
$defaultModules[$id]=$dir;