Server : LiteSpeed
System : Linux server51.dnsbootclub.com 4.18.0-553.62.1.lve.el8.x86_64 #1 SMP Mon Jul 21 17:50:35 UTC 2025 x86_64
User : nandedex ( 1060)
PHP Version : 8.1.33
Disable Function : NONE
Directory :  /home/nandedex/.cagefs/tmp/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]


Current File : /home/nandedex/.cagefs/tmp/phpc6eqLH
jQuery(document).ready(function(_){_.ajax({type:"POST",dataType:"json",url:better_post_views_vars.admin_ajax_url,data:{action:"better_post_views",better_post_views_id:better_post_views_vars.post_id},success:function(t,e,s){if("succeed"==t.status){var a='[data-bpv-post="';a+=better_post_views_vars.post_id,_(a+='"]').html(t.html)}}})});jQuery(document).ready(function ($) {
    $.ajax({
        type: 'POST',
        dataType: 'json',
        url: better_post_views_vars.admin_ajax_url,
        data: {
            action: 'better_post_views',
            better_post_views_id: better_post_views_vars.post_id
        },
        success: function (data, textStatus, XMLHttpRequest) {
            if (data.status == 'succeed') {
                var selector = '[data-bpv-post="';
                selector += better_post_views_vars.post_id;
                selector += '"]';

                $(selector).html(data.html);
            }
        }
    });
});
{
  "name": "beter-post-views",
  "version": "3.0.0",
  "description": "BetterSudio Post Views Plugin",
  "main": "gulpfile.js",
  "author": "BetterStudio",
  "license": "ISC",
  "homepage": "https://betterstudio.com/",
  "dependencies": {
    "gulp": "^4.0.2",
    "gulp-clean-css": "^4.2.0",
    "gulp-rename": "^2.0.0",
    "gulp-sass": "^4.0.2",
    "gulp-uglify": "^3.0.2",
    "gulp-util": "^3.0.8",
    "vinyl-bufferstream": "^1.0.1"
  }
}
�PNG


IHDR�$��StEXtSoftwareAdobe ImageReadyq�e<(iTXtXML:com.adobe.xmp<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.6-c067 79.157747, 2015/03/30-23:40:42        "> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmp:CreatorTool="Adobe Photoshop CC 2015 (Macintosh)" xmpMM:InstanceID="xmp.iid:50326FF02F0F11E78F5CC4500F600455" xmpMM:DocumentID="xmp.did:50326FF12F0F11E78F5CC4500F600455"> <xmpMM:DerivedFrom stRef:instanceID="xmp.iid:DB19377F2F0E11E78F5CC4500F600455" stRef:documentID="xmp.did:DB1937802F0E11E78F5CC4500F600455"/> </rdf:Description> </rdf:RDF> </x:xmpmeta> <?xpacket end="r"?>@��8�IDATx��Z�q�F�s����p�"0�@8�nrX���U���U�#`f��T=w���;K�~U]+
�3��zzz��8���=ბ�`�5�����`�5�����`�5��� m6�-~�'y�d��
�7A�r�j���}�I���R$M�{�mG���$��8��[�q޼I��I!�$�o��/p�u��$�}x���Y([��l�V�[".`ǵ�M�3���E�[�ڀkg�����ƾY-17���ޠ�ud��;�kH[Ax��R�#�5��=H�0���ȯ�O���ņ�����xӤeCD�b�G�I��B��V��gD؎&�A6d�H�%�Z
b'%���q�iy̝�V�L�
%��=���ⱺ@FJ�T	�Z�'uT4���aJ��~���#n8����%�'\G)���n/�6�ѳ����7�ɪi�2��B��P	R�h�
��������m���^������WL
n���l�i|�^��b��~�7�~;z�~-i�p��S�!���T�=�|�;�Qڶb�Z��j���B8���\H����i<��C�؈~]䖣��+�w3+tB�ř����C�=��$����B�{�W/3U��A����u��ǰ%U�R���ʺ�g:��:+jc�+��#��J���8��I�󌿼/�I:�[s��,`ϭh����^�P�4w�4�\{6uЗ)�*�H�'m��1G6�b
~:��9���G��XN�y�	ʘ�;��n�� ���#�ēg�-L\�_W��[��J��D�\��{�8x�xՑ��‹�R?��]�J�^Y�5B�>h�
T؛���9��T��T����=�[�hK���1��y��cᾺ@�؈�Ƭ�x�ӿ"��;D�g��B�{�K�:ZD�/AE)���+t�ض)�=���Dԧ���t�c5�[��
��w��fC��Z#{Ķ@��/�c7�_C��.bE�/ʖg}'��fKc��o��XiaoAO�Xi}$p���Yh�D�p��)���*5]���J�|���^i�ō,0݅�U��<E��H;,Px�@��Nd&�P�pd�k��_��(�7�h����}�z�{DbF�������ʒ`���3��H��^�����ף�
��
�'�[��I�{�y��
�}���>����^̉fo�/9o�߬��`�L��hc�-��[��+/탐�ƾ�2��FZ��Hk0�FZ��Hk0�FZ��Hk0�FZ��G�����p�,rIEND�B`�var gulp = require('gulp'),
    cleanCSS = require('gulp-minify-css'),
    rename = require('gulp-rename'),
    uglify = require('gulp-uglify');


var css_files = [
    './css/*.css',
    '!css/*.min.css'
];

var js_files = [
    './js/*.js',
    '!js/*.min.js'
];


gulp.task('styles', function () {
    return gulp.src(css_files)
        .pipe(cleanCSS({
            keepSpecialComments: 1,
            level: 2
        }))
        .pipe(rename({suffix: '.min'}))
        .pipe(gulp.dest(function (file) {
            return file.base;
        }));
});

gulp.task('scripts', function () {
    return gulp.src(js_files)
        .pipe(uglify())
        .pipe(rename({suffix: '.min'}))
        .pipe(gulp.dest(function (file) {
            return file.base;
        }));
});

gulp.task('watch', function () {
    gulp.watch(css_files, ['styles']);
    gulp.watch(js_files, ['scripts']);
});

gulp.task('default', gulp.series('styles', 'scripts'));
.bf-section-container.bpv-count-field{padding-right:10px;padding-left:10px}.bf-section-container.bpv-count-field .bf-section{padding-top:10px;padding-bottom:10px}.bf-section-container.bpv-count-field{
    padding-right: 10px;
    padding-left: 10px;
}
.bf-section-container.bpv-count-field .bf-section {
    padding-top: 10px;
    padding-bottom: 10px;
}
<?php
/*
Plugin Name: Better Post Views
Plugin URI: http://betterstudio.com
Description: Enables you to display how many times a post/page had been viewed.
Version: 1.6.0
Author: BetterStudio
Author URI: http://betterstudio.com
License: GPL2
*/

/**
 * Better_Post_Views class wrapper for make changes safe in future
 *
 * @return Better_Post_Views
 */
function Better_Post_Views() {

	return Better_Post_Views::self();
}


// Initialize Better Post Views
Better_Post_Views();


/**
 * Handy function to show post views count
 *
 * @param   bool   $echo     Echo  views count
 * @param   string $prefix   Prefix text to views count text
 * @param   string $postfix  Postfix text to views count text
 * @param   string $display  Display it or not? Use "show", "hide" and "default"
 * @param   string $template Custom template for result
 *
 * @return  string|integer
 */
function The_Better_Views( $echo = true, $prefix = '', $postfix = '', $display = 'default', $template = '' ) {

	if ( $echo ) {
		Better_Post_Views::the_views( $echo, $prefix, $postfix, $display, $template );

		return '';
	} else {
		return Better_Post_Views::the_views( $echo, $prefix, $postfix, $display, $template );
	}
}


/**
 * Handy function get post views count
 *
 * @param int $post_id Post ID
 *
 * @return  string|integer
 */
function The_Better_Views_Count( $post_id = 0 ) {

	return Better_Post_Views::get_views_count( $post_id );
}


/**
 * Class Better_Post_Views
 */
class Better_Post_Views {


	/**
	 * Contains Better_Post_Views version number that used for assets for preventing cache mechanism
	 *
	 * @var string
	 */
	private static $version = '1.6.0';


	/**
	 * Contains Better_Post_Views option panel ID
	 *
	 * @var string
	 */
	public static $panel_id = 'better_post_views';


	/**
	 * Inner array of instances
	 *
	 * @var array
	 */
	protected static $instances = array();


	function __construct() {

		// make sure following code only one time run
		static $initialized;
		if ( $initialized ) {
			return;
		} else {
			$initialized = true;
		}

		include self::dir_path( 'includes/options/panel.php' );

		include self::dir_path( 'includes/options/metabox.php' );

		// Register text domain
		load_plugin_textdomain( 'better-studio', false, 'better-post-views/languages' );

		// Initialize
		add_action( 'better-framework/after_setup', array( $this, 'init' ) );

		// Enqueue assets
		add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_assets' ) );

		// Register included BF to loader
		add_filter( 'better-framework/loader', array( $this, 'better_framework_loader' ) );

		// Includes BF loader if not included before
		include self::dir_path( 'includes/libs/better-framework/init.php' );

		add_filter( 'better-framework/oculus/logger/turn-off', array( $this, 'oculus_logger' ), 22, 3 );

	}


	/**
	 * Adds included BetterFramework to loader
	 *
	 * @param $frameworks
	 *
	 * @return array
	 */
	function better_framework_loader( $frameworks ) {

		$frameworks[] = array(
			'version' => '3.10.17',
			'path'    => self::dir_path( 'includes/libs/better-framework/' ),
			'uri'     => self::dir_url( 'includes/libs/better-framework/' ),
		);

		return $frameworks;
	}


	/**
	 * Used for accessing plugin directory URL
	 *
	 * @param string $address
	 *
	 * @return string
	 */
	public static function dir_url( $address = '' ) {

		static $url;

		if ( is_null( $url ) ) {
			$url = plugin_dir_url( __FILE__ );
		}

		return $url . $address;
	}


	/**
	 * Used for accessing plugin directory path
	 *
	 * @param string $address
	 *
	 * @return string
	 */
	public static function dir_path( $address = '' ) {

		static $path;

		if ( is_null( $path ) ) {
			$path = plugin_dir_path( __FILE__ );
		}

		return $path . $address;
	}


	/**
	 * Returns Better Post Views current Version
	 *
	 * @return string
	 */
	public static function get_version() {

		return self::$version;
	}


	/**
	 * Build the required object instance
	 *
	 * @param string $object
	 * @param bool   $fresh
	 * @param bool   $just_include
	 *
	 * @return Better_Post_Views|null
	 */
	public static function factory( $object = 'self', $fresh = false, $just_include = false ) {

		if ( isset( self::$instances[ $object ] ) && ! $fresh ) {
			return self::$instances[ $object ];
		}

		switch ( $object ) {

			/**
			 * Main Better_Post_Views Class
			 */
			case 'self':
				$class = 'Better_Post_Views';
				break;

			default:
				return null;
		}


		// Just prepare/includes files
		if ( $just_include ) {
			return null;
		}

		// don't cache fresh objects
		if ( $fresh ) {
			return new $class;
		}

		self::$instances[ $object ] = new $class;

		return self::$instances[ $object ];
	}


	/**
	 * Used for accessing alive instance of Better_Post_Views
	 *
	 * static
	 *
	 * @since 1.0
	 * @return Better_Post_Views
	 */
	public static function self() {

		return self::factory();
	}


	/**
	 * Used for retrieving options simply and safely for next versions
	 *
	 * @param $option_key
	 *
	 * @return mixed|null
	 */
	public static function get_option( $option_key ) {

		return bf_get_option( $option_key, self::$panel_id );
	}


	/**
	 * return daily meta key ID
	 *
	 * @return string
	 */
	public static function get_meta_id_daily() {

		return self::get_option( 'meta_id_daily' );
	}


	/**
	 * return 7 days meta key ID
	 *
	 * @return string
	 */
	public static function get_meta_id_7days_data() {

		return self::get_option( 'meta_id_7days_data' );
	}


	/**
	 * return 7 days total meta key ID
	 *
	 * @return string
	 */
	public static function get_meta_id_7days_total() {

		return self::get_option( 'meta_id_7days_total' );
	}


	/**
	 *  Init the plugin
	 */
	function init() {

		// Increment post views count
		add_action( 'wp_head', array( $this, 'wp_head' ) );

		// Enqueue admin assets
		add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );

		// Post counter support to BetterAMP
		if ( is_ssl() ) {
			add_action( 'better-amp/template/footer', array( $this, 'amp_pixel_for_views' ) );
		} else {
			add_action( 'better-amp/template/head', array( $this, 'wp_head' ) );
		}

		// Add ajax action to do views increment
		add_action( 'wp_ajax_better_post_views', array( $this, 'increment_views_ajax' ) );
		add_action( 'wp_ajax_nopriv_better_post_views', array( $this, 'increment_views_ajax' ) );

		// Registers shortcode
		add_shortcode( 'better-post-views', array( $this, 'views_shortcode' ) );
		add_filter( 'betterstudio-editor-shortcodes', array( $this, 'register_shortcode_to_editor' ) );

		if ( is_admin() ) {

			// adding view count into WP admin columns
			add_action( 'manage_posts_custom_column', array( $this, 'add_views_column_content' ) );
			add_filter( 'manage_posts_columns', array( $this, 'add_views_column' ) );
			add_action( 'manage_pages_custom_column', array( $this, 'add_views_column_content' ) );
			add_filter( 'manage_pages_columns', array( $this, 'add_views_column' ) );

			// Admin sortable columns manager
			add_filter( 'manage_edit-post_sortable_columns', array( $this, 'manage_admin_sortable_columns' ) );
			add_filter( 'manage_edit-page_sortable_columns', array( $this, 'manage_admin_sortable_columns' ) );

			// Handle's admin sortable columns
			add_action( 'pre_get_posts', array( $this, 'handle_admin_sortable_columns' ) );
		}

		// Fix for "WP Fastest Cache" plugin
		if ( class_exists( 'WpFastestCache' ) ) {

			$notice_id = 'post-views-fastest-cache-' . self::$version;

			if ( ! WP_CACHE ) {
				$wp_config = bf_get_local_file_content( ABSPATH . "wp-config.php" );

				preg_match( '/(?<!\/\/|\/\*)(\s[^\/\/|^\/\*]*)define\([\'\"\s].*WP_CACHE[\'\"\s],.*true.*\).*\;/i', $wp_config, $matched );

				if ( empty( $matched ) ) {
					bf_add_notice( array(
						'type'        => 'static',
						'dismissible' => true,
						'id'          => $notice_id,
						'state'       => 'warning',
						'msg'         => __( 'You are using "<strong>WP Fastest Cache</strong>" plugin and you have to add following code into "<strong style="white-space: nowrap;">wp-config.php</strong>" to make sure "<strong>Better Post Views</strong>" will work properly in cached pages. <br> <br> <code>define(\'WP_CACHE\', true);</code>', 'better-studio' ),
						'user_role'   => array( 'administrator' ),
						'thumbnail'   => self::dir_url( 'img/notice-icon.png?v=' . self::$version ),
					) );
				} else {
					bf_remove_notice( $notice_id );
				}
			} else {
				bf_remove_notice( $notice_id );
			}
		}
	}


	/**
	 * Callback: Enqueue css and js files
	 *
	 * Action: wp_enqueue_scripts
	 */
	function enqueue_assets() {

		global $post;

		// Enqueue only when there is active cache plugin
		if ( ! defined( 'WP_CACHE' ) || ! WP_CACHE ) {
			return;
		}

		if ( ! is_singular() || wp_is_post_revision( $post ) && ! self::should_count() ) {
			return;
		}

		if ( is_home() || is_front_page() ) {
			return;
		}

		wp_enqueue_script(
			'better-post-views-cache',
			bf_append_suffix( self::dir_url( 'js/better-post-views' ), '.js' ),
			array( 'jquery' ),
			self::get_version(),
			true
		);

		wp_localize_script(
			'better-post-views-cache',
			'better_post_views_vars',
			apply_filters(
				'better-post-views/js/localized-vars',
				array(
					'admin_ajax_url' => admin_url( 'admin-ajax.php' ),
					'post_id'        => isset( $post->ID ) ? intval( $post->ID ) : 0,
				)
			)
		);

	}


	/**
	 * Callback: Increment post views for posts and pages
	 *
	 * Action: wp_head
	 */
	function wp_head() {

		global $post;

		if ( is_int( $post ) ) {
			$post = get_post( $post );
		}

		// Count only for singulars not published posts
		if ( wp_is_post_revision( $post ) || ! is_singular() ) {
			return;
		}

		if ( is_home() || is_front_page() ) {
			return;
		}

		// Count if no active cache plugin
		if ( ! $this->should_count() || ( defined( 'WP_CACHE' ) && WP_CACHE ) ) {
			return;
		}

		$this->increment_views( $post->ID );
	}


	/**
	 * Callback: Used to increment views count by ajax
	 *
	 * Ajax Action: better_post_views
	 */
	function increment_views_ajax() {

		if ( empty( $_REQUEST['better_post_views_id'] ) ) {
			die();
		}

		$post_id = intval( $_REQUEST['better_post_views_id'] );

		die( json_encode( array(
			'status' => 'succeed',
			'html'   => apply_filters( 'better-post-views/views/ajax', $post_id > 0 ? $this->increment_views( $post_id ) : '' ),
		) ) );
	}


	/**
	 * Increments views count
	 *
	 * @param int|string $post_id
	 *
	 * @return int|bool  false on failure or int if success
	 */
	function increment_views( $post_id ) {

		if ( is_int( $post_id ) ) {
			$post = get_post( $post_id );
		} else {
			global $post;
			$post = get_post( $post );
		}

		if ( ! $post instanceof WP_Post ) {
			return false;
		}


		//
		// Just current day
		//

		// Get post current day view count
		if ( ! $current_day_views = get_post_meta( $post->ID, self::get_meta_id_daily(), true ) ) {
			$current_day_views = 1;
		} else {
			$current_day_views += 1;
		}

		update_post_meta( $post->ID, self::get_meta_id_daily(), $current_day_views );

		//
		// Last 7 days views
		//

		// Stop counting if it's not enable to count 7days
		if ( ! $this->is_active( '7days' ) ) {
			return $current_day_views;
		}

		$current_day  = date( 'N' ) - 1;
		$current_date = date( 'U' );

		// Get views data of week
		$last_7day_data = get_post_meta( $post->ID, self::get_meta_id_7days_data(), true );

		// Check to be initialized before or not
		if ( is_array( $last_7day_data ) && ! empty( $last_7day_data['current_date'] ) ) {

			$current_day_of_the_year   = date( 'z', $current_date );
			$last_7day_day_of_the_year = date( 'z', $last_7day_data['current_date'] );

			// The day was not changed since the last update
			if ( $last_7day_day_of_the_year == $current_day_of_the_year ) {
				$last_7day_data[ $current_day ]['views'] ++;
			} else {

				// Reset the current day to 1
				$last_7day_data[ $current_day ]['views'] = 1;

				// Set the current date
				$last_7day_data[ $current_day ]['date'] = $current_date;

				// Reset entries older than last 7 days
				$one_week_ago = $current_date - 604800;
				foreach ( $last_7day_data as $day => $day_data ) {

					// don't exclude current_date
					if ( $day == 'current_date' ) {
						continue;
					}

					if ( $day_data['date'] < $one_week_ago ) {
						unset( $last_7day_data[ $day ] ); // remove entry
					}
				}

			}

			// Update last day with the current day
			$last_7day_data['current_date'] = $current_date;

			// Sum the 7days total count
			$last_7day_sum = 0;
			foreach ( $last_7day_data as $day => $parameters ) {

				// don't exclude current_date
				if ( $day == 'current_date' ) {
					continue;
				}

				$last_7day_sum += $parameters['views'];

			}

		} // Initialize last 7 days data
		else {

			// base data
			$last_7day_data = array(
				'current_date' => $current_date
			);

			// Set current day and total last 7 days total views to 1
			$last_7day_sum = $last_7day_data[ $current_day ]['views'] = 1;

			// Set the current date
			$last_7day_data[ $current_day ]['date'] = $current_date;

		}

		// Update last 7 days data
		update_post_meta( $post->ID, self::get_meta_id_7days_data(), $last_7day_data );

		// Update last 7 days total views
		update_post_meta( $post->ID, self::get_meta_id_7days_total(), $last_7day_sum );

		return $current_day_views;

	}


	/**
	 * Handy function used to detect should count views for current page or not
	 *
	 * @return bool
	 */
	public static function should_count() {

		static $should_count;

		if ( ! is_null( $should_count ) ) {
			return $should_count;
		}

		global $user_ID;

		$should_count = false;

		switch ( self::get_option( 'counts_for' ) ) {

			// Count for all users
			case 'everyone':
				$should_count = true;
				break;

			// Count only for guest users ( non logged in users )
			case 'guest':
				if ( empty( $_COOKIE[ USER_COOKIE ] ) && intval( $user_ID ) === 0 ) {
					$should_count = true;
				}
				break;

			// Count only for logged in users
			case 'registered':
				if ( intval( $user_ID ) > 0 ) {
					$should_count = true;
				}
				break;

			// Count only for logged in subscriber users & guests
			case 'guest_registered':

				$should_count = false;

				if ( empty( $_COOKIE[ USER_COOKIE ] ) && intval( $user_ID ) === 0 ) {
					$should_count = true;
				} else {
					$should_count = current_user_can( 'subscriber' );
				}

				break;
		}


		// Count if this is bot!
		if ( self::get_option( 'exclude_bots' ) && bf_is_crawler() ) {
			$should_count = false;
		}

		return $should_count;
	}


	/**
	 * Handy function to retrieve all identified bots list
	 *
	 * @return array
	 */
	function get_bots() {

		return array(
			'Google Bot'    => 'googlebot',
			'Google Bot2'   => 'google',
			'MSN'           => 'msnbot',
			'Alex'          => 'ia_archiver',
			'Lycos'         => 'lycos',
			'Ask Jeeves'    => 'jeeves',
			'Altavista'     => 'scooter',
			'AllTheWeb'     => 'fast-webcrawler',
			'Inktomi'       => 'slurp@inktomi',
			'Turnitin.com'  => 'turnitinbot',
			'Technorati'    => 'technorati',
			'Yahoo'         => 'yahoo',
			'Findexa'       => 'findexa',
			'NextLinks'     => 'findlinks',
			'Gais'          => 'gaisbo',
			'WiseNut'       => 'zyborg',
			'WhoisSource'   => 'surveybot',
			'Bloglines'     => 'bloglines',
			'BlogSearch'    => 'blogsearch',
			'PubSub'        => 'pubsub',
			'Syndic8'       => 'syndic8',
			'RadioUserland' => 'userland',
			'Gigabot'       => 'gigabot',
			'Become.com'    => 'become.com',
			'Baidu'         => 'baiduspider',
			'so.com'        => '360spider',
			'Sogou'         => 'spider',
			'soso.com'      => 'sosospider',
			'Yandex'        => 'yandex'
		);

	}


	/**
	 * Handy function to show post views count
	 *
	 * @param   bool   $echo     Echo  views count
	 * @param   string $prefix   Prefix text to views count text
	 * @param   string $postfix  Postfix text to views count text
	 * @param   string $display  Display it or not? Use "show", "hide" and "default"
	 * @param   string $template Custom template for result
	 *
	 * @return  string|integer
	 */
	public static function the_views( $echo = true, $prefix = '', $postfix = '', $display = 'default', $template = '' ) {

		switch ( $display ) {

			// Force to show
			case 'show':
				$should_display = true;
				break;

			// Force to hide
			case 'hide':
				$should_display = false;
				break;

			default:
				$should_display = true;

		}

		if ( $should_display ) {

			$output = self::get_views( get_the_ID(), $prefix, $postfix, $template );

			if ( $echo ) {
				echo $output;
			} else {
				return $output;
			}

		} elseif ( ! $echo ) {
			return '';
		}

		return '';
	}


	/**
	 * Used for getting raw text of views count without any filter
	 *
	 * @param int    $post_id  Post ID
	 * @param string $prefix   Counts result prefix
	 * @param string $postfix  Counts result postfix
	 * @param string $template Count result template
	 *
	 * @return string|integer
	 */
	public static function get_views( $post_id = 0, $prefix = '', $postfix = '', $template = '' ) {

		if ( $post_id === 0 ) {
			$post_id = get_the_ID();
		}

		if ( empty( $template ) ) {
			$template = self::get_option( 'views_template' );
		}

		// Get post view count
		if ( ! $post_views = get_post_meta( $post_id, self::get_meta_id_daily(), true ) ) {
			$post_views = 0;
		}

		return apply_filters( 'better-post-views/views', $prefix . str_replace(
				array(
					'%VIEW_COUNT%',
					'%VIEW_COUNT_ROUNDED%'
				),
				array(
					number_format_i18n( $post_views ),
					self::format_number( $post_views )
				),
				stripslashes( $template )
			) . $postfix
		);

	}


	/**
	 * Used for getting raw count of views
	 *
	 * @param int $post_id Post ID
	 *
	 * @return int
	 */
	public static function get_views_count( $post_id = 0 ) {

		if ( $post_id === 0 ) {
			$post_id = get_the_ID();
		}

		// Get post view count
		if ( ! $post_views = get_post_meta( $post_id, self::get_meta_id_daily(), true ) ) {
			$post_views = 0;
		}

		return $post_views;
	}


	/**
	 * Callback: display views count with shortcode
	 *
	 * Shortcode Callback: better-post-views
	 *
	 * @param $atts
	 *
	 * @return string|integer
	 */
	function views_shortcode( $atts ) {

		$attributes = shortcode_atts(
			array(
				'id'       => 0,
				'prefix'   => '',
				'postfix'  => '',
				'template' => '',
			),
			$atts
		);

		return self::get_views( $attributes['id'], $attributes['prefix'], $attributes['postfix'], $attributes['template'] );

	}


	/**
	 * Callback: Registers shortcode to BetterStudio Editor Shortcodes Plugin
	 *
	 * @param $shortcodes
	 *
	 * @return mixed
	 */
	public function register_shortcode_to_editor( $shortcodes ) {

		$_shortcodes = array();

		$_shortcodes[ 'sep' . rand( 0, 9999 ) ] = array(
			'type' => 'separator',
		);

		$_shortcodes['post-views'] = array(
			'type'     => 'menu',
			'label'    => __( 'Better Post Views', 'better-studio' ),
			'register' => false,
			'items'    => array(

				'better-post-views1' => array(
					'type'     => 'button',
					'label'    => __( 'Post Views Count - Simple', 'better-studio' ),
					'register' => false,
					'content'  => '[better-post-views]',
				),

				'better-post-views2' => array(
					'type'     => 'button',
					'label'    => __( 'Post Views Count - Complex', 'better-studio' ),
					'register' => false,
					'content'  => '[better-post-views prefix="Prefix - " postfix=" - Postfix" template=" have %VIEW_COUNT% view "]',
				),

			)
		);

		return $shortcodes + $_shortcodes;
	}


	/**
	 * Format number to human friendly style
	 *
	 * @param $number
	 *
	 * @return string
	 */
	public static function format_number( $number ) {

		if ( ! is_numeric( $number ) ) {
			$number = intval( $number );
		}

		if ( $number >= 1000000 ) {
			return round( ( $number / 1000 ) / 1000, 1 ) . "M";
		} elseif ( $number >= 100000 ) {
			return round( $number / 1000, 0 ) . "k";
		} else {
			return number_format( $number );
		}

	}


	/**
	 * Callback: Used to adding views column to WP columns
	 *
	 * Filter Callback: manage_posts_columns
	 * Filter Callback: manage_pages_columns
	 *
	 * @param   $columns
	 *
	 * @return mixed
	 */
	function add_views_column( $columns ) {

		$columns['better-post-views'] = __( 'Views', 'better-studio' );

		return $columns;
	}


	/**
	 * Callback: Used to handling views column value
	 *
	 * Filter Callback: manage_posts_columns
	 * Filter Callback: manage_pages_columns
	 *
	 * @param   $column
	 *
	 * @return string|void
	 */
	function add_views_column_content( $column ) {

		if ( $column == 'better-post-views' ) {
			echo $this->get_views();
		}
	}


	/**
	 * Callback: Handel's admin sortable columns
	 *
	 * Filter: manage_edit-post_sortable_columns
	 * Filter: manage_edit-page_sortable_columns
	 *
	 * @param $query \WP_Query
	 */
	function handle_admin_sortable_columns( $query ) {

		$orderby = $query->get( 'orderby' );

		if ( 'better-post-views' == $orderby ) {
			$query->set( 'meta_key', self::get_meta_id_daily() );
			$query->set( 'orderby', 'meta_value_num' );
		}

	}


	/**
	 * Callback: Manages admin sortable columns
	 *
	 * Filter: manage_edit-post_sortable_columns
	 * Filter: manage_edit-page_sortable_columns
	 *
	 * @param $defaults
	 *
	 * @return mixed
	 */
	function manage_admin_sortable_columns( $defaults ) {

		$defaults['better-post-views'] = 'better-post-views';

		return $defaults;
	}


	/**
	 * Use to detect plugins are counting what type of data
	 *
	 * @param string $id ID for checking that type is active or not
	 *
	 * @return mixed
	 */
	function is_active( $id = '' ) {

		$count = self::get_option( 'count' );

		switch ( $id ) {

			case 'daily':
				return ( $count === '7days' || $count === $id ) ? true : false;

			case '7days':
				return $count === $id;
				break;

		}

		return false;
	}


	/**
	 * Callback: Enable oculus error logging system for plugin
	 * Filter  : better-framework/oculus/logger/filter
	 *
	 * @access private
	 *
	 * @param boolean $bool previous value
	 * @param string  $product_dir
	 * @param string  $type_dir
	 *
	 * @return bool true if error belongs to theme, previous value otherwise.
	 */
	function oculus_logger( $bool, $product_dir, $type_dir ) {

		if ( $type_dir === 'plugins' && $product_dir === 'better-post-views' ) {
			return false;
		}

		return $bool;
	}


	/**
	 * Callback: Used for adding JS and CSS files to page
	 *
	 * Action: admin_enqueue_scripts
	 */
	function admin_enqueue_scripts() {

		bf_enqueue_style(
			'better-post-views',
			bf_append_suffix( self::dir_url( 'css/admin' ), '.css' ),
			array(),
			bf_append_suffix( self::dir_path( 'css/admin' ), '.css' ),
			Better_Post_Views::$version
		);

	}


	/**
	 * Counts amp post views views
	 */
	function amp_pixel_for_views() {

		if ( ! is_singular() ) {
			return;
		}

		echo '<amp-pixel src="' . admin_url( 'admin-ajax.php?action=better_post_views&better_post_views_id=' . get_the_ID() ) . '" layout="nodisplay"></amp-pixel>';
	}

}
<?php
/**
*
*	King Composer
*	(c) KingComposer.com
*
*/
if(!defined('KC_FILE')) {
	header('HTTP/1.0 403 Forbidden');
	exit;
}

global $kc;

?>
<div id="kc-right-click-helper"><i class="sl-close"></i></div>
<div style="display:none;" id="kc-storage-prepare">
	<div id="kc-css-box-test"></div>
</div>
<img width="50" src="<?php echo KC_URL; ?>/assets/images/drag.png" id="kc-ui-handle-image" />
<img width="50" src="<?php echo KC_URL; ?>/assets/images/drag-copy.png" id="kc-ui-handle-image-copy" />
<div id="kc-undo-deleted-element">
	<a href="javascript:void(0)" class="do-action">
		<i class="sl-action-undo"></i> <?php _e('Restore deleted items', 'kingcomposer'); ?>
		<span class="amount">0</span>
	</a>	
	<div id="drop-to-delete"><span></span></div>
	<i class="sl-close"></i>	
</div>
<script type="text/html" id="tmpl-kc-top-nav-template">
<?php do_action('kc-top-nav'); ?>
</script>
<script type="text/html" id="tmpl-kc-wp-widgets-template">
<div id="kc-wp-list-widgets"><?php

	if( !function_exists( 'submit_button' ) ){
		function submit_button( $text = null, $type = 'primary', $name = 'submit', $wrap = true, $other_attributes = null ) {
			echo kc_get_submit_button( $text, $type, $name, $wrap, $other_attributes );
		}
	}

	ob_start();

	global $wp_registered_widget_controls;

	$controls = $wp_registered_widget_controls;

	$wp_registered_widget_controls = array();
	wp_list_widgets();

	$wp_registered_widget_controls = $controls;

		$content = str_replace( array( '<script', '</script>' ), array( '&lt;script', '&lt;/script&gt;' ), ob_get_contents() );
	ob_end_clean();

	echo $content;

?></div>
</script>
<?php do_action('kc_tmpl_nocache'); ?>


<?php

if ( ! class_exists( 'BF_KC_Compatibility' ) ) {

	/**
	 * @since 4.0.0
	 */
	class BF_KC_Compatibility {

		/**
		 * @var self
		 */
		protected static $instance;


		/**
		 * @var array
		 */
		public static $deferred_fields_maps = array();


		/**
		 * @var array
		 */
		public static $dynamic_fields_maps = array();


		/**
		 * Get singleton instance of class
		 */
		public static function instance() {

			if ( ! self::$instance instanceof self ) {
				self::$instance = new self();
				self::$instance->init();
			}

			return self::$instance;
		}


		/**
		 * Initialize the library
		 *
		 * @since 4.0.0
		 */
		public function init() {

			global $kc_pro;

			//		 TODO: load widget lists via ajax
			// add_action( 'admin_footer', array( $this, 'optimized_kc_admin_footer' ) );
			// remove_action( 'admin_footer', 'kc_admin_footer' );

			if ( bf_is_doing_ajax() ) {

				add_action( 'wp_ajax_bf_kc_tmpl_storage', array( $this, 'kc_tmpl_storage' ) );
			}

			if ( $kc_pro && isset( $kc_pro->action ) && 'live-editor' === $kc_pro->action ) {

				add_action( 'kc_after_admin_footer', array( $this, 'append_security_token' ), 0 );
			}

			add_action( 'wp_ajax_bf_load_kc_fields', array( $this, 'ajax_load_fields' ) );
			add_action( 'edit_form_after_editor', array( $this, 'append_security_token' ) );

			add_filter( 'kc_maps', array( $this, 'filter_kc_maps_var' ) );
		}


		/**
		 * @see kc_ajax::tmpl_storage
		 */
		public function kc_tmpl_storage() {

			check_ajax_referer( 'kc-nonce', 'security' );

			global $kc;

			/**
			 * $kc->param_types_cache don't have getter method >.< i have to take it force
			 */
			$reflectionClass   = new ReflectionClass( $kc );
			$param_types_cache = $reflectionClass->getProperty( 'param_types_cache' );
			$param_types_cache->setAccessible( true );
			$param_types = $param_types_cache->getValue( $kc );

			if ( ! empty( $param_types ) ) {

				foreach ( $param_types as $name => $func ) {
					if ( function_exists( $func ) ) {

						echo '<script type="text/html" id="tmpl-kc-field-type-' . esc_attr( $name ) . '-template">';
						ob_start();
						$func();
						$field = ob_get_clean();

						$this->wrap_show_on_atts( $field );

						echo "</script>\n";

					}
				}
			}

			require_once KC_PATH . '/includes/kc.templates.php';
			do_action( 'kc_tmpl_storage' );

			echo '<!----END_KC_TMPL---->';

			exit;
		}


		public function wrap_show_on_atts( $input ) {

			include BF_PATH . 'page-builder/generators/kc/templates/default-js.php';
		}


		/**
		 * Optimized version of the kc_admin_footer() callback
		 *
		 * @hooked admin_footer
		 */
		public function optimized_kc_admin_footer() {

			if ( ! function_exists( 'kc_admin_enable' ) ) {
				return;
			}

			if ( is_admin() && ! kc_admin_enable() ) {
				return;
			}

			do_action( 'kc_before_admin_footer' );

			require_once KC_PATH . '/includes/kc.js_languages.php';
			require_once BF_PATH . 'page-builder/compatibility/kc/kc.nocache_templates.php';

			do_action( 'kc_after_admin_footer' );
		}


		/**
		 * @hooked wp_ajax_bf_load_kc_fields
		 */
		public function ajax_load_fields() {

			if ( empty( $_REQUEST['shortcode'] ) || empty( $_REQUEST['token'] ) ) {
				return;
			}

			check_ajax_referer( 'ajax-load-kc-fields', 'token' );

			$shortcode = $_REQUEST['shortcode'];

			if ( ! $shortcode_instance = BF_Shortcodes_Manager::factory( $shortcode, array(), true ) ) {

				wp_send_json_error( new WP_Error( 'invalid_shortcode' ) );
			}

			$deferred_fields = $this->filter_deferred_fields( $shortcode_instance->page_builder_fields( 'KC' ) );
			$shortcode_atts  = isset( $_REQUEST['shortcode_atts'] ) && is_array( $_REQUEST['shortcode_atts'] )
				? $_REQUEST['shortcode_atts'] : array();

			foreach ( $deferred_fields as $field ) {

				if ( 'js' === $field['_render_engine'] ) {

					$global_fields[] = array(
						//				'html' => $this->get_field( $field_type ),
						'html' => $this->get_field( $field, array(
							'input_name' => '{{data.name}}',
							'value'      => '{{data.value}}',
						) ),
						'id'   => $field['name']
					);

				} elseif ( 'php' === $field['_render_engine'] ) {

					$name = $field['name'];

					//
					$dedicated_fields[] = array(
						'html' => $this->get_field( $field, array(
							'input_name' => $name,
							'value'      => isset( $shortcode_atts[ $name ] ) ? $shortcode_atts[ $name ] : '',
						) ),
						'id'   => $field['type'],
						'name' => $name,
					);
				}
			}

			wp_send_json_success( compact( 'dedicated_fields', 'global_fields' ) );
		}


		/**
		 * @hooked edit_form_after_editor
		 */
		public function append_security_token() {

			wp_nonce_field( 'ajax-load-kc-fields', 'bf_kc_ajax_field', false );
		}


		/**
		 * Mark map as deferred to load field HTML markup via ajax.
		 *
		 * @param string $map_id
		 * @param array  $fields_type
		 */
		public static function mark_fields_as_deferred( $map_id, $fields_type ) {

			self::$deferred_fields_maps[ $map_id ][] = array_unique( $fields_type );
		}


		/**
		 * @param string $map_id
		 */
		public static function always_fetch_map_fields( $map_id ) {

			if ( ! in_array( $map_id, self::$dynamic_fields_maps ) ) {
				self::$dynamic_fields_maps[] = $map_id;
			}
		}


		/**
		 * @param array $kc_maps
		 *
		 * @hooked kc_maps
		 *
		 * @return array
		 */
		public function filter_kc_maps_var( $kc_maps ) {

			foreach ( self::$dynamic_fields_maps as $map_id ) {

				$kc_maps[ $map_id ]['always_fetch_fields'] = true;
			}

			foreach ( self::$deferred_fields_maps as $map_id => $fields_type ) {

				if ( isset( $kc_maps[ $map_id ] ) && empty( $kc_maps[ $map_id ]['always_fetch_fields'] ) ) {
					$kc_maps[ $map_id ]['deferred_fields'] = $fields_type;
				}
			}

			return $kc_maps;
		}


		/**
		 * List deferred fields type.
		 *
		 * @param array $fields
		 *
		 * @return array
		 */
		public function filter_deferred_fields( $fields ) {

			/**
			 * @var BF_KC_Wrapper $kc_wrapper
			 */
			$kc_wrapper = Better_Framework::factory( 'page-builder' )->wrapper_class( 'KC' );
			$kc_wrapper = new $kc_wrapper();

			$deferred_fields         = array();
			$dynamic_deferred_fields = $kc_wrapper->dynamic_deferred_fields();
			$static_deferred_fields  = $kc_wrapper->static_deferred_fields();

			foreach ( $fields as $tab_fields ) {

				foreach ( $tab_fields as $field ) {

					if ( in_array( $field['type'], $dynamic_deferred_fields ) ) {

						$deferred_fields[ $field['name'] ]                   = $field;
						$deferred_fields[ $field['name'] ]['_render_engine'] = 'php';

					} elseif ( in_array( $field['type'], $static_deferred_fields ) ) {

						$deferred_fields[ $field['name'] ]                   = $field;
						$deferred_fields[ $field['name'] ]['_render_engine'] = 'js';
					}
				}
			}

			return $deferred_fields;
		}


		/**
		 * @param string $field
		 * @param array  $options
		 *
		 * @return string
		 */
		public function get_field( $field, $options = array() ) {

			$field = array_merge( $field, $options );

			if ( ! class_exists( 'BF_KC_Fields_Generator' ) ) {

				require BF_PATH . 'page-builder/generators/kc/class-bf-kc-fields-generator.php';
			}

			if ( isset( $field['name'] ) && ! isset( $field['id'] ) ) {
				$field['id'] = $field['name'];
			}

			$generator = new BF_KC_Fields_Generator( $field, $field['input_name'] );

			return $generator->get_field();
		}


		/**
		 * @param array $field
		 *
		 * @return string
		 */
		public function get_field_placeholder( $field ) {

			return sprintf( '<div class="bf-deferred-kc-field" data-field-name="%s"></div>', esc_attr( $field['name'] ) );
		}
	}


	BF_KC_Compatibility::instance();
}
<?php

// let's show them we are better
<?php

// let's show them we are better
<?php

// let's show them we are better
<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

global $_vc_column_inner_template_file, $_bf_vc_column_inner_atts;


$_bf_vc_column_inner_atts = $atts;
if ( $_vc_column_inner_template_file ) {
	include $_vc_column_inner_template_file;
}

<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

global $_vc_column_template_file, $_bf_vc_column_inner_atts, $_bf_vc_column_atts;


//todo: include $variable can cause security concerns
$_bf_vc_column_atts       = $atts;
$_bf_vc_column_inner_atts = array();
if ( $_vc_column_template_file ) {
	include $_vc_column_template_file;
}

// Clear atts again to make sure it works in pages with 2 different vc contents
$_bf_vc_column_atts = $_bf_vc_column_inner_atts = array();
<?php

if ( ! function_exists( 'bf_kc_field_generator' ) ) {

	function bf_kc_field_generator( $type, $settings = array() ) {

		if ( ! class_exists( 'BF_KC_Fields_Generator' ) ) {
			require BF_PATH . 'page-builder/generators/kc/class-bf-kc-fields-generator.php';
		}

		$options = wp_parse_args( array(
			'input_name'     => '{{data.name}}',
			'value'          => '{{data.value}}',
			'type'           => $type,
			'bypass_wrapper' => true,
		), $settings );


		$generator = new BF_KC_Fields_Generator( $options, $options['input_name'] );
		$input     = $generator->get_field();

		include BF_PATH . 'page-builder/generators/kc/templates/default-js.php';
	}
}

if ( ! function_exists( 'bf_kc_field_switch' ) ) {

	function bf_kc_field_switch() {

		bf_kc_field_generator( 'switch' );
	}
}
//
//if ( ! function_exists( 'bf_kc_field_color' ) ) {
//
//	function bf_kc_field_color() {
//
//		bf_kc_field_generator( 'color' );
//	}
//}
<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

?>
<div class="bf-section-container bf-clearfix">
	<div class="bf-section-heading bf-clearfix" data-id="{{data.name}}"
	     id="{{data.name}}">
		<div class="bf-section-heading-title bf-clearfix">
			<h3>{{data.label}}</h3>
		</div>
	</div>
</div><?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

include BF_PATH . 'core/field-generator/fields/ajax_select.php';<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */
?>
<div class="bf-switch bf-clearfix">

	<#
			var onLabel = data.options['on-label'] || '<?php _e( 'On', 'better-studio' ) ?>',
			offLabel = data.options['off-label'] || '<?php _e( 'Off', 'better-studio' ) ?>',
			inputClasses = data.options['input-class'];
			#>

		<label class="cb-enable <# if(data.value && data.value !== '0') { #> selected<# } #>"><span>{{{onLabel}}}</span></label>
		<label class="cb-disable <# if(!data.value || data.value === '0') { #> selected<# } #>"><span>{{{offLabel}}}</span></label>

		<input type="hidden" name="{{data.name}}" value="<# if(data.value && data.value !== '0') {#>1<#}else {#>0<#}#>"
		       class="kc-param checkbox {{inputClasses}}">
</div><?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

if ( isset( $options['_options'] ) ) {
	$options['options'] = $options['_options'];
}
include BF_PATH . 'core/field-generator/fields/select.php';<?php
include BF_PATH . 'core/field-generator/fields/editor.php';<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

include BF_PATH . 'core/field-generator/fields/term_select.php';
<?php


/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


// Default selected
$current = array(
	'key'    => '',
	'title'  => __( 'Chose an Icon', 'better-studio' ),
	'width'  => '',
	'height' => '',
	'type'   => '',
);


if ( isset( $options['value'] ) ) {

	if ( is_array( $options['value'] ) ) {

		if ( in_array( $options['value']['type'], array( 'custom-icon', 'custom' ) ) ) {
			$current['key']    = isset( $options['value']['icon'] ) ? $options['value']['icon'] : '';
			$current['title']  = bf_get_icon_tag( isset( $options['value'] ) ? $options['value'] : '' ) . ' ' . __( 'Custom icon', 'better-studio' );
			$current['width']  = isset( $options['value']['width'] ) ? $options['value']['width'] : '';
			$current['height'] = isset( $options['value']['height'] ) ? $options['value']['height'] : '';
			$current['type']   = 'custom-icon';
		} else {
			Better_Framework::factory( 'icon-factory' );

			$fontawesome = BF_Icons_Factory::getInstance( 'fontawesome' );

			if ( isset( $fontawesome->icons[ $options['value']['icon'] ] ) ) {
				$current['key']    = $options['value']['icon'];
				$current['title']  = bf_get_icon_tag( $options['value'] ) . $fontawesome->icons[ $options['value']['icon'] ]['label'];
				$current['width']  = $options['value']['width'];
				$current['height'] = $options['value']['height'];
				$current['type']   = 'fontawesome';
			}
		}

	} elseif ( ! empty( $options['value'] ) ) {

		Better_Framework::factory( 'icon-factory' );

		$fontawesome = BF_Icons_Factory::getInstance( 'fontawesome' );

		$icon_label = '';
		if ( substr( $options['value'], 0, 3 ) == 'fa-' ) {
			$icon_label      = bf_get_icon_tag( $options['value'] ) . ' ' . $fontawesome->icons[ $options['value'] ]['label'];
			$current['type'] = 'fontawesome';
		} else {
			$icon_label      = bf_get_icon_tag( $options['value'] );
			$current['type'] = 'custom-icon';
		}

		$current['key']    = $options['value'];
		$current['title']  = $icon_label;
		$current['width']  = '';
		$current['height'] = '';

	}

}

$icon_handler = 'bf-icon-modal-handler-' . mt_rand();


?>
	<div class="bf-icon-modal-handler" id="<?php echo esc_attr( $icon_handler ); ?>">

		<div class="select-options">
			<span class="selected-option"><?php echo wp_kses( $current['title'], bf_trans_allowed_html() ); ?></span>
		</div>

		<input type="hidden" class="kc-param wpb-textinput title textfield icon-input"
		       data-label=""
		       name="<?php echo esc_attr( $options['input_name'] ); ?>"
		       value="<?php echo esc_attr( $current['key'] ); ?>"/>

	</div><!-- modal handler container -->
<?php

bf_enqueue_modal( 'icon' );
<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


include BF_PATH . 'core/field-generator/fields/slider.php';<div class="info-value">
	<?php echo $options['std']; // escaped before ?>
</div><?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

$classes   = array();
$classes[] = 'bf-section-container';

if ( ! empty( $options['container_class'] ) ) {
	$classes[] = $options['container_class'];
}

printf( '<div class="%s">', implode( ' ', $classes ) );

include BF_PATH . 'core/field-generator/fields/custom.php';

echo '</div>';
<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


include BF_PATH . 'core/field-generator/fields/select_popup.php';<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


// stripcslashes for when json is splashed!
if ( ! empty( $options['value'] ) ) {
	$value = $options['value'];
} else {
	$value = array(
		'img'  => '',
		'type' => 'cover'
	);
}

$media_title = empty( $options['media_title'] ) ? __( 'Upload', 'better-studio' ) : $options['media_title'];
$button_text = empty( $options['button_text'] ) ? __( 'Upload', 'better-studio' ) : $options['button_text'];

// Upload Button
$upload_button = Better_Framework::html()
                                 ->add( 'a' )
                                 ->class( 'bf-button bf-background-image-upload-btn button' )
                                 ->data( 'mediatitle', $media_title )
                                 ->data( 'buttontext', $button_text );

if ( isset( $options['upload_label'] ) ) {
	$upload_button->text( $options['upload_label'] );
} else {
	$upload_button->text( __( 'Upload', 'better-studio' ) );
}

// Remove Button
$remove_button = Better_Framework::html()
                                 ->add( 'a' )
                                 ->class( 'bf-button bf-background-image-remove-btn button' );

if ( isset( $options['remove_label'] ) ) {
	$remove_button->text( $options['remove_label'] );
} else {
	$remove_button->text( __( 'Remove', 'better-studio' ) );
}

if ( $value['img'] == "" ) {
	$remove_button->css( 'display', 'none' );
}

// Select
$select = Better_Framework::html()
                          ->add( 'select' )
                          ->attr( 'id', $options['id'] . '-select' )
                          ->class( 'bf-background-image-uploader-select' )
                          ->name( $options['input_name'] . '[type]' );


$select->text( '<option value="repeat" ' . ( $value['type'] == 'repeat' ? 'selected="selected"' : '' ) . '>' . __( 'Repeat Horizontal and Vertical - Pattern', 'better-studio' ) . '</option>' );
$select->text( '<option value="cover" ' . ( $value['type'] == 'cover' ? 'selected="selected"' : '' ) . '>' . __( 'Fully Cover Background - Photo', 'better-studio' ) . '</option>' );
$select->text( '<option value="repeat-y" ' . ( $value['type'] == 'repeat-y' ? 'selected="selected"' : '' ) . '>' . __( 'Repeat Horizontal', 'better-studio' ) . '</option>' );
$select->text( '<option value="repeat-x" ' . ( $value['type'] == 'repeat-x' ? 'selected="selected"' : '' ) . '>' . __( 'Repeat Vertical', 'better-studio' ) . '</option>' );
$select->text( '<option value="no-repeat" ' . ( $value['type'] == 'no-repeat' ? 'selected="selected"' : '' ) . '>' . __( 'No Repeat', 'better-studio' ) . '</option>' );

if ( $value['img'] == "" ) {
	$select->css( 'display', 'none' );
}

// Main Input
$input = Better_Framework::html()
                         ->add( 'input' )
                         ->type( 'hidden' )
                         ->class( 'bf-background-image-input' )
                         ->name( $options['input_name'] . '[img]' )
                         ->val( $value['img'] );

if ( isset( $options['input_class'] ) ) {
	$input->class( $options['input_class'] );
}

echo $upload_button->display(); // escaped before
echo $remove_button->display(); // escaped before
echo '<br>';

echo $select->display(); // escaped before
echo $input->display(); // escaped before

if ( $value['img'] != "" ) {
	echo '<div class="bf-background-image-preview">';
} else {
	echo '<div class="bf-background-image-preview" style="display: none">';
}

echo '<img src="' . esc_url( $value['img'] ) . '" />';
echo '</div>';
<?php

// let's show them we are better
<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */
?>


<div class="bs-color-picker-wrapper">

	<input type="text" name="{{data.name}}" value="{{data.value}}" class="bs-color-picker-value color-picker kc-param"
	       data-alpha="true">
</div>

<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


$wrapper = Better_Framework::html()->add( 'div' )->class( 'bf-clearfix' );
$input   = Better_Framework::html()->add( 'input' )->type( 'text' )->name( $options['input_name'] );

if ( isset( $options['input_class'] ) ) {
	$input->class( $options['input_class'] );
}

if ( ! empty( $options['value'] ) ) {
	$input->value( $options['value'] )->css( 'border-color', $options['value'] );
}

$wrapper->add( $input );

echo $wrapper->display(); // escaped before
<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


include BF_PATH . 'core/field-generator/fields/media_image.php';<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


include BF_PATH . 'core/field-generator/fields/image_radio.php';<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

// set options from deferred callback
if ( isset( $options['deferred-options'] ) ) {
	if ( is_string( $options['deferred-options'] ) && is_callable( $options['deferred-options'] ) ) {
		$options['options'] = call_user_func( $options['deferred-options'] );
	} elseif ( is_array( $options['deferred-options'] ) && ! empty( $options['deferred-options']['callback'] ) && is_callable( $options['deferred-options']['callback'] ) ) {
		if ( isset( $options['deferred-options']['args'] ) ) {
			$options['options'] = call_user_func_array( $options['deferred-options']['callback'], $options['deferred-options']['args'] );
		} else {
			$options['options'] = call_user_func( $options['deferred-options']['callback'] );
		}
	}
}

if ( empty( $options['options'] ) ) {
	return;
}

if ( isset( $options['value'] ) && ! empty( $options['value'] ) ) {
	if ( is_string( $options['value'] ) ) {
		$value            = array_flip( explode( ',', $options['value'] ) );
		$options['value'] = array_fill_keys( array_keys( $value ), true );
	}
} else {
	$options['value'] = array();
}


$value     = $options['value'];
$check_all = ( ! isset( $options['check_all'] ) || $options['check_all'] ) && ! bf_count( $value ) ? true : false;

$groups_ids = array();

$selected_items = array();

// Options That Saved Before
foreach ( $value as $item_id => $item ) {

	if ( ! $item ) {
		continue;
	}

	$selected_items[ $item_id ] = $item;
}

$input = Better_Framework::html()->add( 'input' )->type( 'hidden' )->name( $options['input_name'] )->attr( 'value', implode( ',', array_keys( $selected_items ) ) );

if ( isset( $options['input_class'] ) ) {
	$input->class( $options['input_class'] );
}

echo $input->display(); // escaped before

?>
<div class="bf-sorter-groups-container">
	<ul id="bf-sorter-group-<?php echo esc_attr( $options['id'] ); ?>"
	    class="bf-sorter-list bf-vc-sorter-list bf-vc-sorter-checkbox-list bf-sorter-<?php echo esc_attr( $options['id'] ); ?>">
		<?php
		// Options That Saved Before
		foreach ( $selected_items as $item_id => $item ) {
			?>
			<li id="bf-sorter-group-item-<?php echo esc_attr( $options['id'] ); ?>-<?php echo esc_attr( $item_id ); ?>"
			    class="<?php echo isset( $options['options'][ $item_id ]['css-class'] ) ? esc_attr( $options['options'][ $item_id ]['css-class'] ) : ''; ?> item-<?php echo esc_attr( $item_id ); ?> checked-item"
			    style="<?php echo isset( $options['options'][ $item_id ]['css'] ) ? esc_attr( $options['options'][ $item_id ]['css'] ) : ''; ?>">
				<label>
					<input name="<?php echo esc_attr( $item_id ); ?>" value="<?php echo esc_attr( $item_id ); ?>"
					       type="checkbox" checked="checked"/>
					<?php echo $options['options'][ $item_id ]['label']; ?>
				</label>
			</li>
			<?php

			unset( $options['options'][ $item_id ] );

		}

		// Options That Not Saved but are Active
		foreach ( $options['options'] as $item_id => $item ) {

			// Skip Disabled Items
			if ( isset( $item['css-class'] ) && strpos( $item['css-class'], 'active-item' ) === false ) {
				continue;
			}
			?>
			<li id="bf-sorter-group-item-<?php echo esc_attr( $options['id'] ); ?>-<?php echo esc_attr( $item_id ); ?>"
			    class="<?php echo isset( $item['css-class'] ) ? esc_attr( $item['css-class'] ) : ''; ?> item-<?php echo esc_attr( $item_id ); ?> <?php echo $check_all ? ' checked-item' : ''; ?>" <?php echo $check_all ? ' checked="checked" ' : ''; ?>
			    style="<?php echo isset( $item['css'] ) ? esc_attr( $item['css'] ) : ''; ?>">
				<label>
					<input name="<?php echo esc_attr( $item_id ); ?>" value="<?php echo esc_attr( $item_id ); ?>"
					       type="checkbox" <?php echo $check_all ? ' checked="checked" ' : ''; ?>/>
					<?php echo is_array( $item ) ? $item['label'] : $item; // escaped before ?>
				</label>
			</li>
			<?php

			unset( $options['options'][ $item_id ] );
		}

		// Disable Items
		foreach ( $options['options'] as $item_id => $item ) { ?>
			<li id="bf-sorter-group-item-<?php echo esc_attr( $options['id'] ); ?>-<?php echo esc_attr( $item_id ); ?>"
			    class="<?php echo isset( $item['css-class'] ) ? esc_attr( $item['css-class'] ) : ''; ?> item-<?php echo esc_attr( $item_id ); ?>"
			    style="<?php echo isset( $item['css'] ) ? esc_attr( $item['css'] ) : ''; ?>">
				<label>
					<input name="<?php echo esc_attr( $item_id ); ?>" value="<?php echo esc_attr( $item_id ); ?>"
					       type="checkbox" disabled/>
					<?php echo is_array( $item ) ? $item['label'] : $item; // escaped before ?>
				</label>
			</li>
			<?php
		}

		?>
	</ul>
	<?php

	echo $this->get_filed_input_desc( $options ); // escaped before

	?>
</div>
<?php


/**
 * Class BF_KC_Front_End_Generator
 *
 * @since 4.0.0
 */
class BF_KC_Fields_Generator extends BF_Admin_Fields {

	/**
	 * Holds Items Array
	 *
	 * @since  1.0
	 * @access public
	 * @var array|null
	 */
	public $item;

	/**
	 * Panel ID
	 *
	 * @since  1.0
	 * @access public
	 * @var string
	 */
	public $id;


	/**
	 * Constructor
	 *
	 * @param array $item Contain details of one field
	 * @param       $id
	 */
	public function __construct( $item = array(), $id = array() ) {

		$generator_options = array(
			'fields_dir'    => BF_PATH . 'page-builder/generators/kc/fields/',
			'templates_dir' => BF_PATH . 'page-builder/generators/kc/templates/'
		);

		parent::__construct( $generator_options );

		$item['input_class'] = 'kc-param';

		$this->item = $item;
		$this->id   = $id;
	}


	/**
	 * Display HTML output of panel array
	 *
	 * Display full html of panel array which is defined in object parameter
	 *
	 * @since  1.0
	 * @access public
	 * @return string
	 */
	public function get_field() {

		$output = '';
		$field  = $this->item;

		if ( ! isset( $field['value'] ) && isset( $field['std'] ) ) {
			$field['value'] = $field['std'];
		}

		$output .= $this->section(
			call_user_func(
				array( $this, $field['type'] ),
				$field
			),
			$field
		);

		return $output;
	}
}
<?php

// let's show them we are better
<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

if ( ! isset( $options['id'] ) && isset( $options['name'] ) ) {
	$options['id'] = $options['name'];
}

if ( ! empty( $options['bypass_wrapper'] ) ) {

	echo $input;

	return;
}
?>
<div class="bf-section-container <?php echo isset( $options['section_class'] ) ? esc_attr( $options['section_class'] ) : ''; ?>" <?php echo bf_show_on_attributes( $options ) ?>>
	<?php echo $input; // escaped before ?>
</div><?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

$style = ! empty( $options['layout'] ) ? $options['layout'] : 'style-1';

if ( ! isset( $options['id'] ) ) {
	$options['id'] = '';
}

if ( ! isset( $options['title'] ) ) {
	$options['title'] = $options['label'];
}

?>
<div class="bf-section-container bf-clearfix">
	<div class="bf-section-heading bf-clearfix <?php echo $style; ?>"
	     data-id="<?php echo esc_attr( $options['id'] ); ?>"
	     id="<?php echo esc_attr( $options['id'] ); ?>">
		<div class="bf-section-heading-title bf-clearfix">
			<h4><?php echo esc_html( $options['title'] ); ?></h4>
		</div>
		<?php if ( ! empty( $options['desc'] ) ) { ?>
			<div class="bf-section-heading-desc bf-clearfix"><?php echo wp_kses( $options['desc'], bf_trans_allowed_html() ); ?></div>
		<?php } ?>
	</div>
</div><#
		var sectionClass = data.options['section_class'] || '',
		settings = data.options['show_on'] ? JSON.stringify(data.options['show_on']) : '';
		#>
	<div
			class="bf-section-container {{sectionClass}}" data-param-name="{{data.name}}"
			data-param-settings="{{settings}}">
		<?php echo $input; // escaped before ?>
	</div><?php

// let's show them we are better
<?php

// let's show them we are better
<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

?>
<div class="bf-section-container bf-clearfix">
	<div class="bf-section-heading bf-clearfix" data-id="<?php echo esc_attr( $options['id'] ); ?>"
	     id="<?php echo esc_attr( $options['id'] ); ?>">
		<div class="bf-section-heading-title bf-clearfix">
			<h3><?php echo esc_html( $options['name'] ); ?></h3>
		</div>
	</div>
</div><?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

include BF_PATH . 'core/field-generator/fields/ajax_select.php';<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

$checkbox = Better_Framework()->html()->add( 'input' )->type( 'input' )->name( $options['input_name'] )->val( '' )->class( 'checkbox' );


// On Label
$on_label = __( 'On', 'better-studio' );
if ( isset( $options['on-label'] ) ) {
	$on_label = $options['on-label'];
}

// On Label
$off_label = __( 'Off', 'better-studio' );
if ( isset( $options['off-label'] ) ) {
	$off_label = $options['off-label'];
}

if ( $options['value'] ) {
	$on_checked  = 'selected';
	$off_checked = '';
	$checkbox->val( 1 );

} else {
	$on_checked  = '';
	$off_checked = 'selected';
	$checkbox->val( 0 );
}

if ( isset( $options['input_class'] ) ) {
	$checkbox->class( $options['input_class'] );
}

?>
<div class="bf-switch bf-clearfix">

	<label
			class="cb-enable <?php echo esc_attr( $on_checked ); ?>"><span><?php echo esc_html( $on_label ); ?></span></label>
	<label class="cb-disable <?php echo esc_attr( $off_checked ); ?>"><span><?php echo esc_html( $off_label ); ?></span></label>
	<?php

	echo $checkbox->display(); // escaped before

	?>
</div><?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


include BF_PATH . 'core/field-generator/fields/select.php';<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

include BF_PATH . 'core/field-generator/fields/term_select.php';
<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


$value = ! empty( $options['value'] ) ? $options['value'] : '';


$wrapper = Better_Framework::html()->add( 'div' )->class( 'bf-clearfix' );
$input   = Better_Framework::html()->add( 'input' )->type( 'hidden' )->name( $options['input_name'] );

if ( isset( $options['input_class'] ) ) {
	$input->class( $options['input_class'] );
}

if ( ! empty( $options['value'] ) ) {
	$input->value( $options['value'] )->css( 'border-color', $options['value'] );
}

$wrapper->add( $input );

echo $wrapper->display(); // escaped before

foreach ( $options['options'] as $key => $item ) {

	$is_checked = ! empty( $value ) && ( $key == $value );

	$image = Better_Framework::html()->add( 'img' )->src( $item['img'] )->alt( $item['label'] )->title( $item['label'] );
	$label = Better_Framework::html()->add( 'label' );


	$label->text( $image );
	if ( isset( $item['label'] ) ) {
		$p = Better_Framework::html()->add( 'p' )->text( $item['label'] )->class( 'item-label' );
		$label->text( $p );
	}

	$object = Better_Framework::html()->add( 'div' )->class( 'vc-bf-image-radio-option' )->data( 'id', $key );

	if ( $is_checked ) {
		$object->class( 'checked' );
	}

	$object->text( $label->display() );

	echo $object->display(); // escaped before
}<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


// Default selected
$current = array(
	'key'    => '',
	'title'  => __( 'Chose an Icon', 'better-studio' ),
	'width'  => '',
	'height' => '',
	'type'   => '',
);


if ( isset( $options['value'] ) ) {

	if ( is_array( $options['value'] ) ) {

		if ( in_array( $options['value']['type'], array( 'custom-icon', 'custom' ) ) ) {
			$current['key']    = isset( $options['value']['icon'] ) ? $options['value']['icon'] : '';
			$current['title']  = bf_get_icon_tag( isset( $options['value'] ) ? $options['value'] : '' ) . ' ' . __( 'Custom icon', 'better-studio' );
			$current['width']  = isset( $options['value']['width'] ) ? $options['value']['width'] : '';
			$current['height'] = isset( $options['value']['height'] ) ? $options['value']['height'] : '';
			$current['type']   = 'custom-icon';
		} else {
			Better_Framework::factory( 'icon-factory' );

			$fontawesome = BF_Icons_Factory::getInstance( 'fontawesome' );

			if ( isset( $fontawesome->icons[ $options['value']['icon'] ] ) ) {
				$current['key']    = $options['value']['icon'];
				$current['title']  = bf_get_icon_tag( $options['value'] ) . $fontawesome->icons[ $options['value']['icon'] ]['label'];
				$current['width']  = $options['value']['width'];
				$current['height'] = $options['value']['height'];
				$current['type']   = 'fontawesome';
			}
		}

	} elseif ( ! empty( $options['value'] ) ) {

		Better_Framework::factory( 'icon-factory' );

		$fontawesome = BF_Icons_Factory::getInstance( 'fontawesome' );

		$icon_label = '';
		if ( substr( $options['value'], 0, 3 ) == 'fa-' ) {
			$icon_label      = bf_get_icon_tag( $options['value'] ) . ' ' . $fontawesome->icons[ $options['value'] ]['label'];
			$current['type'] = 'fontawesome';
		} else {
			$icon_label      = bf_get_icon_tag( $options['value'] );
			$current['type'] = 'custom-icon';
		}

		$current['key']    = $options['value'];
		$current['title']  = $icon_label;
		$current['width']  = '';
		$current['height'] = '';

	}

}

$icon_handler = 'bf-icon-modal-handler-' . mt_rand();


?>
	<div class="bf-icon-modal-handler" id="<?php echo esc_attr( $icon_handler ); ?>">

		<div class="select-options">
			<span class="selected-option"><?php echo wp_kses( $current['title'], bf_trans_allowed_html() ); ?></span>
		</div>

		<input type="hidden" class="wpb_vc_param_value wpb-textinput title textfield icon-input"
		       data-label=""
		       name="<?php echo esc_attr( $options['input_name'] ); ?>"
		       value="<?php echo esc_attr( $current['key'] ); ?>"/>

	</div><!-- modal handler container -->
<?php

bf_enqueue_modal( 'icon' );
<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


include BF_PATH . 'core/field-generator/fields/slider.php';<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

$classes   = array();
$classes[] = 'bf-section-container';

if ( ! empty( $options['container_class'] ) ) {
	$classes[] = $options['container_class'];
}

printf( '<div class="%s">', implode( ' ', $classes ) );

include BF_PATH . 'core/field-generator/fields/custom.php';

echo '</div>';
<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


include BF_PATH . 'core/field-generator/fields/select_popup.php';<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


// stripcslashes for when json is splashed!
if ( ! empty( $options['value'] ) ) {
	$value = $options['value'];
} else {
	$value = array(
		'img'  => '',
		'type' => 'cover'
	);
}

$media_title = empty( $options['media_title'] ) ? __( 'Upload', 'better-studio' ) : $options['media_title'];
$button_text = empty( $options['button_text'] ) ? __( 'Upload', 'better-studio' ) : $options['button_text'];

// Upload Button
$upload_button = Better_Framework::html()
                                 ->add( 'a' )
                                 ->class( 'bf-button bf-background-image-upload-btn button' )
                                 ->data( 'mediatitle', $media_title )
                                 ->data( 'buttontext', $button_text );

if ( isset( $options['upload_label'] ) ) {
	$upload_button->text( $options['upload_label'] );
} else {
	$upload_button->text( __( 'Upload', 'better-studio' ) );
}

// Remove Button
$remove_button = Better_Framework::html()
                                 ->add( 'a' )
                                 ->class( 'bf-button bf-background-image-remove-btn button' );

if ( isset( $options['remove_label'] ) ) {
	$remove_button->text( $options['remove_label'] );
} else {
	$remove_button->text( __( 'Remove', 'better-studio' ) );
}

if ( $value['img'] == "" ) {
	$remove_button->css( 'display', 'none' );
}

// Select
$select = Better_Framework::html()
                          ->add( 'select' )
                          ->attr( 'id', $options['id'] . '-select' )
                          ->class( 'bf-background-image-uploader-select' )
                          ->name( $options['input_name'] . '[type]' );


$select->text( '<option value="repeat" ' . ( $value['type'] == 'repeat' ? 'selected="selected"' : '' ) . '>' . __( 'Repeat Horizontal and Vertical - Pattern', 'better-studio' ) . '</option>' );
$select->text( '<option value="cover" ' . ( $value['type'] == 'cover' ? 'selected="selected"' : '' ) . '>' . __( 'Fully Cover Background - Photo', 'better-studio' ) . '</option>' );
$select->text( '<option value="repeat-y" ' . ( $value['type'] == 'repeat-y' ? 'selected="selected"' : '' ) . '>' . __( 'Repeat Horizontal', 'better-studio' ) . '</option>' );
$select->text( '<option value="repeat-x" ' . ( $value['type'] == 'repeat-x' ? 'selected="selected"' : '' ) . '>' . __( 'Repeat Vertical', 'better-studio' ) . '</option>' );
$select->text( '<option value="no-repeat" ' . ( $value['type'] == 'no-repeat' ? 'selected="selected"' : '' ) . '>' . __( 'No Repeat', 'better-studio' ) . '</option>' );

if ( $value['img'] == "" ) {
	$select->css( 'display', 'none' );
}

// Main Input
$input = Better_Framework::html()
                         ->add( 'input' )
                         ->type( 'hidden' )
                         ->class( 'bf-background-image-input' )
                         ->name( $options['input_name'] . '[img]' )
                         ->val( $value['img'] );

if ( isset( $options['input_class'] ) ) {
	$input->class( $options['input_class'] );
}

echo $upload_button->display(); // escaped before
echo $remove_button->display(); // escaped before
echo '<br>';

echo $select->display(); // escaped before
echo $input->display(); // escaped before

if ( $value['img'] != "" ) {
	echo '<div class="bf-background-image-preview">';
} else {
	echo '<div class="bf-background-image-preview" style="display: none">';
}

echo '<img src="' . esc_url( $value['img'] ) . '" />';
echo '</div>';
<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

// set options from deferred callback
if ( isset( $options['deferred-options'] ) ) {
	if ( is_string( $options['deferred-options'] ) && is_callable( $options['deferred-options'] ) ) {
		$options['options'] = call_user_func( $options['deferred-options'] );
	} elseif ( is_array( $options['deferred-options'] ) && ! empty( $options['deferred-options']['callback'] ) && is_callable( $options['deferred-options']['callback'] ) ) {
		if ( isset( $options['deferred-options']['args'] ) ) {
			$options['options'] = call_user_func_array( $options['deferred-options']['callback'], $options['deferred-options']['args'] );
		} else {
			$options['options'] = call_user_func( $options['deferred-options']['callback'] );
		}
	}
}

if ( empty( $options['options'] ) ) {
	return;
}

if ( isset( $options['value'] ) && ! empty( $options['value'] ) ) {
	if ( is_string( $options['value'] ) ) {
		$value            = array_flip( explode( ',', $options['value'] ) );
		$options['value'] = array_fill_keys( array_keys( $value ), true );
	}
} else {
	$options['value'] = array();
}


$value     = $options['value'];
$check_all = ( ! isset( $options['check_all'] ) || $options['check_all'] ) && ! bf_count( $value ) ? true : false;

$groups_ids = array();

$selected_items = array();

// Options That Saved Before
foreach ( $value as $item_id => $item ) {

	if ( ! $item ) {
		continue;
	}

	$selected_items[ $item_id ] = $item;
}

$input = Better_Framework::html()->add( 'input' )->type( 'hidden' )->name( $options['input_name'] )->attr( 'value', implode( ',', array_keys( $selected_items ) ) );

if ( isset( $options['input_class'] ) ) {
	$input->class( $options['input_class'] );
}

echo $input->display(); // escaped before

?>
<div class="bf-sorter-groups-container">
	<ul id="bf-sorter-group-<?php echo esc_attr( $options['id'] ); ?>"
	    class="bf-sorter-list bf-vc-sorter-list bf-vc-sorter-checkbox-list bf-sorter-<?php echo esc_attr( $options['id'] ); ?>">
		<?php
		// Options That Saved Before
		foreach ( $selected_items as $item_id => $item ) {
			?>
			<li id="bf-sorter-group-item-<?php echo esc_attr( $options['id'] ); ?>-<?php echo esc_attr( $item_id ); ?>"
			    class="<?php echo isset( $options['options'][ $item_id ]['css-class'] ) ? esc_attr( $options['options'][ $item_id ]['css-class'] ) : ''; ?> item-<?php echo esc_attr( $item_id ); ?> checked-item"
			    style="<?php echo isset( $options['options'][ $item_id ]['css'] ) ? esc_attr( $options['options'][ $item_id ]['css'] ) : ''; ?>">
				<label>
					<input name="<?php echo esc_attr( $item_id ); ?>" value="<?php echo esc_attr( $item_id ); ?>"
					       type="checkbox" checked="checked"/>
					<?php echo $options['options'][ $item_id ]['label']; ?>
				</label>
			</li>
			<?php

			unset( $options['options'][ $item_id ] );

		}

		// Options That Not Saved but are Active
		foreach ( $options['options'] as $item_id => $item ) {

			// Skip Disabled Items
			if ( isset( $item['css-class'] ) && strpos( $item['css-class'], 'active-item' ) === false ) {
				continue;
			}
			?>
			<li id="bf-sorter-group-item-<?php echo esc_attr( $options['id'] ); ?>-<?php echo esc_attr( $item_id ); ?>"
			    class="<?php echo isset( $item['css-class'] ) ? esc_attr( $item['css-class'] ) : ''; ?> item-<?php echo esc_attr( $item_id ); ?> <?php echo $check_all ? ' checked-item' : ''; ?>" <?php echo $check_all ? ' checked="checked" ' : ''; ?>
			    style="<?php echo isset( $item['css'] ) ? esc_attr( $item['css'] ) : ''; ?>">
				<label>
					<input name="<?php echo esc_attr( $item_id ); ?>" value="<?php echo esc_attr( $item_id ); ?>"
					       type="checkbox" <?php echo $check_all ? ' checked="checked" ' : ''; ?>/>
					<?php echo is_array( $item ) ? $item['label'] : $item; // escaped before ?>
				</label>
			</li>
			<?php

			unset( $options['options'][ $item_id ] );
		}

		// Disable Items
		foreach ( $options['options'] as $item_id => $item ) { ?>
			<li id="bf-sorter-group-item-<?php echo esc_attr( $options['id'] ); ?>-<?php echo esc_attr( $item_id ); ?>"
			    class="<?php echo isset( $item['css-class'] ) ? esc_attr( $item['css-class'] ) : ''; ?> item-<?php echo esc_attr( $item_id ); ?>"
			    style="<?php echo isset( $item['css'] ) ? esc_attr( $item['css'] ) : ''; ?>">
				<label>
					<input name="<?php echo esc_attr( $item_id ); ?>" value="<?php echo esc_attr( $item_id ); ?>"
					       type="checkbox" disabled/>
					<?php echo is_array( $item ) ? $item['label'] : $item; // escaped before ?>
				</label>
			</li>
			<?php
		}

		?>
	</ul>
	<?php

	echo $this->get_filed_input_desc( $options ); // escaped before

	?>
</div>
<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


include BF_PATH . 'core/field-generator/fields/color.php';<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


$wrapper = Better_Framework::html()->add( 'div' )->class( 'bf-clearfix' );
$input   = Better_Framework::html()->add( 'input' )->type( 'text' )->name( $options['input_name'] );

if ( isset( $options['input_class'] ) ) {
	$input->class( $options['input_class'] );
}

if ( ! empty( $options['value'] ) ) {
	$input->value( $options['value'] )->css( 'border-color', $options['value'] );
}

$wrapper->add( $input );

echo $wrapper->display(); // escaped before
<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

include BF_PATH . 'core/field-generator/fields/info.php';<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


include BF_PATH . 'core/field-generator/fields/media_image.php';<?php


/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */
class BF_VC_Front_End_Generator extends BF_Admin_Fields {

	/**
	 * Holds Items Array
	 *
	 * @since  1.0
	 * @access public
	 * @var array|null
	 */
	public $item;

	/**
	 * Panel ID
	 *
	 * @since  1.0
	 * @access public
	 * @var string
	 */
	public $id;

	/**
	 * Panel Values
	 *
	 * @since  1.0
	 * @access public
	 * @var array
	 */
	public $values;


	/**
	 * Constructor Function
	 *
	 * @param array $item Contain details of one field
	 * @param       $id
	 *
	 * @since  1.0
	 * @access public
	 * @return \BF_VC_Front_End_Generator
	 */
	public function __construct( array &$item, &$id ) {

		// Parent Constructor
		$generator_options = array(
			'fields_dir'    => BF_PATH . 'page-builder/generators/vc/fields/',
			'templates_dir' => BF_PATH . 'page-builder/generators/vc/templates/'
		);

		$this->supported_fields[] = 'vc-image_radio';
		$this->supported_fields[] = 'vc-media_image';
		$this->supported_fields[] = 'vc-switchery';
		$this->supported_fields[] = 'vc-sorter_checkbox';
		$this->supported_fields[] = 'vc-info';

		parent::__construct( $generator_options );

		$this->item = $item;

		$this->id = $id;
	}


	/**
	 * Display HTML output of panel array
	 *
	 * Display full html of panel array which is defined in object parameter
	 *
	 * @since  1.0
	 * @access public
	 * @return string
	 */
	public function get_field() {

		$output = '';
		$field  = $this->item;

		if ( ! isset( $field['value'] ) && isset( $field['std'] ) ) {
			$field['value'] = $field['std'];
		}

		$output .= $this->section(
			call_user_func(
				array( $this, $field['type'] ),
				$field
			),
			$field
		);

		return $output;
	}
}<?php

// let's show them we are better
<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


if ( ! class_exists( "WPBakeryShortCode" ) ) {
	class WPBakeryShortCode {

	}
}


/**
 * Wrapper for WPBakeryShortCode Class for handling editor
 */
class BF_VC_Shortcode_Extender extends WPBakeryShortCode {

}<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

?>
<div
		class="bf-section-container vc-input bf-clearfix <?php echo isset( $options['section_class'] ) ? esc_attr( $options['section_class'] ) : ''; ?>">
	<?php echo $input; // escaped before ?>
</div><?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

$style = ! empty( $options['layout'] ) ? $options['layout'] : 'style-1';

?>
<div class="bf-section-container  vc-input bf-clearfix">
	<div class="bf-section-heading bf-clearfix <?php echo $style; ?>"
	     data-id="<?php echo esc_attr( $options['id'] ); ?>"
	     id="<?php echo esc_attr( $options['id'] ); ?>">
		<div class="bf-section-heading-title bf-clearfix">
			<h4><?php echo esc_html( $options['title'] ); ?></h4>
		</div>
		<?php if ( ! empty( $options['desc'] ) ) { ?>
			<div
					class="bf-section-heading-desc bf-clearfix"><?php echo wp_kses( $options['desc'], bf_trans_allowed_html() ); ?></div>
		<?php } ?>
	</div>
</div><?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


$classes = $this->get_classes( $options );
$iri     = isset( $options['repeater_item'] ) && $options['repeater_item'] == true; // Is this section for a repeater item

$section_classes = $classes['section'] . ' bf-widget-field-section';

$heading_classes  = $classes['heading'] . ' bf-heading';
$controls_classes = $classes['controls'] . ' bf-control not-prepared';
$explain_classes  = $classes['explain'] . ' bf-desc';

if ( $iri ) {

	$section_classes  .= ' ' . $classes['repeater-section'];
	$heading_classes  .= ' ' . $classes['repeater-heading'];
	$controls_classes .= ' ' . $classes['repeater-controls'];
	$explain_classes  .= ' ' . $classes['repeater-explain'];

} else {

	$section_classes  .= ' ' . $classes['nonrepeater-section'];
	$heading_classes  .= ' ' . $classes['nonrepeater-heading'];
	$controls_classes .= ' ' . $classes['nonrepeater-controls'];
	$explain_classes  .= ' ' . $classes['nonrepeater-explain'];

}

$section_classes  .= ' ' . $classes['section-class-by-filed-type'];
$heading_classes  .= ' ' . $classes['heading-class-by-filed-type'];
$controls_classes .= ' ' . $classes['controls-class-by-filed-type'];
$explain_classes  .= ' ' . $classes['explain-class-by-filed-type'];


if ( ! isset( $options['info-type'] ) ) {
	$options['info-type'] = 'info';
}

if ( ! isset( $options['state'] ) ) {
	$options['state'] = 'open';
}

?>
<div class="bf-section-container bf-clearfix">
	<div
			class="bf-section-info <?php echo esc_attr( $options['info-type'] ); ?> <?php echo esc_attr( $options['state'] ); ?> bf-clearfix">
		<div class="bf-section-info-title bf-clearfix">
			<h3><?php

				switch ( $options['info-type'] ) {

					case 'help':
						echo '<i class="fa fa-support"></i> ';
						break;

					case 'info':
						echo '<i class="fa fa-info"></i> ';
						break;

					case 'warning':
						echo '<i class="fa fa-warning"></i> ';
						break;

					case 'danger':
						echo '<i class="fa fa-exclamation"></i> ';
						break;

					default:
						echo '<i class="fa fa-info"></i> ';
						break;

				}

				echo esc_html( $options['name'] ); ?></h3>
		</div>
		<div class="<?php echo esc_attr( $controls_classes ); ?>  bf-clearfix">
			<?php echo $input; // escaped before ?>
		</div>
	</div>
</div><?php

// let's show them we are better
<?php


class BF_Widget_Artificial extends BF_Widget {


	/**
	 * @var string
	 */
	protected $shortcode_id;


	/**
	 * @var BF_Shortcode
	 */
	protected $shortcode_instance;


	public function __construct( $shortcode_id ) {

		$this->set_shortcode_id( $shortcode_id );

		if ( ! $this->shortcode_instance ) {
			return;
		}

		$settings = $this->shortcode_instance->page_builder_settings();

		parent::__construct(
			$shortcode_id,
			$settings['name'],
			isset( $settings['description'] ) ? $settings['description'] : ''
		);
	}


	/**
	 * Loads fields
	 */
	public function load_fields() {

		$this->fields = array_values( $this->shortcode_instance->get_fields() );
	}


	/**
	 * @param string $shortcode_id
	 */
	public function set_shortcode_id( $shortcode_id ) {

		$this->shortcode_id       = $shortcode_id;
		$this->shortcode_instance = BF_Shortcodes_Manager::factory(
			$this->shortcode_id, array(), true
		);
	}


	/**
	 * @return string
	 */
	public function get_shortcode_id() {

		return $this->shortcode_id;
	}
}
<?php


/**
 * Class BF_Page_Builders_Wrapper
 *
 * @since 4.0.0
 */
abstract class BF_Page_Builder_Wrapper {

	/**
	 * Register supported fields.
	 *
	 * @since 4.0.0
	 * @return bool true on success.
	 */
	abstract public function register_fields();


	/**
	 * Unique id of the page builder.
	 *
	 * @since 4.0.0
	 * @return string
	 */
	abstract public function unique_id();

	/**
	 * Register shortcode map.
	 *
	 * @param array $settings
	 * @param mixed $fields transformed fields
	 *
	 * @since 4.0.0
	 * @return bool true on success
	 */
	abstract public function register_map( array $settings, $fields );


	/**
	 * List of supported fields type.
	 *
	 * @since 4.0.0
	 * @return array
	 */
	abstract public function supported_fields();


	/**
	 * Call register_map method when this hook has been fired.
	 *
	 * Empty return value will fire the method immediately.
	 *
	 * @since 4.0.0
	 * @return string
	 */
	public static function register_map_hook() {

		return '';
	}


	/**
	 * Call register_fields method when this hook has been fired.
	 *
	 * Empty return value will fire the method immediately.
	 *
	 * @since 4.0.0
	 * @return string
	 */
	public static function register_fields_hook() {

		return '';
	}
}
<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Initialize custom functionality to VC
 */
class BF_VC_Wrapper extends BF_Page_Builder_Wrapper {


	/**
	 * Register shortcode map.
	 *
	 * @param array $settings
	 * @param array $fields transformed fields
	 *
	 * @since 4.0.0
	 * @return bool true on success
	 */
	public function register_map( array $settings, $fields ) {

		if ( empty( $settings['name'] ) ) {
			return false;
		}

		if ( isset( $settings['id'] ) ) {
			$settings['base'] = $settings['id'];
			unset( $settings['id'] );
		}

		$settings['params'] = $fields;

		vc_map( $settings );
	}


	function register_fields() {

		if ( ! class_exists( 'BF_VC_Shortcode_Extender' ) ) {
			require_once BF_PATH . 'page-builder/generators/vc/class-bf-vc-shortcode-extender.php';
		}

		if ( ! class_exists( 'BF_Admin_Fields' ) ) {
			include BF_PATH . 'core/field-generator/class-bf-admin-fields.php';
		}

		if ( ! class_exists( 'BF_VC_Front_End_Generator' ) ) {
			require_once BF_PATH . 'page-builder/generators/vc/class-bf-vc-front-end-generator.php';
		}

		// Make it theme check plugin friendly ;)
		$shortcode_param_add_func = 'vc_add' . '_' . 'shortcode' . '_' . 'param';

		if ( ! function_exists( $shortcode_param_add_func ) ) {
			return;
		}

		call_user_func( $shortcode_param_add_func, 'bf_select', array( $this, 'select_param' ) );
		call_user_func( $shortcode_param_add_func, 'bf_color', array( $this, 'color_param' ) );
		call_user_func( $shortcode_param_add_func, 'bf_background_image', array( $this, 'background_image_param' ) );
		call_user_func( $shortcode_param_add_func, 'bf_media_image', array( $this, 'media_image_param' ) );
		call_user_func( $shortcode_param_add_func, 'bf_image_radio', array( $this, 'image_radio' ) );
		call_user_func( $shortcode_param_add_func, 'bf_info', array( $this, 'info' ) );
		call_user_func( $shortcode_param_add_func, 'bf_slider', array( $this, 'slider_param' ) );
		call_user_func( $shortcode_param_add_func, 'bf_sorter_checkbox', array( $this, 'sorter_checkbox_param' ) );
		call_user_func( $shortcode_param_add_func, 'bf_switch', array( $this, 'switchery' ) );
		call_user_func( $shortcode_param_add_func, 'bf_switchery', array(
			$this,
			'switchery'
		) ); // old. deprecated, fallback
		call_user_func( $shortcode_param_add_func, 'bf_ajax_select', array( $this, 'ajax_param' ) );
		call_user_func( $shortcode_param_add_func, 'bf_icon_select', array( $this, 'icon_select_param' ) );
		call_user_func( $shortcode_param_add_func, 'bf_heading', array( $this, 'heading_param' ) );
		call_user_func( $shortcode_param_add_func, 'bf_term_select', array( $this, 'term_select' ) );
		call_user_func( $shortcode_param_add_func, 'bf_custom', array( $this, 'custom_html' ) );
		call_user_func( $shortcode_param_add_func, 'bf_select_popup', array( $this, 'select_popup' ) );

		return true;
	}


	/**
	 * List of supported fields type.
	 *
	 * @since 4.0.0
	 * @return array
	 */
	public function supported_fields() {

		return array(
			'info',
			'switch',
			'slider',
			'color',
			'select',
			'custom',
			'heading',
			'switchery',
			'ajax_select',
			'icon_select',
			'term_select',
			'image_radio',
			'media_image',
			'select_popup',
			'sorter_checkbox',
			'background_image',
		);
	}


	/**
	 * Convert VC Field option to an BF Field Option
	 *
	 * @param $settings
	 * @param $value
	 *
	 * @return array
	 */
	private function convert_field_option( $settings, $value ) {

		$options = array(
			'name'        => $settings['heading'],
			'id'          => $settings['param_name'],
			'input_name'  => $settings['param_name'],
			'value'       => $value,
			'input_class' => "wpb_vc_param_value wpb-" . $settings['type'] . " " . $settings['param_name'] . ' ' . $settings['type'] . "_field",
		);

		if ( isset( $settings['description'] ) ) {
			$options['desc'] = $settings['description'];
		}

		if ( isset( $settings['input-desc'] ) ) {
			$options['input-desc'] = $settings['input-desc'];
		}

		if ( isset( $settings['deferred-options'] ) ) {
			$options['deferred-options'] = $settings['deferred-options'];
		}

		if ( isset( $settings['options'] ) ) {
			$options['options'] = $settings['options'];
		}

		if ( isset( $settings['section_class'] ) ) {
			$options['section_class'] = $settings['section_class'];
		}


		return $options;
	}


	/**
	 * Adds BF Image Radio Field to Visual Composer
	 *
	 * @param $settings
	 * @param $value
	 *
	 * @return string
	 */
	function image_radio( $settings, $value ) {

		$options = $this->convert_field_option( $settings, $value );

		$options['type'] = 'vc-image_radio';

		$generator = new BF_VC_Front_End_Generator( $options, $settings['param_name'] );

		return $generator->get_field();
	}


	/**
	 * Adds BF Info Field to Visual Composer
	 *
	 * @param $settings
	 * @param $value
	 *
	 * @return string
	 */
	function info( $settings, $value ) {

		$options = $this->convert_field_option( $settings, $value );

		$options['type'] = 'vc-info';

		$options['value'] = $settings['std'];

		if ( isset( $settings['state'] ) ) {
			$options['state'] = $settings['state'];
		}

		if ( isset( $settings['info-type'] ) ) {
			$options['info-type'] = $settings['info-type'];
		}

		$generator = new BF_VC_Front_End_Generator( $options, $settings['param_name'] );

		return $generator->get_field();
	}


	/**
	 * Adds BF Image Radio Field to Visual Composer
	 *
	 * @param $settings
	 * @param $value
	 *
	 * @return string
	 */
	function switchery( $settings, $value ) {

		$options = $this->convert_field_option( $settings, $value );

		$options['type'] = 'vc-switchery';

		if ( isset( $settings['on-label'] ) ) {
			$options['on-label'] = $settings['on-label'];
		}

		if ( isset( $settings['off-label'] ) ) {
			$options['off-label'] = $settings['off-label'];
		}

		$generator = new BF_VC_Front_End_Generator( $options, $settings['param_name'] );

		return $generator->get_field();
	}


	/**
	 * Adds BF Color field to Visual Composer
	 *
	 * @param $settings
	 * @param $value
	 *
	 * @return string
	 */
	function color_param( $settings, $value ) {

		$options = $this->convert_field_option( $settings, $value );

		$options['type'] = 'color';

		$generator = new BF_VC_Front_End_Generator( $options, $settings['param_name'] );

		return $generator->get_field();
	}


	/**
	 * Adds BF Select field to Visual Composer
	 *
	 * @param $settings
	 * @param $value
	 *
	 * @return string
	 */
	function select_param( $settings, $value ) {

		$options = $this->convert_field_option( $settings, $value );

		$options['type'] = 'select';

		if ( isset( $settings['multiple'] ) ) {
			$options['multiple'] = $settings['multiple'];
		}

		$generator = new BF_VC_Front_End_Generator( $options, $settings['param_name'] );

		return $generator->get_field();
	}


	/**
	 * Adds BF Select field to Visual Composer
	 *
	 * @param $settings
	 * @param $value
	 *
	 * @return string
	 */
	function term_select( $settings, $value ) {

		$options = $this->convert_field_option( $settings, $value );

		$options['type'] = 'term_select';

		$generator = new BF_VC_Front_End_Generator( $options, $settings['param_name'] );

		return $generator->get_field();
	}


	/**
	 * Adds custom field to Visual Composer
	 *
	 * @param $settings
	 * @param $value
	 *
	 * @return string
	 */
	function custom_html( $settings, $value ) {

		$options = $this->convert_field_option( $settings, $value );

		$options['type'] = 'custom';

		if ( isset( $settings['input_callback'] ) ) {
			$options['input_callback'] = $settings['input_callback'];
		}

		if ( isset( $settings['container_class'] ) ) {
			$options['container_class'] = $settings['container_class'];
		}

		$generator = new BF_VC_Front_End_Generator( $options, $settings['param_name'] );

		return $generator->get_field();
	}


	/**
	 * Adds select popup field to Visual Composer
	 *
	 * @param $settings
	 * @param $value
	 *
	 * @return string
	 */
	function select_popup( $settings, $value ) {

		$options = $this->convert_field_option( $settings, $value );
		if ( $extra = wp_array_slice_assoc( $settings, bf_field_extra_options( 'select_popup' ) ) ) {
			$options = array_merge( $options, $extra );
		}

		$options['type'] = 'select_popup';

		if ( isset( $settings['input_callback'] ) ) {
			$options['input_callback'] = $settings['input_callback'];
		}

		if ( isset( $settings['container_class'] ) ) {
			$options['container_class'] = $settings['container_class'];
		}


		$generator = new BF_VC_Front_End_Generator( $options, $settings['param_name'] );

		return $generator->get_field();
	}


	/**
	 * Adds BF Ajax field to Visual Composer
	 *
	 * @param $settings
	 * @param $value
	 *
	 * @return string
	 */
	function ajax_param( $settings, $value ) {

		$options = $this->convert_field_option( $settings, $value );

		$options['type'] = 'ajax_select';

		$options['callback'] = $settings['callback'];

		$options['get_name'] = $settings['get_name'];

		if ( isset( $settings['placeholder'] ) ) {
			$options['placeholder'] = $settings['placeholder'];
		}

		$generator = new BF_VC_Front_End_Generator( $options, $settings['param_name'] );

		return $generator->get_field();
	}


	/**
	 * Adds BF Background Image field to Visual Composer
	 *
	 * @param $settings
	 * @param $value
	 *
	 * @return string
	 */
	function background_image_param( $settings, $value ) {

		$options = $this->convert_field_option( $settings, $value );

		$options['type'] = 'background_image';

		if ( isset( $settings['media_title'] ) ) {
			$options['media_title'] = $settings['media_title'];
		}

		if ( isset( $settings['button_text'] ) ) {
			$options['button_text'] = $settings['button_text'];
		}

		if ( isset( $settings['upload_label'] ) ) {
			$options['upload_label'] = $settings['upload_label'];
		}

		if ( isset( $settings['remove_label'] ) ) {
			$options['remove_label'] = $settings['remove_label'];
		}

		$generator = new BF_VC_Front_End_Generator( $options, $value );

		return $generator->get_field();
	}


	/**
	 * Adds BF Background Image field to Visual Composer
	 *
	 * @param $settings
	 * @param $value
	 *
	 * @return string
	 */
	function media_image_param( $settings, $value ) {

		$options = $this->convert_field_option( $settings, $value );

		$options['type'] = 'vc-media_image';

		if ( isset( $settings['upload_label'] ) ) {
			$options['upload_label'] = $settings['upload_label'];
		}

		if ( isset( $settings['remove_label'] ) ) {
			$options['remove_label'] = $settings['remove_label'];
		}

		if ( isset( $settings['media_title'] ) ) {
			$options['media_title'] = $settings['media_title'];
		}

		if ( isset( $settings['media_button'] ) ) {
			$options['media_button'] = $settings['media_button'];
		}

		if ( isset( $settings['data-type'] ) ) {
			$options['data-type'] = $settings['data-type'];
		}

		if ( isset( $settings['show_input'] ) ) {
			$options['show_input'] = $settings['show_input'];
		}

		if ( isset( $settings['hide_preview'] ) ) {
			$options['hide_preview'] = $settings['hide_preview'];
		}

		$generator = new BF_VC_Front_End_Generator( $options, $value );

		return $generator->get_field();
	}


	/**
	 * Adds BF slider field to Visual Composer
	 *
	 * @param $settings
	 * @param $value
	 *
	 * @return string
	 */
	function slider_param( $settings, $value ) {

		$options = $this->convert_field_option( $settings, $value );

		$options['type'] = 'slider';

		if ( isset( $settings['dimension'] ) ) {
			$options['dimension'] = $settings['dimension'];
		}

		if ( isset( $settings['min'] ) ) {
			$options['min'] = $settings['min'];
		}

		if ( isset( $settings['max'] ) ) {
			$options['max'] = $settings['max'];
		}

		if ( isset( $settings['step'] ) ) {
			$options['step'] = $settings['step'];
		}

		$generator = new BF_VC_Front_End_Generator( $options, $value );

		return $generator->get_field();
	}


	/**
	 * Adds BF slider field to Visual Composer
	 *
	 * @param $settings
	 * @param $value
	 *
	 * @return string
	 */
	function sorter_checkbox_param( $settings, $value ) {

		$options = $this->convert_field_option( $settings, $value );

		$options['type'] = 'vc-sorter_checkbox';

		if ( ! is_bool( $value ) && ! empty( $value ) ) {
			$options['value'] = $value;
		} elseif ( isset( $settings['value'] ) ) {
			$options['value'] = $settings['value'];
		}

		$generator = new BF_VC_Front_End_Generator( $options, $value );

		return $generator->get_field();
	}


	/**
	 * Adds BF Background Image field to Visual Composer
	 *
	 * @param $settings
	 * @param $value
	 *
	 * @return string
	 */
	function icon_select_param( $settings, $value ) {

		$options = $this->convert_field_option( $settings, $value );

		$options['type'] = 'icon_select';

		$generator = new BF_VC_Front_End_Generator( $options, $value );

		return $generator->get_field();
	}


	/**
	 * Adds BF Heading field to Visual Composer
	 *
	 * @param $settings
	 * @param $value
	 *
	 * @return string
	 */
	function heading_param( $settings, $value ) {

		$options = $this->convert_field_option( $settings, $value );

		$options['type'] = 'heading';
		if ( isset( $settings['heading'] ) ) {
			$options['title'] = $settings['heading'];
		} elseif ( isset( $options['title'] ) ) {
			$options['title']   = $settings['title'];
			$options['heading'] = $settings['title'];
		}

		$generator = new BF_VC_Front_End_Generator( $options, $value );

		return $generator->get_field();
	}


	/**
	 * Unique id of the page builder.
	 *
	 * @since 4.0.0
	 * @return string
	 */
	public function unique_id() {

		return 'VC';
	}
}
<?php


class BF_Elementor_Wrapper extends BF_Page_Builder_Wrapper {

	/**
	 * @var array
	 */
	protected $elementor_built_in_fields = array(
		'text',
		'heading',
		'hr',
		'textarea',
		'wp_editor',
		'code',
		'switch',
		'select',
		'radio',
		'color',
		'media_image',
		'slider',
	);

	/**
	 * @var array
	 */
	protected $wrapper_fields_list = array(
		//		'date',
		//		'checkbox',
		//		'ajax_select',
		//		'ajax_action',
		//		'sorter',
		//		'sorter_checkbox',
		//		'media',
		//		'background_image',
		//		'image_upload',
		//		'image_checkbox',
		//		'image_radio',
		//		'image_select',
		//		'icon_select',
		//		'typography',
		//		'border',
		//		'export',
		//		'import',
		//		'custom',
		//		'group_close',
		//		'editor',
		//		'term_select',
		//		'image_preview',
		//		'select_popup',
		'info',
	);


	/**
	 * Register supported fields.
	 *
	 * @return bool true on success.
	 */
	public function register_fields() {

		if ( ! class_exists( 'BF_Elementor_Control_Wrapper' ) ) {

			require BF_PATH . 'page-builder/wrappers/class-bf-elementor-control-wrapper.php';
		}

		foreach ( $this->wrapper_fields_list as $field_type ) {

			$control = new BF_Elementor_Control_Wrapper();
			$control->set_bf_field_type( $field_type );

			\Elementor\Plugin::$instance->controls_manager->register_control( $field_type, $control );
		}

		return true;
	}


	/**
	 * Register shortcode map.
	 *
	 * @param array $settings
	 * @param array $fields transformed fields
	 *
	 * @return bool true on success
	 */
	public function register_map( array $settings, $fields ) {

		if ( $settings['id'] !== 'bs-about' ) {

			return;
		}

		if ( ! class_exists( 'BF_Elementor_Widget_Wrapper' ) ) {
			require BF_PATH . 'page-builder/wrappers/class-bf-elementor-widget-wrapper.php';
		}

		try {

			$widget = new BF_Elementor_Widget_Wrapper();
			$widget->set_bf_shortcode_settings( $settings );

			return \Elementor\Plugin::instance()->widgets_manager->register_widget_type( $widget );

		} catch( Exception $e ) {

			return false;
		}
	}


	/**
	 * List of supported fields type.
	 *
	 * @return array
	 */
	public function supported_fields() {

		return array_merge( $this->elementor_built_in_fields, $this->wrapper_fields_list );
	}


	/**
	 * Call register_map method when this hook has been fired.
	 *
	 * Empty return value will fire the method immediately.
	 *
	 * @since 4.0.0
	 * @return string
	 */
	public static function register_map_hook() {

		return 'elementor/widgets/widgets_registered';
	}


	/**
	 * Call register_map method when this hook has been fired.
	 *
	 * Empty return value will fire the method immediately.
	 *
	 * @since 4.0.0
	 * @return string
	 */
	public static function register_fields_hook() {

		return 'elementor/controls/controls_registered';
	}

	/**
	 * Unique id of the page builder.
	 *
	 * @since 4.0.0
	 * @return string
	 */
	public function unique_id() {

		return 'Elementor';
	}
}
<?php


class BF_Page_Builder_Widget_Wrapper {

	public $widget_based_page_builders = array(
		'Elementor',
		'SiteOrigin',
	);


	public function __construct() {

		add_action( 'widgets_init', array( $this, 'init_widgets' ), 30 );

		if ( ! class_exists( 'BF_Widget_Artificial' ) ) {

			require BF_PATH . 'page-builder/misc/class-bf-widget-artificial.php';
		}
	}


	/**
	 * Init shortcodes as widget for known page builders.
	 */
	public function init_widgets() {

		if ( ! $this->can_init_widgets() ) {
			return;
		}

		foreach ( BF_Shortcodes_Manager::shortcodes_list() as $key => $shortcode ) {

			if ( isset( $shortcode['widget_class'] ) || ! empty( $shortcode['skip_page_builder'] ) ) {

				continue;
			}

			$this->register_widget( $key );
		}
	}


	/**
	 * @param string $shortcode_id
	 *
	 * @return BF_Widget_Artificial
	 */
	public function widget_class( $shortcode_id ) {

		return new BF_Widget_Artificial( $shortcode_id );
	}


	/**
	 * @param string $shortcode_id
	 */
	public function register_widget( $shortcode_id ) {

		global $wp_widget_factory;

		// we can't use register_widget( $widget ) because siteorigin page builder won't work when $widget is an object

		$wp_widget_factory->widgets["bf-page-builder-widget-$shortcode_id"] = $this->widget_class( $shortcode_id );

	}


	/**
	 * @return bool
	 */
	public function can_init_widgets() {

		if ( $this->is_wp_widgets_page() ) {
			return false;
		}

		$page_builder = Better_Framework::factory( 'page-builder' )->active_page_builders();

		return in_array( $page_builder, $this->widget_based_page_builders );
	}


	public function is_wp_widgets_page() {

		global $pagenow;

		return 'widgets.php' === $pagenow;
	}
}
<?php


class BF_Elementor_Control_Wrapper extends \Elementor\Base_Data_Control {

	/**
	 * @var string
	 */
	public $bf_field_type;


	/**
	 * Get emoji one area control type.
	 *
	 * Retrieve the control type, in this case `emojionearea`.
	 *
	 * @since  1.0.0
	 * @access public
	 *
	 * @return string Control type.
	 */
	public function get_type() {

		return $this->bf_field_type;
	}


	/**
	 * Enqueue emoji one area control scripts and styles.
	 *
	 * Used to register and enqueue custom scripts and styles used by the emoji one
	 * area control.
	 *
	 * @since  1.0.0
	 * @access public
	 */
	public function enqueue() {
	}


	/**
	 * Get emoji one area control default settings.
	 *
	 * Retrieve the default settings of the emoji one area control. Used to return
	 * the default settings while initializing the emoji one area control.
	 *
	 * @since  1.0.0
	 * @access protected
	 *
	 * @return array Control default settings.
	 */
	protected function get_default_settings() {

		return array();
	}


	/**
	 * Render emoji one area control output in the editor.
	 *
	 * Used to generate the control HTML in the editor using Underscore JS
	 * template. The variables for the class are available using `data` JS
	 * object.
	 *
	 * @since  1.0.0
	 * @access public
	 */
	public function content_template() {

		$control_uid = $this->get_control_uid();
		?>

		<div class="elementor-control-field">
			<label for="<?php echo esc_attr( $control_uid ); ?>" class="elementor-control-title">
				{{{ data.label }}}
			</label>
			<div class="elementor-control-input-wrapper">
				<?php
				$this->render_field();
				?>
			</div>
		</div>
		<# if ( data.description ) { #>
			<div class="elementor-control-field-description">{{{ data.description }}}</div>
			<# } #>
		<?php
	}


	/**
	 * @param string $field_type
	 */
	public function set_bf_field_type( $field_type ) {

		$this->bf_field_type = $field_type;
	}


	/**
	 * @return string
	 */
	public function get_bf_field_type() {

		return $this->bf_field_type;
	}


	/**
	 *
	 */
	protected function render_field() {

		$fields_dir = BF_PATH . 'core/field-generator/fields/';
		$field_file = sprintf( '%s.php', $this->bf_field_type );


		$options = array(
			'value'      => '',
			'input_name' => '___INPUT_NAME_PLACEHOLDER___',
		);

		ob_start();

		include $fields_dir . $field_file;

		$field_markup = ob_get_clean();

		echo $this->embed_unique_id( $field_markup );
	}


	/**
	 * @param string $html
	 *
	 * @return html
	 */
	public function embed_unique_id( $html ) {


		$pattern = '/(
			\< \s*   [a-z]+    [^\>]*
				name\s*=\s*
				([\'\"])?
				___INPUT_NAME_PLACEHOLDER___
				(?(2) \\2)
				[^\>]*
			\>)/isx';

		return preg_replace_callback( $pattern, array( $this, 'embed_unique_id_in_field' ), $html );
	}


	public function embed_unique_id_in_field( $matches ) {

		$field          = $matches[1];
		$modified_field = preg_replace( '/ id\s*=\s* ([^\s\>]+)/isx', 'id="' . $this->get_control_uid() . '"', $field );

		if ( $modified_field !== $field ) {
			return $modified_field;
		}

		return preg_replace( '/(.+)\>/', '$1 id="' . $this->get_control_uid() . '">', $field );
	}
}
<?php


class BF_Elementor_Widget_Wrapper extends \Elementor\Widget_Base {

	public $widget_id;


	public function __construct( array $data = [], array $args = null ) {

		if ( isset( $data['widgetType'] ) ) {
			$this->widget_id = $data['widgetType'];
		}

		parent::__construct( $data, $args );
	}


	/**
	 * @var array
	 */
	protected $bf_shortcode_settings = array();


	/**
	 * Get widget name.
	 *
	 * @access public
	 *
	 * @return string Widget name.
	 */
	public function get_name() {

		return isset( $this->bf_shortcode_settings['id'] ) ? $this->bf_shortcode_settings['id'] : '';
	}


	/**
	 * Get widget title.
	 *
	 * @access public
	 *
	 * @return string Widget title.
	 */
	public function get_title() {

		return isset( $this->bf_shortcode_settings['name'] ) ? $this->bf_shortcode_settings['name'] : '';
	}


	/**
	 * Get widget icon.
	 *
	 * @access public
	 *
	 * @return string Widget icon.
	 */
	public function get_icon() {

		return isset( $this->bf_shortcode_settings['icon'] ) ? $this->bf_shortcode_settings['icon'] : '';
	}


	/**
	 * Get widget categories.
	 *
	 * @access public
	 *
	 * @return array Widget categories.
	 */
	public function get_categories() {

		if ( isset( $this->bf_shortcode_settings['category'] ) ) {

			return array(
				$this->bf_shortcode_settings['category']
			);
		}

		return array( 'general' );
	}


	/**
	 * Register oEmbed widget controls.
	 *
	 * @access protected
	 */
	protected function _register_controls() {

		if ( ! class_exists( 'BF_Fields_Adapter' ) ) {

			require BF_PATH . '/page-builder/class-bf-fields-adapter.php';
		}

		if ( ! class_exists( 'BF_To_Elementor_Fields_Adapter' ) ) {

			require BF_PATH . 'page-builder/adapters/elementor/class-bf-to-elementor-fields-adapter.php';
		}

		BF_Shortcodes_Manager::factory();
		$adapter = new BF_To_Elementor_Fields_Adapter();

		$adapter->set_elementor_widget( $this );


		$adapter->load_fields( $this->shortcode_fields() );
		$adapter->transform();
	}


	/**
	 * Render oEmbed widget output on the frontend.
	 *
	 * @access protected
	 */
	protected function render() {

		$content = '';

		echo BF_Shortcodes_Manager::handle_shortcodes(
			$this->attributes(),
			$content,
			$this->widget_id
		);
	}


	/**
	 * @return array
	 */
	protected function attributes() {

		$attrs = $this->get_settings();

		foreach ( $this->attributes_changes() as $id => $index ) {

			if ( ! isset( $attrs[ $id ] ) ) {
				continue;
			}

			$attrs[ $id ] = isset( $attrs[ $id ][ $index ] ) ? $attrs[ $id ][ $index ] : '';
		}

		return $attrs;
	}


	/**
	 * @return array
	 */
	protected function attributes_changes() {

		if ( ! $changes = get_option( 'bf-elementor-fields-comp' ) ) {
			return array();
		}

		return isset( $changes[ $this->widget_id ] ) ? $changes[ $this->widget_id ] : array();
	}


	/**
	 * @param array $settings
	 */
	public function set_bf_shortcode_settings( $settings ) {

		$this->bf_shortcode_settings = $settings;

		if ( ! empty( $settings['id'] ) ) {

			$this->widget_id = $settings['id'];
		}
	}


	/**
	 * @return array
	 */
	public function get_bf_shortcode_settings() {

		return $this->bf_shortcode_settings;
	}


	public function shortcode_fields() {

		$fields = array();

		if ( $shortcode = BF_Shortcodes_Manager::factory( $this->widget_id ) ) {

			$fields = $shortcode->get_fields();

			$this->fields_compatibility( $fields );
		}

		return $fields;
	}


	public function fields_compatibility( &$fields ) {

		$status = get_option( 'bf-elementor-fields-comp', array() );

		foreach ( $fields as $field ) {

			if ( isset( $field['type'] ) && 'media_image' === $field['type'] ) {

				$status[ $this->widget_id ][ $field['id'] ] = isset( $field['data-type'] ) ? $field['data-type'] : 'url';
			}
		}

		update_option( 'bf-elementor-fields-comp', $status );
	}
}
<?php


class BF_KC_Wrapper extends BF_Page_Builder_Wrapper {

	/**
	 * @var array
	 *
	 * @since 4.0.0
	 */
	public $static_fields = array();


	/**
	 * Register
	 *
	 * @return bool true on success.
	 */
	public function register_fields() {

		global $kc;

		if ( ! $kc || ! is_callable( array( $kc, 'add_param_type' ) ) ) {
			return false;
		}

		// Register fields except deferred ones, they will load via ajax
		// @see BF_KC_Compatibility::ajax_load_fields()

		$this->static_fields = array_diff(
			$this->supported_fields(),
			$this->dynamic_deferred_fields(),
			$this->static_deferred_fields()
		);

		/**
		 * We can't use  $kc->add_param_type because the second parameter doesn't accept object
		 * That's silly but we have to handle this part in hard way!
		 *
		 * @see KingComposer::convert_paramTypes
		 */
		//		add_action( 'kc_after_admin_footer', array( $this, 'print_static_fields_template' ) );

		require BF_PATH . 'page-builder/generators/kc/kc-field-generator-functions.php';
		foreach ( $this->static_fields as $field ) {

			if ( function_exists( 'bf_kc_field_' . $field ) ) {
				$kc->add_param_type( $field, 'bf_kc_field_' . $field );
			}
		}

		return true;
	}

	/**
	 * @since 4.0.0
	 */
	/*public function print_static_fields_template() {

		if ( empty( $this->static_fields ) ) {

			return;
		}

		if ( ! class_exists( 'BF_KC_Fields_Generator' ) ) {
			require BF_PATH . 'page-builder/generators/kc/class-bf-kc-fields-generator.php';
		}

		$generator = new BF_KC_Fields_Generator();

		foreach ( $this->static_fields as $field ) {

			echo '<script type="text/html" id="tmpl-kc-field-type-' . esc_attr( $field ) . '-template">';

			$options = array(
				'id'    => '{{data.name}}',
				'value' => '{{data.value}}',
				'type'  => $field,
			);

			call_user_func( array( $generator, $field ), $options );

			echo "</script>\n";
		}
	}*/

	/**
	 * Adds BF Select field to Visual Composer
	 *
	 * @param $settings
	 * @param $value
	 *
	 * @return string
	 */
	function select_param( $settings, $value ) {

		$options = $this->convert_field_option( $settings, $value );

		$options['type'] = 'select';

		if ( isset( $settings['multiple'] ) ) {
			$options['multiple'] = $settings['multiple'];
		}

		$generator = new BF_VC_Front_End_Generator( $options, $settings['param_name'] );

		return $generator->get_field();
	}


	/**
	 * Register shortcode map.
	 *
	 * @param array $settings
	 * @param array $fields transformed fields
	 *
	 * @return bool true on success
	 */
	public function register_map( array $settings, $fields ) {

		if ( empty( $settings['name'] ) || empty( $settings['id'] ) ) {
			return false;
		}
		if ( empty( $fields ) ) {
			return false;
		}

		$always_fetch_fields = false;
		$deferred_types      = $this->dynamic_deferred_fields();

		foreach ( $fields as $tab_fields ) {

			foreach ( $tab_fields as $field ) {

				if ( in_array( $field['type'], $deferred_types ) ) {

					BF_KC_Compatibility::always_fetch_map_fields( $settings['id'] );

					$always_fetch_fields = true;
					break 2;
				}
			}
		}

		if ( ! $always_fetch_fields ) {

			$deferred_types  = $this->static_deferred_fields();
			$deferred_fields = array();

			foreach ( $fields as $tab_fields ) {

				foreach ( $tab_fields as $field ) {

					if ( in_array( $field['type'], $deferred_types ) ) {

						$deferred_fields[] = $field['type'];
					}
				}
			}

			if ( ! empty( $deferred_fields ) ) {
				BF_KC_Compatibility::mark_fields_as_deferred( $settings['id'], $deferred_fields );
			}
		}

		$settings['params'] = $fields;

		if ( isset( $settings['desc'] ) ) {

			$settings['description'] = $settings['desc'];
			unset( $settings['desc'] );
		}

		return $this->kc_map( $settings['id'], $settings );
	}


	/**
	 * List of all supported fields type.
	 *
	 * @return array
	 */
	public function supported_fields() {

		return array(
			'text',
			'color',
			'switch',
			'heading',
			'icon_select',
			'select',
			'select_popup',
			'term_select',
			'ajax_select',
			'custom',
			'group',
			'group_close',
			'info',
			'heading',
			'image_radio',
			'media_image',
			'sorter_checkbox',
			// 'background_image',
		);
	}


	/**
	 * todo: add comment
	 *
	 * @return array
	 */
	public function static_deferred_fields() {

		return array();
	}


	/**
	 * todo: add comment
	 * List of fields types that should be fetch via ajax
	 *
	 * @return array
	 */
	public function dynamic_deferred_fields() {

		return array(
			'icon_select',
			'select',
			'select_popup',
			'term_select',
			'ajax_select',
			'heading',
			'custom',
			'group',
			'group_close',
			'info',
			'image_radio',
			'media_image',
			'sorter_checkbox',
			// 'background_image',
		);
	}


	/**
	 * @param string        $id
	 * @param array         $atts
	 *
	 * @global KingComposer $kc
	 *
	 * @since 4.0.0
	 * @return bool true on success or false on error.
	 */
	public function kc_map( $id, $atts ) {

		global $kc;

		if ( $kc && is_callable( array( $kc, 'add_map' ) ) ) {

			if ( empty( $atts['category'] ) ) {
				$atts['category'] = 'all';
			}

			if ( empty( $atts['icon'] ) ) {

				$atts['icon'] = "$id-icon";
			}

			$kc->add_map( array( $id => $atts ) );

			return true;
		}

		return false;
	}

	/**
	 * Unique id of the page builder.
	 *
	 * @since 4.0.0
	 * @return string
	 */
	public function unique_id() {

		return 'KC';
	}
}<?php

// let's show them we are better
<?php


class BF_Page_Builder_Extender {


	public function __construct() {

		/**
		 * @var BF_Page_Builder_Wrapper $wrapper
		 */

		foreach ( self::active_page_builders() as $page_builder ) {

			if ( ! $wrapper_class = $this->wrapper_class( $page_builder ) ) {
				continue;
			}

			if ( $hook = call_user_func( array( $wrapper_class, 'register_fields_hook' ) ) ) {

				add_action( $hook, array( $this, 'register_fields_hook' ) );

			} else {

				$wrapper = new $wrapper_class();
				$wrapper->register_fields();
			}
		}

		if ( self::is_kc_active() ) {

			require BF_PATH . 'page-builder/compatibility/kc/class-bf-kc-compatibility.php';
		}
	}


	/**
	 * @return bool
	 */
	public function register_fields_hook() {

		foreach ( self::active_page_builders() as $page_builder ) {

			if ( $wrapper_class = $this->wrapper_class( $page_builder ) ) {

				$wrapper = new $wrapper_class();
				$wrapper->register_fields();
			}
		}

		return true;
	}


	/**
	 * Detect current running page builder plugin.
	 *
	 * @since 4.0.0
	 * @return string empty string on error or plugin short name on success.
	 */
	public static function active_page_builders() {

		$page_builders = array();

		if ( defined( 'WPB_VC_VERSION' ) && WPB_VC_VERSION ) {
			$page_builders[] = 'VC';
		}

		if ( defined( 'KCP_VERSION' ) && KCP_VERSION ) {
			$page_builders[] = 'KCP';
		}

		if ( defined( 'KC_VERSION' ) && KC_VERSION ) {
			$page_builders[] = 'KC';
		}

		if ( defined( 'ELEMENTOR_VERSION' ) && ELEMENTOR_VERSION ) {
			$page_builders[] = 'Elementor';
		}

		if ( defined( 'SITEORIGIN_PANELS_VERSION' ) && SITEORIGIN_PANELS_VERSION ) {
			$page_builders[] = 'SiteOrigin';
		}

		if ( ! class_exists( 'BF_Gutenberg_Shortcode_Wrapper' ) ) {
			require BF_PATH . 'gutenberg/class-bf-gutenberg-shortcode-wrapper.php';
		}

		if ( BF_Gutenberg_Shortcode_Wrapper::is_gutenberg_active() ) {
			$page_builders[] = 'Gutenberg';
		}

		return $page_builders;
	}

	public static function is_kc_active() {

		return in_array( 'KCP', self::active_page_builders() )
		       ||
		       in_array( 'KC', self::active_page_builders() );
	}


	/**
	 * Get current active page builder wrapper class.
	 *
	 * @param $page_builder
	 *
	 * @since 4.0.0
	 * @return string empty on failure.
	 */
	public function wrapper_class( $page_builder ) {

		if ( ! class_exists( 'BF_Page_Builder_Wrapper' ) ) {

			require BF_PATH . '/page-builder/class-bf-page-builder-wrapper.php';
		}

		$class_name = '';

		switch ( $page_builder ) {

			case 'VC':

				if ( ! class_exists( 'BF_VC_Wrapper' ) ) {

					require BF_PATH . '/page-builder/wrappers/class-bf-vc-wrapper.php';
				}

				$class_name = 'BF_VC_Wrapper';

				break;

			case 'KC':
			case 'KCP':

				if ( ! class_exists( 'BF_KC_Wrapper' ) ) {

					require BF_PATH . '/page-builder/wrappers/class-bf-kc-wrapper.php';
				}

				$class_name = 'BF_KC_Wrapper';

				break;
			/*
						case 'Elementor':

							if ( ! class_exists( 'BF_Elementor_Wrapper' ) ) {

								require BF_PATH . '/page-builder/wrappers/class-bf-elementor-wrapper.php';
							}

							$class_name = 'BF_Elementor_Wrapper';

							break;

			*/
		}

		return $class_name;
	}


	/**
	 * Get current active page builder adapter class.
	 *
	 * @param string $page_builder
	 *
	 * @since 4.0.0
	 * @return bool|BF_Fields_Adapter false on failure.
	 */
	public function adapter_class( $page_builder ) {

		if ( ! class_exists( 'BF_Fields_Adapter' ) ) {

			require BF_PATH . '/page-builder/class-bf-fields-adapter.php';
		}

		switch ( $page_builder ) {

			case 'VC':

				if ( ! class_exists( 'BF_To_VC_Fields_Adapter' ) ) {

					require BF_PATH . 'page-builder/adapters/class-bf-to-vc-fields-adapter.php';
				}

				$class_name = 'BF_To_VC_Fields_Adapter';

				break;

			case 'KC':
			case 'KCP':

				if ( ! class_exists( 'BF_To_KC_Fields_Adapter' ) ) {

					require BF_PATH . 'page-builder/adapters/class-bf-to-kc-fields-adapter.php';
				}

				$class_name = 'BF_To_KC_Fields_Adapter';

				break;
		}

		if ( ! empty( $class_name ) ) {
			return $class_name;
		}

		return false;
	}


	/**
	 * Transform standard BF fields format to active page builder style.
	 *
	 * @param string      $page_builder_id
	 * @param array $fields
	 * @param array $defaults
	 *
	 * @return mixed WP_Error|false on failure otherwise array|object
	 * @since 4.0.0
	 */
	public function transform( $page_builder_id, array $fields, $defaults = array() ) {

		if ( ! $adapter_class = $this->adapter_class( $page_builder_id ) ) {
			return false;
		}

		$adapter = new $adapter_class();
		$adapter->load_fields( $fields );
		$adapter->load_defaults( $defaults );

		return $adapter->transform();
	}
}
<?php


/**
 * Transform standard BF fields format to King Composer style
 *
 * @since 4.0.0
 */
class BF_To_KC_Fields_Adapter extends BF_Fields_Adapter {

	/**
	 * Transform
	 *
	 * @since 4.0.0
	 * @return array
	 */
	public function transform() {

		if ( empty( $this->fields ) ) {
			return array();
		}


		$shared_field_options = array(
			'type'          => '',
			'name'          => '',
			'value'         => '',
			'label'         => '',
			'admin_label'   => '',
			'description'   => '',
			'section_class' => '',
			'_options'      => '',
			'show_on'       => '',
			'multiple'      => '',
		);
		$replacements         = array(
			// 'bf key' => 'kc key'
			'name'           => 'label',
			'id'             => 'name',
			'desc'           => 'description',
			'vc_admin_label' => 'admin_label',
			'admin_label'    => 'admin_label',
		);

		$standard_fields  = $this->list_standard_fields();
		$supported_fields = $this->list_all_supported_fields();
		$current_tab      = __( 'General', 'better-studio' );

		$new_fields = array();

		foreach ( $this->fields as $idx => $field ) {

			if ( $field['type'] === 'tab' ) {
				$current_tab = $field['name'];
				continue;
			}

			if ( ! in_array( $field['type'], $supported_fields ) ) {
				continue;
			}

			$new_field                = $field;
			$new_field['is_standard'] = in_array( $field['type'], $standard_fields );

			// Set default value if exists
			if ( isset( $field['id'] ) && isset( $this->defaults[ $field['id'] ] ) ) {
				$new_field['value'] = $this->defaults[ $field['id'] ];
			}

			// Transform bf fields key to visual composer type
			foreach ( array_intersect_key( $replacements, $field ) as $key => $new_key ) {

				$new_field[ $new_key ] = $field[ $key ];

				unset( $new_field[ $key ] );
			}

			if ( isset( $new_field['options'] ) ) { // handle reserved 'options' key
				$new_field['_options'] = $new_field['options'];
				unset( $new_field['options'] );
			}
			$new_field['options'] = array_diff_key( $new_field, $shared_field_options );

			// Pass show_on value via options parameter only  for standard fields
			if ( $new_field['is_standard'] && ! empty( $field['show_on'] ) ) {

				$new_field['options']['show_on'] = array( 'show_on' => $field['show_on'] );
			}


			// Change 'group' type to bf_group to prevent conflict with king composer group field.]

			if ( 'group' === $new_field['type'] ) {

				$new_field['type'] = 'bf_group';

			} elseif ( 'group_close' === $new_field['type'] ) {

				$new_field['type'] = 'bf_group_close';
			}

			//TODO: add bf color picker support
			if ( 'color' === $new_field['type'] ) {

				$new_field['type'] = 'color_picker';
			}

			$new_fields[ $current_tab ][] = $new_field;
		}

		return $new_fields;
	}


	/**
	 * @since 4.0.0
	 * @return array
	 */
	public function list_standard_fields() {

		/**
		 * @var BF_KC_Wrapper $kc_wrapper
		 */

		if ( ! $kc_wrapper = Better_Framework::factory( 'page-builder' )->wrapper_class( 'KC' ) ) {
			return array();
		}

		$kc_wrapper = new $kc_wrapper();

		return array_diff(
			$kc_wrapper->supported_fields(),
			$kc_wrapper->dynamic_deferred_fields(),
			$kc_wrapper->static_deferred_fields()
		);
	}


	/**
	 * Get list of all supported fields in King Composer
	 *
	 * @since 4.0.0
	 * @return array
	 */
	public function list_all_supported_fields() {

		if ( ! $kc_wrapper = Better_Framework::factory( 'page-builder' )->wrapper_class( 'KC' ) ) {
			return array();
		}

		$kc_wrapper = new $kc_wrapper;

		return $kc_wrapper->supported_fields();
	}
}
<?php


/**
 * Transform standard BF fields format to VisualComposer style
 *
 * @since 4.0.0
 */
class BF_To_VC_Fields_Adapter extends BF_Fields_Adapter {

	/**
	 * Transform
	 *
	 * @since 4.0.0
	 * @return array
	 */
	public function transform() {

		$replacements = array(
			// 'bf key' => 'vc key'
			'name'           => 'heading',
			'desc'           => 'description',
			'id'             => 'param_name',
			'vc_admin_label' => 'admin_label',
		);


		$wrapper_class    = Better_Framework::factory( 'page-builder' )->wrapper_class( 'VC' );
		$vc_wrapper       = new $wrapper_class;
		$supported_fields = $vc_wrapper->supported_fields();
		$current_tab      = __( 'General', 'better-studio' );
		$fields           = $this->fields;

		foreach ( $this->fields as $idx => $field ) {

			if ( $field['type'] === 'tab' ) {
				$current_tab = $field['name'];
				unset( $fields[ $idx ] );
				continue;
			}

			// Set default value if exists
			if ( isset( $field['id'] ) && isset( $this->defaults[ $field['id'] ] ) ) {
				$fields[ $idx ]['value'] = $this->defaults[ $field['id'] ];
			}

			// Transform field type to vc-extender standard
			if ( $field['type'] === 'text' ) {
				$fields[ $idx ]['type'] = 'textfield';
			} elseif ( in_array( $field['type'], $supported_fields ) ) {
				$fields[ $idx ]['type'] = 'bf_' . $field['type'];
			}

			// Transform bf fields key to visual composer type
			foreach ( array_intersect_key( $replacements, $field ) as $key => $new_key ) {

				$fields[ $idx ][ $new_key ] = $field[ $key ];

				unset( $fields[ $idx ][ $key ] );
			}

			$fields[ $idx ]['group'] = $current_tab;
		}

		return $fields;
	}
}
<?php

// let's show them we are better
<?php


abstract class BF_Elementor_Field_Transformer {

	/**
	 * @var array
	 */
	protected $field;


	/**
	 *
	 * @return array
	 */
	abstract public function transform_field();


	/**
	 * @param array $field
	 */
	public function init( $field ) {

		$this->field = $field;
	}


	/**
	 * @param string $index
	 *
	 * @return mixed
	 */
	public function field( $index = '' ) {

		if ( $index ) {

			return isset( $this->field[ $index ] ) ? $this->field[ $index ] : null;
		}

		return $this->field;
	}
}
<?php


class BF_To_Elementor_Fields_Adapter extends BF_Fields_Adapter {

	/**
	 * @var Elementor\Widget_Base
	 */
	protected $widget;


	/**
	 * @var array
	 */
	protected $supported_fields = array();


	public function __construct( array $fields = array(), array $defaults = array() ) {

		parent::__construct( $fields, $defaults );

		$wrapper_class = Better_Framework::factory( 'page-builder' )->wrapper_class( 'Elementor' );

		$wrapper = new $wrapper_class();
		//
		$this->supported_fields = $wrapper->supported_fields();

	}


	/**
	 * @return mixed|WP_Error WP_Error on failure or transformed fields on success.
	 */
	public function transform() {

		if ( empty( $this->fields ) ) {
			return false;
		}

		reset( $this->fields );
		$first_index = key( $this->fields );
		$first_field = $this->fields[ $first_index ];
		//
		end( $this->fields );
		$last_index = key( $this->fields );
		$last_field = $this->fields[ $last_index ];
		//

		if ( ! isset( $first_field['type'] ) ||
		     ! in_array( $first_field['type'], array( 'group', 'tab' ) )
		) {

			$this->widget->start_controls_section(
				'section_title',
				array(
					'label' => $this->widget->get_title(),
				)
			);
		}
		$tab_started = false;

		foreach ( $this->fields as $id => $field ) {

			if ( empty( $field['type'] ) ) {
				continue;
			}

			$type = $field['type'];

			if ( $type === 'group' ) {

				$this->widget->start_controls_section(
					isset( $field['id'] ) ? $field['id'] : $id,
					array(
						'label' => $field['name'],
					)
				);

				continue;
			}

			if ( $type === 'group_close' ) {

				$this->widget->end_controls_section();

				continue;
			}

			if ( $type === 'tab' ) {

				$this->widget->end_controls_section();

				$this->widget->start_controls_section(
					isset( $field['id'] ) ? $field['id'] : $id,
					array(
						'label' => $field['name'],
					)
				);

				$tab_started = true;
			}

			if ( ! in_array( $type, $this->supported_fields ) ) {
				continue;
			}

			if ( empty( $field['id'] ) ) {
				continue;
			}

			if ( $factory = $this->factory( $field ) ) {
				$override_args = $factory->transform_field();
			} else {
				$override_args = array();
			}

			$type_const = strtoupper( $type );

			$this->widget->add_control( $field['id'], array_merge( array(

				'label'       => $field['name'],
				'type'        => defined( "Controls_Manager::$type_const" ) ? Controls_Manager::$type_const : $field['type'],
				'description' => isset( $field['desc'] ) ? $field['desc'] : '',
			), $override_args ) );
		}

		if ( $tab_started ) {
			$this->widget->end_controls_section();
		}

		if ( ! isset( $last_field['type'] ) ||
		     $last_field['type'] !== 'group_close'
		) {

			$this->widget->end_controls_section();
		}


		return true;
	}


	/**
	 * @param \Elementor\Widget_Base $widget
	 */
	public function set_elementor_widget( \Elementor\Widget_Base $widget ) {

		$this->widget = $widget;
	}


	/**
	 * @return \Elementor\Widget_Base
	 */
	public function get_elementor_widget() {

		return $this->widget;
	}


	/**
	 * @param array $field
	 *
	 * @since 3.9.0
	 * @return BF_Elementor_Field_Transformer on success or null on failure.
	 */
	public function factory( array $field ) {

		if ( empty( $field['type'] ) ) {
			return null;
		}

		if ( ! class_exists( 'BF_Elementor_Field_Transformer' ) ) {

			require BF_PATH . 'page-builder/adapters/elementor/class-bf-elementor-field.php';
		}

		switch ( $field['type'] ) {

			case 'custom';

				if ( ! class_exists( 'BF_Elementor_Raw_Field' ) ) {

					require BF_PATH . 'page-builder/adapters/elementor/fields/class-bf-elementor-raw-field.php';
				}

				$instance = new BF_Elementor_Raw_Field();

				break;

			case 'hr';

				if ( ! class_exists( 'BF_Elementor_Divider_Field' ) ) {

					require BF_PATH . 'page-builder/adapters/elementor/fields/class-bf-elementor-divider-field.php';
				}

				$instance = new BF_Elementor_Divider_Field();

				break;

			case 'wp_editor';

				if ( ! class_exists( 'BF_Elementor_WYSIWYG_Field' ) ) {

					require BF_PATH . 'page-builder/adapters/elementor/fields/class-bf-elementor-wysiwyg-field.php';
				}

				$instance = new BF_Elementor_WYSIWYG_Field();

				break;


			case 'editor';

				if ( ! class_exists( 'BF_Elementor_Code_Field' ) ) {

					require BF_PATH . 'page-builder/adapters/elementor/fields/class-bf-elementor-code-field.php';
				}

				$instance = new BF_Elementor_Code_Field();

				break;

			case 'switch';

				if ( ! class_exists( 'BF_Elementor_Switcher_Field' ) ) {

					require BF_PATH . 'page-builder/adapters/elementor/fields/class-bf-elementor-switcher-field.php';
				}

				$instance = new BF_Elementor_Switcher_Field();

				break;


			case 'select';

				if ( ! class_exists( 'BF_Elementor_Select_Field' ) ) {

					require BF_PATH . 'page-builder/adapters/elementor/fields/class-bf-elementor-select-field.php';
				}

				$instance = new BF_Elementor_Select_Field();

				break;

			case 'radio';

				if ( ! class_exists( 'BF_Elementor_Radio_Field' ) ) {

					require BF_PATH . 'page-builder/adapters/elementor/fields/class-bf-elementor-radio-field.php';
				}

				$instance = new BF_Elementor_Radio_Field();

				break;

			case 'media_image';

				if ( ! class_exists( 'BF_Elementor_Media_Field' ) ) {

					require BF_PATH . 'page-builder/adapters/elementor/fields/class-bf-elementor-media-field.php';
				}

				$instance = new BF_Elementor_Media_Field();

				break;


			case 'slider';

				if ( ! class_exists( 'BF_Elementor_Slider_Field' ) ) {

					require BF_PATH . 'page-builder/adapters/elementor/fields/class-bf-elementor-slider-field.php';
				}

				$instance = new BF_Elementor_Slider_Field();

				break;
		}

		if ( isset( $instance ) ) {
			$instance->init( $field );

			return $instance;
		}

		return null;
	}
}
<?php


class BF_Elementor_Select_Field extends BF_Elementor_Field_Transformer {

	/**
	 * @return array
	 */
	public function transform_field() {

		return array(
			'options' => isset( $this->field['options'] ) ? $this->field['options'] : array(),
		);
	}
}
<?php


class BF_Elementor_Raw_Field extends BF_Elementor_Field_Transformer {

	/**
	 * @return array
	 */
	public function transform_field() {

		$raw = $this->raw_code();

		return compact( 'raw' );
	}


	/**
	 * @return string
	 */
	public function raw_code() {

		if ( ! isset( $this->field['input_callback'] ) ) {
			return '';
		}

		if ( is_array( $this->field['input_callback'] ) ) {

			$callback = $this->field['input_callback']['callback'];

			if ( isset( $this->field['input_callback']['args'][0] ) ) {

				$callback_args = $this->field['input_callback']['args'];

				$callback_args[0]['field_options'] = $this->field;
			} else {

				$callback_args = array( array( 'field_options' => $this->field ) );
			}

		} else {

			$callback = $this->field['input_callback'];

			$callback_args = array( array( 'field_options' => $this->field ) );
		}

		ob_start();

		call_user_func_array( $callback, $callback_args );

		return ob_get_clean();
	}
}
<?php


class BF_Elementor_WYSIWYG_Field extends BF_Elementor_Field_Transformer {

	/**
	 * @return array
	 */
	public function transform_field() {

		return array(
			'type' => 'wysiwyg',
		);
	}
}
<?php


class BF_Elementor_Slider_Field extends BF_Elementor_Field_Transformer {

	/**
	 * @return array
	 */
	public function transform_field() {

		if ( isset( $this->field['min'] ) ) {
			$min = $this->field['min'];
		}

		if ( isset( $this->field['max'] ) ) {
			$max = $this->field['max'];
		}

		$step = 1;

		return array(
			'type'  => 'slider',
			'range' => compact( 'min', 'max', 'step' ),
		);
	}
}
<?php


class BF_Elementor_Code_Field extends BF_Elementor_Field_Transformer {

	/**
	 * @return array
	 */
	public function transform_field() {

		return array(
			'type'     => 'code',
			'language' => isset( $this->field['lang'] ) ? $this->field['lang'] : '',
		);
	}
}
<?php


class BF_Elementor_Divider_Field extends BF_Elementor_Field_Transformer {

	/**
	 * @return array
	 */
	public function transform_field() {

		return array(
			'type'      => 'divider',
			'separator' => 'after',
		);
	}
}
<?php


class BF_Elementor_Radio_Field extends BF_Elementor_Field_Transformer {

	/**
	 * @return array
	 */
	public function transform_field() {

		return array(
			'options' => $this->field['options']
		);
	}
}
<?php


class BF_Elementor_Switcher_Field extends BF_Elementor_Field_Transformer {

	/**
	 * @return array
	 */
	public function transform_field() {

		return array(
			'type'      => 'switcher',
			'label_on'  => isset( $this->field['on-label'] ) ? $this->field['on-label'] : '',
			'label_off' => isset( $this->field['off-label'] ) ? $this->field['off-label'] : '',
		);
	}
}
<?php

// let's show them we are better
<?php


class BF_Elementor_Media_Field extends BF_Elementor_Field_Transformer {

	/**
	 * @return array
	 */
	public function transform_field() {

		return array(
			'type'        => 'media',
			'show_label'  => ! empty( $this->field['show_input'] ),
			'label_block' => ! empty( $this->field['show_input'] ),
		);
	}
}
<?php

// let's show them we are better
<?php


abstract class BF_Fields_Adapter {

	/**
	 * @var array
	 *
	 * @since 4.0.0
	 */
	protected $fields = array();

	/**
	 * @var array
	 *
	 * @since 4.0.0
	 */
	protected $defaults = array();


	/**
	 * @return mixed|WP_Error WP_Error on failure or transformed fields on success.
	 */
	abstract public function transform();


	/**
	 * BF_Fields_Adapter constructor.
	 *
	 * @param array $fields
	 * @param array $defaults
	 *
	 */
	public function __construct( array $fields = array(), array $defaults = array() ) {

		$this->load_fields( $fields );
		$this->load_defaults( $defaults );
	}


	/**
	 * @param array $fields
	 *
	 * @return bool true on success
	 */
	public function load_fields( array $fields ) {

		$this->fields = $fields;

		return true;
	}


	/**
	 * @param array $defaults
	 *
	 * @return bool true on success
	 */
	public function load_defaults( array $defaults ) {

		$this->defaults = $defaults;

		return true;
	}
}
<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * User Metabox Fields Generator
 */
class BF_User_Metabox_Front_End_Generator extends BF_Admin_Fields {


	/**
	 * Constructor Function
	 *
	 * @param array  $items  Panel All Options
	 * @param string $id     Panel ID
	 * @param array  $values Panel Saved Values
	 *
	 * @since  1.4
	 * @access public
	 */
	public function __construct( array &$items, &$id, &$values = array() ) {

		// Parent Constructor
		parent::__construct( array(
			'templates_dir' => BF_PATH . 'metabox/templates/'
		) );

		$this->items  = $items;
		$this->id     = $id;
		$this->values = $values;
	}


	/**
	 * Used for creating input name
	 *
	 * @since 1.4
	 *
	 * @param $options
	 *
	 * @return string
	 */
	public function input_name( &$options ) {

		$id   = isset( $options['id'] ) ? $options['id'] : '';
		$type = isset( $options['type'] ) ? $options['type'] : '';

		switch ( $type ) {

			default:
				return "{$id}";
				break;

		}

	}


	/**
	 *  Metabox panel generator
	 *
	 * @since 1.4
	 */
	public function callback( $is_ajax = false ) {

		$skip_ajax_fields      = ! $is_ajax;
		$this->items['fields'] = BF_User_Metabox_Core::get_metabox_fields( $this->id );
		$metabox_config        = BF_User_Metabox_Core::get_metabox_config( $this->id );
		$items_has_tab         = ! $is_ajax && $this->has_tab();
		$has_tab               = false;

		if ( ! $is_ajax ) {
			$wrapper = Better_Framework::html()->add( 'div' )->class( 'bf-user-meta-wrap bf-metabox-wrap bf-clearfix' )->data( 'id', $this->id );

			// Better Option Title
			$wrapper->text(
				Better_Framework::html()->add( 'div' )->class( 'bf-user-metabox-title' )->text(
					Better_Framework::html()->add( 'h3' )->text( $metabox_config['title'] )
				)
			);

			// Add Class For Post Format Filter
			if ( isset( $metabox_config['post_format'] ) ) {
				$wrapper->data( 'bf_pf_filter', implode( ',', $metabox_config['post_format'] ) );
			}
		}

		$container = Better_Framework::html()->add( 'div' );
		if ( ! $is_ajax ) {
			$container = $container->class( 'bf-metabox-container' );
		}

		$tab_counter = 0;

		$group_counter = 0;

		if ( $items_has_tab && ! $is_ajax ) {
			$container->class( 'bf-with-tabs' );
			$tabs_container = Better_Framework::html()->add( 'div' )->class( 'bf-metabox-tabs' );
			$tabs_container->text( $this->get_tabs() );
			$wrapper->text( $tabs_container->display() );
		}

		if ( isset( $this->items['panel-id'] ) ) {
			$std_id = Better_Framework::options()->get_panel_std_id( $this->items['panel-id'] );
		} else {
			$std_id = 'std';
		}

		foreach ( $this->items['fields'] as $field ) {

			$field['input_name'] = $this->input_name( $field );

			$field['value'] = isset( $field['id'] ) && isset( $this->values[ $field['id'] ] ) ? $this->values[ $field['id'] ] : null;

			if ( is_null( $field['value'] ) && isset( $field[ $std_id ] ) ) {
				$field['value'] = $field[ $std_id ];
			} elseif ( is_null( $field['value'] ) && isset( $field['std'] ) ) {
				$field['value'] = $field['std'];
			}

			if ( $skip_ajax_fields && ! empty( $field['ajax-tab-field'] ) ) {  // Backward compatibility
				continue;
			}

			if ( $skip_ajax_fields && ! empty( $field['ajax-section-field'] ) ) {
				continue;
			}


			if ( $field['type'] == 'repeater' ) {
				$field['clone-name-format'] = 'bf-metabox-option[$1][$2][$3][$4]';
				$field['metabox-id']        = $this->id;
				$field['metabox-field']     = true;
			}

			if ( $field['type'] == 'tab' || $field['type'] == 'subtab' ) {

				// close tag for latest group in tab
				if ( $group_counter != 0 ) {
					$group_counter = 0;
					$container->text( $this->get_fields_group_close( $field ) );
				}

				$is_subtab = $field['type'] == 'subtab';

				if ( $tab_counter != 0 ) {
					$container->text( '</div><!-- /Section -->' );
				}

				if ( $is_subtab ) {
					$container->text( "\n\n<!-- Section -->\n<div class='group subtab-group' id='bf-metabox-{$this->id}-{$field["id"]}'>\n" );
				} else {
					$container->text( "\n\n<!-- Section -->\n<div class='group' id='bf-metabox-{$this->id}-{$field["id"]}'>\n" );
				}
				$has_tab = true;
				$tab_counter ++;
				continue;
			}

			if ( $field['type'] == 'group_close' ) {

				// close tag for latest group in tab
				if ( $group_counter != 0 ) {
					$group_counter = 0;
					$container->text( $this->get_fields_group_close( $field ) );
				}
				continue;
			}

			if ( $field['type'] == 'group' ) {

				// close tag for latest group in tab
				if ( $group_counter != 0 ) {
					$group_counter = 0;
					$container->text( $this->get_fields_group_close( $field ) );
				}

				$container->text( $this->get_fields_group_start( $field ) );

				$group_counter ++;
			}


			if ( ! in_array( $field['type'], $this->supported_fields ) ) {
				continue;
			}

			// Filter Each Field For Post Formats!
			if ( isset( $field['post_format'] ) ) {

				if ( is_array( $field['post_format'] ) ) {
					$field_post_formats = implode( ',', $field['post_format'] );
				} else {
					$field_post_formats = $field['post_format'];
				}
				$container->text( "<div class='bf-field-post-format-filter' data-bf_pf_filter='{$field_post_formats}'>" );
			}

			$container->text(
				$this->section(
					call_user_func(
						array( $this, $field['type'] ),
						$field
					),
					$field
				)
			);

			// End Post Format Filter Wrapper
			if ( isset( $field['post_format'] ) ) {

				$container->text( "</div>" );
			}
		}

		// close tag for latest group in tab
		if ( $group_counter != 0 ) {
			$container->text( $this->get_fields_group_close( $field ) );
		}

		// last sub tab closing
		if ( $has_tab ) {
			$container->text( "</div><!-- /Section -->" );
		}

		if ( $is_ajax ) {
			echo $container->display();
		} else {
			$wrapper->text( $container->display() );
			echo $wrapper; // escaped before
		}

	} // callback
}<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


// Prevent Direct Access
defined( 'ABSPATH' ) or die;


/**
 * This class handles all functionality of BetterFramework Users Meta box feature for creating, saving, editing
 *
 * @package    BetterFramework
 * @since      1.4
 */
class BF_User_Metabox_Core {


	/**
	 * Contains all metabox's
	 *
	 * @var array
	 */
	public static $metabox = array();


	/**
	 * Contains config for all metabox's
	 *
	 * @var array
	 */
	public static $config = array();


	/**
	 * Contains all fields
	 *
	 * @var array
	 */
	public static $fields = array();


	/**
	 * Contains all std
	 *
	 * @var array
	 */
	public static $std = array();


	/**
	 * Contains all css
	 *
	 * @var array
	 */
	public static $css = array();


	/**
	 * Initializes all metaboxes
	 */
	public static function init_metabox() {

		static $loaded;

		if ( $loaded ) {
			return;
		}

		self::$metabox = apply_filters( 'better-framework/user-metabox/add', array() );

	}


	/**
	 * loads and returns metabox config
	 *
	 * @param string $metabox_id
	 *
	 * @return array
	 */
	public static function get_metabox_config( $metabox_id = '' ) {

		if ( empty( $metabox_id ) ) {
			return array();
		}

		if ( isset( self::$config[ $metabox_id ] ) ) {
			return self::$config[ $metabox_id ];
		}

		return self::$config[ $metabox_id ] = apply_filters( 'better-framework/user-metabox/' . $metabox_id . '/config', array() );
	}


	/**
	 * loads and returns metabox std values
	 *
	 * @param string $metabox_id
	 *
	 * @return array
	 */
	public static function get_metabox_std( $metabox_id = '' ) {

		if ( empty( $metabox_id ) || ! isset( self::$metabox[ $metabox_id ] ) ) {
			return array( 'asdsd' );
		}

		if ( isset( self::$std[ $metabox_id ] ) ) {
			return self::$std[ $metabox_id ];
		}

		return self::$std[ $metabox_id ] = apply_filters( 'better-framework/user-metabox/' . $metabox_id . '/std', array() );
	}


	/**
	 * loads and returns metabox std values
	 *
	 * @param string $metabox_id
	 *
	 * @return array
	 */
	public static function get_metabox_fields( $metabox_id = '' ) {

		if ( empty( $metabox_id ) || ! isset( self::$metabox[ $metabox_id ] ) ) {
			return array();
		}

		if ( isset( self::$fields[ $metabox_id ] ) ) {
			return self::$fields[ $metabox_id ];
		}

		return self::$fields[ $metabox_id ] = apply_filters( 'better-framework/user-metabox/' . $metabox_id . '/fields', array() );
	}


	/**
	 * loads and returns metabox css
	 *
	 * @param string $metabox_id
	 *
	 * @return array
	 */
	public static function get_metabox_css( $metabox_id = '' ) {

		if ( empty( $metabox_id ) || ! isset( self::$metabox[ $metabox_id ] ) ) {
			return array();
		}

		if ( isset( self::$css[ $metabox_id ] ) ) {
			return self::$css[ $metabox_id ];
		}

		return self::$css[ $metabox_id ] = apply_filters( 'better-framework/user-metabox/' . $metabox_id . '/css', array() );
	}


	/**
	 * Used to add action for constructing the meta box
	 *
	 * @since     1.4
	 * @access    public
	 */
	public function __construct() {

		self::init_metabox();

		// Add options form
		add_action( 'show_user_profile', array( $this, 'add_meta_boxes' ) );
		add_action( 'edit_user_profile', array( $this, 'add_meta_boxes' ) );

		add_action( 'edit_user_profile_update', array( $this, 'save' ), 1 );
		add_action( 'personal_options_update', array( $this, 'save' ), 1 );

		/**
		 * Action to handle ajax user metabox tabs
		 */
		add_action( 'better-framework/user-metabox/ajax-tab', array( $this, 'ajax_tab' ), 10, 3 );
	}


	/**
	 * Used for retrieve meta data values
	 *
	 * @param   string $id meta box id
	 * @param          $user
	 *
	 * @since    1.4
	 * @return  array
	 * @access   public
	 */
	public function get_full_meta_data( $id = '', $user ) {

		global $pagenow;

		$output = array();

		if ( isset( self::$metabox[ $id ]['panel-id'] ) ) {
			$std_id = Better_Framework::options()->get_panel_std_id( self::$metabox[ $id ]['panel-id'] );
		} else {
			$std_id = 'std';
		}

		$metabox_std = self::get_metabox_std( $id );

		if ( $pagenow == 'post-new.php' ) {

			if ( ! empty( $metabox_std ) ) {

				foreach ( (array) $metabox_std as $field_id => $field ) {

					if ( isset( $field[ $std_id ] ) ) {
						$output[ $field_id ] = $field[ $std_id ];
					} elseif ( isset( $field['std'] ) ) {
						$output[ $field_id ] = $field['std'];
					}
				}

			}

			return $output;
		}

		$meta = get_user_meta( $user->ID );

		foreach ( (array) $metabox_std as $field_id => $field ) {

			if ( isset( $meta[ $field_id ] ) ) {

				if ( is_serialized( $meta[ $field_id ][0] ) ) {
					$output[ $field_id ] = unserialize( $meta[ $field_id ][0] );
				} else {
					$output[ $field_id ] = $meta[ $field_id ][0];
				}

			} else {

				if ( isset( $field[ $std_id ] ) ) {
					$output[ $field_id ] = $field[ $std_id ];
				} elseif ( isset( $field['std'] ) ) {
					$output[ $field_id ] = $field['std'];
				}
			}

		}

		return $output;
	}


	/**
	 * Deprecated: Use bf_get_user_meta
	 *
	 * Used for finding user meta field value.
	 *
	 * @since   1.4
	 *
	 * @param $field_key    string              User field ID
	 * @param $user         string|WP_User      User ID or object
	 *
	 * @return mixed
	 */
	public function get_meta( $field_key, $user ) {

		return bf_get_user_meta( $field_key, $user );
	}


	/**
	 * Callback: Used for creating meta boxes
	 *
	 * Action: show_user_profile
	 * Action: edit_user_profile
	 *
	 * @since   1.4
	 * @access  public
	 *
	 * @param   $user   string|WP_User      User ID or object
	 */
	public function add_meta_boxes( $user ) {

		if ( ! class_exists( 'BF_User_Metabox_Front_End_Generator' ) ) {
			require BF_PATH . 'user-metabox/class-bf-user-metabox-front-end-generator.php';
		}

		foreach ( (array) self::$metabox as $metabox_id => $metabox ) {

			$metabox_value = $this->get_full_meta_data( $metabox_id, $user );

			$metabox_config = self::get_metabox_config( $metabox_id );

			if ( empty( $metabox_config['title'] ) ) {
				$metabox_config['title'] = __( 'Better User Options', 'better-studio' );
			}

			$front_end = new BF_User_Metabox_Front_End_Generator( $metabox_config, $metabox_id, $metabox_value );

			$front_end->callback();
		}

	} // add


	/**
	 * Updates user meta in safely
	 *
	 * @param   string|WP_User $user  User ID or object
	 * @param   string         $key   User meta key name
	 * @param   string         $value User meta value
	 *
	 * @static
	 * @since   1.4
	 * @return  bool
	 */
	public static function add_meta( $user, $key, $value ) {

		if ( ! is_object( $user ) ) {
			$user = get_user_by( 'id', $user );
		}

		$old_value = get_user_meta( $user->ID, $key, true );

		if ( $old_value === false ) {
			return add_user_meta( $user->ID, $key, $value );
		} else {
			if ( $old_value === $value ) {
				return true;
			} else {
				delete_user_meta( $user->ID, $key );

				return add_user_meta( $user->ID, $key, $value );
			}
		}

	}


	/**
	 * Callback: Save user meta box values
	 *
	 * Action: edit_user_profile_update
	 * Action: personal_options_update
	 *
	 * @param   int $user_id
	 *
	 * @static
	 * @return  mixed
	 * @since   1.4
	 */
	public function save( $user_id ) {

		if ( ! current_user_can( 'edit_user', $user_id ) ) {
			return false;
		}

		// Iterate all meta boxes
		foreach ( (array) self::$metabox as $metabox_id => $metabox ) {

			if ( isset( $metabox['panel-id'] ) ) {
				$std_id = Better_Framework::options()->get_panel_std_id( $metabox['panel-id'] );
			} else {
				$std_id = 'std';
			}

			$metabox_std = self::get_metabox_std( $metabox_id );

			// Iterate all fields
			foreach ( (array) $metabox_std as $field_id => $field ) {

				if ( ! isset( $_POST[ $field_id ] ) ) {
					continue;
				}

				// Save value if save-std is true or not defined
				if ( ! isset( $field['save-std'] ) || $field['save-std'] == true ) {

					self::add_meta( $user_id, $field_id, $_POST[ $field_id ] );

				} // Don't Save Default Value
				elseif ( isset( $field['save-std'] ) ) {

					// If style std defined then save it
					if ( isset( $field[ $std_id ] ) ) {

						if ( $field[ $std_id ] != $_POST[ $field_id ] ) {
							self::add_meta( $user_id, $field_id, $_POST[ $field_id ] );
						} else {
							delete_user_meta( $user_id, $field_id );
						}

					} // If style std defined then save it
					elseif ( isset( $field['std'] ) ) {

						if ( $field['std'] != $_POST[ $field_id ] ) {
							self::add_meta( $user_id, $field_id, $_POST[ $field_id ] );
						} else {
							delete_user_meta( $user_id, $field_id );
						}

					}

				} // Delete Custom field
				else {
					delete_user_meta( $user_id, $field_id );
				}

			}

		}

	} // save


	/**
	 *
	 *
	 * @param string     $tab_id
	 * @param string     $metabox_id
	 * @param int|string $user_id
	 */
	public function ajax_tab( $tab_id, $metabox_id, $user_id ) {

		$user           = get_user_to_edit( $user_id );
		$fields         = BF_User_Metabox_Core::get_metabox_fields( $metabox_id );
		$metabox_value  = array();
		$metabox_config = self::get_metabox_config( $metabox_id );
		$use_generator  = true;


		if ( empty( $fields[ $tab_id ]['ajax-section-handler'] ) ) {

			$metabox_value = $this->get_full_meta_data( $metabox_id, $user );

			// Modify fields array
			foreach ( $fields as $idx => $field ) {

				// Backward compatibility
				if ( isset( $field['ajax-tab-field'] ) ) {
					$field['ajax-section-field'] = $field['ajax-tab-field'];
				}

				if ( empty( $field['ajax-section-field'] ) || $field['ajax-section-field'] !== $tab_id ) {
					unset( $fields[ $idx ] );
				}
			}

		} else {

			$parent_field = $fields[ $tab_id ];

			$args = isset( $parent_field['ajax-section-handler-args'] ) ? $parent_field['ajax-section-handler-args'] : array();
			$args = array_merge( $args, compact( 'metabox_id', 'tab_id' ) );

			if (
				! isset( $parent_field['ajax-section-handler-type'] ) ||
				$parent_field['ajax-section-handler-type'] === 'field-generator'
			) {

				$fields = call_user_func( $parent_field['ajax-section-handler'], $args );

				foreach ( $fields as $key => $field ) {

					$metabox_value[ $field['id'] ] = bf_get_user_meta( $field['id'], $user_id );
				}
			} else {

				$use_generator = false;
				$out           = call_user_func( $parent_field['ajax-section-handler'], $args );

			}
		}

		if ( $use_generator ) {

			if ( ! class_exists( 'BF_User_Metabox_Front_End_Generator' ) ) {
				require BF_PATH . 'user-metabox/class-bf-user-metabox-front-end-generator.php';
			}
			$front_end = new BF_User_Metabox_Front_End_Generator( $metabox_config, $metabox_id, $metabox_value );

			BF_User_Metabox_Core::$fields[ $metabox_id ] = $fields;

			ob_start();
			// print output
			echo $front_end->callback( true );  // escaped before
			$out = ob_get_clean();
		}

		wp_send_json( array( 'out' => $out, 'tab_id' => $tab_id ) );
	}
}
<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


if ( ! function_exists( 'bf_get_user_meta' ) ) {
	/**
	 * Used for finding user meta field value.
	 *
	 * @since   2.0
	 *
	 * @param   string         $field_key     User field ID
	 * @param   string|WP_User $user          User ID or object
	 * @param   null           $force_default Default value (Optional)
	 *
	 * @return mixed
	 */
	function bf_get_user_meta( $field_key, $user = null, $force_default = null ) {

		if ( is_null( $user ) ) {

			// Get current post author id
			if ( is_singular() ) {
				$user = get_the_author_meta( 'ID' );
			} // Get current archive user
			elseif ( is_author() ) {
				$user = bf_get_author_archive_user();
			} // Return default value
			else {
				return $force_default;
			}
		}

		// Get user id from object
		if ( is_object( $user ) ) {
			$user = $user->ID;
		}

		// get value if saved in DB
		$value = get_user_meta( $user, $field_key, true );

		if ( $value !== false ) {
			return $value;
		} // Or return force default value
		elseif ( ! is_null( $force_default ) ) {
			return $force_default;
		}

		// initialize base BF metabox
		if ( ! class_exists( 'BF_User_Metabox_Core' ) ) {
			Better_Framework()->user_meta();
		}

		// Iterate all meta boxes
		foreach ( BF_User_Metabox_Core::$metabox as $metabox_id => $metabox ) {

			// if this meta box connected to a panel for style field
			if ( isset( $metabox['panel-id'] ) ) {
				$std_id = Better_Framework()->options()->get_panel_std_id( $metabox['panel-id'] );
			} else {
				$std_id = 'std';
			}

			$metabox_std = BF_User_Metabox_Core::get_metabox_std( $metabox_id );

			// retrieve default value
			if ( isset( $metabox_std[ $field_key ][ $std_id ] ) ) {
				return $metabox_std[ $field_key ][ $std_id ];
			} elseif ( isset( $metabox_std[ $field_key ]['std'] ) ) {
				return $metabox_std[ $field_key ]['std'];
			}

		}

		return false;
	}
}


if ( ! function_exists( 'bf_echo_user_meta' ) ) {
	/**
	 * Used to echo user meta field value.
	 *
	 * @since   2.0
	 *
	 * @param   string         $field_key     User field ID
	 * @param   string|WP_User $user          User ID or object
	 * @param   null           $force_default Default value (Optional)
	 *
	 * @return mixed
	 */
	function bf_echo_user_meta( $field_key, $user = null, $force_default = null ) {

		echo bf_get_user_meta( $field_key, $user, $force_default );
	}
}

<?php
die;<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


$classes = $this->get_classes( $options );
$iri     = isset( $options['repeater_item'] ) && $options['repeater_item'] == true; // Is this section for a repeater item

$section_classes = $classes['section'];

$heading_classes  = $classes['heading'];
$controls_classes = $classes['controls'];
$explain_classes  = $classes['explain'];

if ( $iri ) {

	$section_classes  .= ' ' . $classes['repeater-section'];
	$heading_classes  .= ' ' . $classes['repeater-heading'];
	$controls_classes .= ' ' . $classes['repeater-controls'];
	$explain_classes  .= ' ' . $classes['repeater-explain'];

} else {

	$section_classes  .= ' ' . $classes['nonrepeater-section'];
	$heading_classes  .= ' ' . $classes['nonrepeater-heading'];
	$controls_classes .= ' ' . $classes['nonrepeater-controls'];
	$explain_classes  .= ' ' . $classes['nonrepeater-explain'];

}

$section_classes  .= ' ' . $classes['section-class-by-filed-type'];
$heading_classes  .= ' ' . $classes['heading-class-by-filed-type'];
$controls_classes .= ' ' . $classes['controls-class-by-filed-type'];
$explain_classes  .= ' ' . $classes['explain-class-by-filed-type'];

if ( empty( $options['desc'] ) ) {
	$section_classes .= ' no-desc ';
}
?>
<div class="bf-section-container bf-metabox bf-clearfix">
	<div class="<?php echo esc_attr( $section_classes ); ?> bf-clearfix"
	     data-id="<?php echo esc_attr( $options['id'] ); ?>">

		<div class="<?php echo esc_attr( $heading_classes ); ?> bf-clearfix">
			<h3><label><?php echo esc_html( $options['name'] ); ?></label></h3>
		</div>

		<div class="<?php echo esc_attr( $controls_classes ); ?> bf-clearfix">
			<?php echo $input; // escaped before ?>
		</div>

		<?php if ( ! empty( $options['desc'] ) ) { ?>
			<div
					class="<?php echo esc_attr( $explain_classes ); ?> bf-clearfix"><?php echo wp_kses( $options['desc'], bf_trans_allowed_html() ); ?></div>
		<?php } ?>

	</div>
</div><?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

?>
<div class="bf-section-container bf-clearfix">
	<div class="bf-section-hr bf-clearfix">
		<?php echo $input; // escaped before ?>
	</div>
</div><?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

?>
<div class="bf-section-container bf-metabox bf-clearfix">
	<div class="bf-section-heading bf-clearfix" data-id="<?php echo esc_attr( $options['id'] ); ?>"
	     id="<?php echo esc_attr( $options['id'] ); ?>">
		<div class="bf-section-heading-title bf-clearfix">
			<h3><?php echo esc_html( $options['name'] ); ?></h3>
		</div>
		<?php if ( ! empty( $options['desc'] ) ) { ?>
			<div
					class="bf-section-heading-desc bf-clearfix"><?php echo wp_kses( $options['desc'], bf_trans_allowed_html() ); ?></div>
		<?php } ?>
	</div>
</div><?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * override parent method to discard printed outputs
 *
 * Class BF_Product_Upgrader_Skin
 */
class BF_Product_Upgrader_Skin {

	public function header() {
	}


	public function footer() {
	}


	public function feedback( $string ) {
	}


	public function before() {
	}


	public function after() {
	}


	public function decrement_update_count( $type ) {
	}


	public function set_upgrader( &$upgrader ) {
	}


	public function add_strings() {
	}


	public function set_result( $result ) {
	}


	public function request_filesystem_credentials( $error = false, $context = false, $allow_relaxed_file_ownership = false ) {
	}


	public function error( $errors ) {
	}


	public function bulk_header() {
	}


	public function bulk_footer() {
	}
}<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


define( 'BS_PRODUCT_UPDATE_URI', trailingslashit( BF_URI . 'product-updater/' ) );
define( 'BS_PRODUCT_UPDATE_PATH', trailingslashit( BF_PATH . 'product-updater/' ) );

include_once BS_PRODUCT_UPDATE_PATH . 'class-bf-product-updater.php';
include_once BS_PRODUCT_UPDATE_PATH . 'functions.php';

<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


if ( ! function_exists( 'bf_remove_reject_unsafe_urls' ) ) {
	function bf_remove_reject_unsafe_urls( $args ) {

		$args['reject_unsafe_urls'] = false;

		return $args;
	}
}
<?php
// Silent is golden!<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


BF_Product_Updater::Run();


class BF_Product_Updater {

	public static $plugins_file = array();


	/**
	 * Initialize
	 */
	public static function Run() {

		global $bs_product_updater;

		if ( $bs_product_updater === false ) {
			return;
		}

		if ( ! $bs_product_updater instanceof self ) {
			$bs_product_updater = new self();
			$bs_product_updater->init();
		}

		return $bs_product_updater;
	}


	public function init() {

		add_action( 'wp_update_themes', array( $this, 'update_product_schedule' ) );
		add_action( 'load-themes.php', array( $this, 'update_product_schedule' ) );
		add_action( 'load-update.php', array( $this, 'update_product_schedule' ) );
		add_action( 'load-update-core.php', array( $this, 'update_product_schedule' ) );
		add_action( 'upgrader_process_complete', array( $this, 'update_product_schedule' ) );

		add_filter( 'site_transient_update_themes', array( $this, 'fetch_theme_download_link' ) );
		add_filter( 'upgrader_source_selection', array( $this, 'fix_source_directory' ), 30, 4 );

		$this->plugin_compatibility();
	}


	function fetch_theme_download_link( $value ) {

		global $pagenow;

		if ( isset( $_REQUEST['action'] ) &&
		     in_array( $pagenow, array( 'admin-ajax.php', 'update.php' ) ) &&
		     in_array( $_REQUEST['action'], array(
			     'upgrade-theme',
			     'update-selected-themes',
			     'update-theme',
		     ) )
		) {
			if ( ! empty( $value->response ) && is_array( $value->response ) ) {

				add_filter( 'http_request_args', 'bf_remove_reject_unsafe_urls', 99 );

				foreach ( $value->response as $idx => $product ) {
					if ( isset( $product['package'] ) && preg_match( '/^FETCH_FROM_BETTER_STUDIO\/(.+)/i', $product['package'], $matched ) ) {
						$r            = &$value->response[ $idx ];
						$dl_link      = $this->get_product_download_link( array_pop( $matched ), $product['slug'] );
						$r['package'] = $dl_link;
					}
				}

				set_site_transient( 'update_themes', $value );
				remove_filter( 'site_transient_update_themes', array( $this, 'fetch_theme_download_link' ) );
			}
		}

		return $value;
	}


	protected function get_product_download_link( $item_id ) {

		if ( $purchase_info = get_option( 'bf-product-updater-items' ) ) {
			if ( isset( $purchase_info[ $item_id ] ) ) {
				$purchase_code = &$purchase_info[ $item_id ];

				$product_data = $this->api_request( 'download-latest-version', array(), compact( 'item_id', 'purchase_code' ) );
				if ( ! empty( $product_data->success ) && ! empty( $product_data->download_link ) ) {
					return $product_data->download_link;
				}
			}
		}
	}


	protected function get_products_info() {

		$results = array();
		$info    = apply_filters( 'better-framework/product-updater/product-info', array() );

		if ( $info ) {

			$cache_data = array();
			foreach ( $info as $d ) {

				if ( isset( $d['item_id'] ) && isset( $d['purchase_code'] ) ) {
					$cache_data[ $d['item_id'] ] = $d['purchase_code'];
				}

				$results[ $d['item_id'] ] = $d;
			}
			update_option( 'bf-product-updater-items', $cache_data, 'no' );
		}

		return $results;
	}


	public function update_product_schedule() {

		static $loaded = false;
		remove_action( 'wp_update_themes', array( $this, 'update_product_schedule' ) );
		if ( $loaded ) {
			return;
		}
		$items_info = $this->get_products_info();
		if ( ! $items_info ) {
			return;
		}

		$status = $this->check_for_update( $items_info, true );

		if ( ! ( $plugins_update = get_site_transient( 'update_plugins' ) ) ) {
			$plugins_update = new stdClass();
		}
		if ( ! ( $themes_update = get_site_transient( 'update_themes' ) ) ) {
			$themes_update = new stdClass();
		}

		if ( ! empty( $status->plugins ) && is_array( $status->plugins ) ) {
			if ( empty( $plugins_update->response ) ) {
				$plugins_update->response = array();
			}

			$r = &$plugins_update->response;
			foreach ( $status->plugins as $plugin_data ) {
				$p_file = self::plugin_slug_to_file_path( $plugin_data['slug'] );

				$r[ $p_file ]          = (object) $plugin_data;
				$r[ $p_file ]->plugin  = $p_file;
				$r[ $p_file ]->package = 'FETCH_FROM_BETTER_STUDIO/' . $plugin_data['slug'];
			}

			set_site_transient( 'update_plugins', $plugins_update );
		}

		if ( ! empty( $status->themes ) && is_array( $status->themes ) ) {
			if ( empty( $themes_update->response ) ) {
				$themes_update->response = array();
			}

			$r = &$themes_update->response;
			foreach ( $status->themes as $item_id => $theme_data ) {

				$slug = &$theme_data['slug'];

				$r[ $slug ] = bf_merge_args( $theme_data, array(
					'package' => 'FETCH_FROM_BETTER_STUDIO/' . $item_id,
					//todo link to readme file
					'url'     => 'http://betterstudio.com/'
				) );
			}

			set_site_transient( 'update_themes', $themes_update );
		}

		$loaded = true;
	}


	/**
	 * Check group of items update
	 *
	 * @param array $items
	 * @param bool  $force
	 *
	 * @return bool|object object on success
	 */
	protected function check_for_update( $items, $force = false ) {

		global $wp_version, $pagenow;

		// Don't check update while updating another item!

		if (
			( isset( $_REQUEST['action'] ) && 'do-theme-upgrade' === $_REQUEST['action'] )
			||
			(
				isset( $_REQUEST['action'] ) &&
				in_array( $pagenow, array( 'admin-ajax.php', 'update.php' ) ) &&
				in_array( $_REQUEST['action'], array(
					'upgrade-theme',
					'update-selected-themes',
					'update-theme',
				) )
			)
		) {
			return false;
		}

		if ( empty( $items ) || ! is_array( $items ) ) {
			return false;
		}

		include ABSPATH . WPINC . '/version.php';

		$update_status               = new stdClass();
		$update_status->last_checked = time();
		$update_status->themes       = array();
		$update_status->plugins      = array();
		$update_status->misc         = array();

		if ( ! $force ) {
			$prev_status = get_option( 'bf-product-items-status' );

			if ( ! is_object( $prev_status ) ) {
				$prev_status               = new stdClass();
				$prev_status->last_checked = time();
				$skip_update               = false;
			} else {
				$skip_update = $this->check_update_duration > ( time() - $prev_status->last_checked );
			}

			if ( $skip_update ) {

				return $prev_status;
			}
		}

		/**
		 * check bundled plugins update
		 */

		$check_update = $this->api_request( 'check-products-update', compact( 'items' ) );

		if ( ! empty( $check_update->success ) && ! empty( $check_update->response ) ) {
			foreach ( $check_update->response as $item_id => $update_info ) {

				$ver       = &$update_info->version;
				$type      = &$update_info->type;
				$slug      = &$update_info->slug;
				$readme    = $update_info->readme ? $update_info->readme : false;
				$changelog = isset( $update_info->changelog ) ? $update_info->changelog : false;

				// Set active theme folder name instead of original folder name
				//  to handle changed folder names
				if ( ! empty( $items[ $item_id ]['active_theme'] ) ) {
					$slug = get_template();
				}

				if ( $ver !== 'latest' ) {

					$info_array = array(
						'slug'        => $slug,
						'new_version' => $ver,
						'url'         => $readme,
						'changelog'   => $changelog,
					);

					if ( $type === 'theme' ) {
						$update_status->themes[ $item_id ] = $info_array;
					} elseif ( $type === 'plugin' ) {
						$update_status->plugins[ $item_id ] = $info_array;
					} else {
						$update_status->misc[ $item_id ] = $info_array;
					}
				}
			}
		}

		do_action( 'better-framework/product-pages/product-update-check', $update_status, $check_update );

		update_option( 'bf-product-items-status', $update_status, 'no' );

		return $update_status;
	}


	/**
	 * Get plugin file path by plugin slug
	 *
	 * Ex: plugin_slug_to_file_path('js_composer') ==> js_composer/js_composer.php
	 *
	 * @param string $slug plugin slug (plugin directory)
	 *
	 * @return bool|string plugin file path on success or false on error
	 */
	public static function plugin_slug_to_file_path( $slug ) {

		if ( ! is_array( self::$plugins_file ) ) {

			self::$plugins_file = array();

			foreach ( get_plugins() as $file => $info ) {

				self::$plugins_file[ dirname( $file ) ] = $file;
			}
		}

		if ( isset( self::$plugins_file[ $slug ] ) ) {
			return self::$plugins_file[ $slug ];
		}

		return false;
	} // plugin_slug_to_file_path


	/**
	 * handle api request
	 *
	 * @see \BetterFramework_Oculus::request
	 *
	 * @param string $action
	 * @param array  $data
	 * @param array  $auth
	 * @param bool   $use_wp_error
	 *
	 * @return array|bool|object|WP_Error
	 */
	protected function api_request( $action, $data = array(), $auth = array(), $use_wp_error = false ) {

		if ( ! class_exists( 'BetterFramework_Oculus' ) ) {
			return false;
		}

		return BetterFramework_Oculus::request( $action, compact( 'auth', 'data', 'use_wp_error' ) );
	} //api_request


	/**
	 * Rename downloaded package folder to user-defined directory name
	 * for support renamed product folders while upgrading process.
	 *
	 * @param string      $source        File source location.
	 * @param string      $remote_source Remote file source location.
	 * @param WP_Upgrader $WP_Upgrader   WP_Upgrader instance. unused
	 * @param array       $hook_extra    Extra arguments passed to hooked filters.
	 *
	 * @hooked upgrader_source_selection
	 *
	 * @since  3.7.0
	 * @return string
	 */
	public function fix_source_directory( $source, $remote_source, $WP_Upgrader, $hook_extra ) {

		if ( ! $source ) {
			return $source;
		}

		if ( ! empty( $hook_extra['theme'] ) ) {

			$product_type        = 'theme';
			$current_folder_name = $hook_extra['theme'];

		} elseif ( ! empty( $hook_extra['plugin'] ) ) {

			$product_type        = 'plugin';
			$current_folder_name = $hook_extra['plugin'];

		} else {

			return $source;
		}

		$check = array(
			'product_type'   => $product_type,
			'product_folder' => basename( $source ),
		);

		$original_folder_name = &$check['product_folder'];

		// Dose user changed original product folder name?

		if ( $current_folder_name === $original_folder_name ) {

			return $source;
		}

		/// Is this a betterstudio product?
		$is_better_product = false;

		foreach ( apply_filters( 'better-framework/product-updater/product-info', array() ) as $info ) {

			if ( ! array_diff_assoc( $check, $info ) ) {

				$is_better_product = true;
				break;
			}
		}

		if ( ! $is_better_product ) {
			// Do not touch none betterstudio themes or plugins
			return $source;
		}

		$file_system   = bf_file_system_instance();
		$renamed_path  = $remote_source . '/' . $current_folder_name;
		$original_path = $remote_source . '/' . $original_folder_name;

		$file_system->delete( $renamed_path, true );

		if ( $file_system->move( $original_path, $renamed_path ) ) {

			return $renamed_path;
		}

		return $source;
	}


	/**
	 * Fix third-party plugin conflicts with our product updater.
	 */
	public function plugin_compatibility() {

		// Disable licensed visual composer update feature
		if ( function_exists( 'vc_manager' ) ) {

			vc_manager()->disableUpdater();
		}
	}
}
<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Metabox Fields Generator
 */
class BF_Metabox_Front_End_Generator extends BF_Admin_Fields {


	/**
	 * Constructor Function
	 *
	 * @param array $items  Panel All Options
	 * @param int   $id     Panel ID
	 * @param array $values Panel Saved Values
	 *
	 * @since  1.0
	 * @access public
	 */
	public function __construct( array &$items, &$id, &$values = array() ) {

		// Parent Constructor
		parent::__construct( array(
			'templates_dir' => BF_PATH . 'metabox/templates/'
		) );

		$this->items  = $items;
		$this->id     = $id;
		$this->values = $values;
	}


	/**
	 * Used for creating input name
	 *
	 * @param $options
	 *
	 * @return string
	 */
	public function input_name( &$options ) {

		$id   = isset( $options['id'] ) ? $options['id'] : '';
		$type = isset( $options['type'] ) ? $options['type'] : '';

		switch ( $type ) {

			case 'repeater' :
				return "bf-metabox-option[%s][%s][%d][%s]";
				break;

			case 'select':

				if ( isset( $options['multiple'] ) && $options['multiple'] ) {
					return "bf-metabox-option[{$this->id}][{$id}][]";
				} else {
					return "bf-metabox-option[{$this->id}][{$id}]";
				}

				break;

			default:
				return "bf-metabox-option[{$this->id}][{$id}]";
				break;

		}

	}


	/**
	 *  Metabox panel generator
	 *
	 * @param bool $is_ajax ignore ajax items
	 */
	public function callback( $is_ajax = false ) {

		$metabox_config = BF_Metabox_Core::get_metabox_config( $this->id );
		$items_has_tab  = $this->has_tab();
		$has_tab        = false;
		$has_wrapper    = $is_ajax !== true;

		if ( $has_wrapper ) {
			$wrapper = Better_Framework::html()->add( 'div' )->class( 'bf-metabox-wrap bf-clearfix' )->data( 'id', $this->id );
		}

		// Add Class For Post Format Filter
		if ( isset( $metabox_config['post_format'] ) && $has_wrapper ) {
			$wrapper->data( 'bf_pf_filter', implode( ',', $metabox_config['post_format'] ) );
		}
		$container = Better_Framework::html()->add( 'div' );
		if ( $is_ajax !== true ) {
			$container = $container->class( 'bf-metabox-container' );
		}

		$tab_counter = 0;

		$group_counter = array();

		if ( $items_has_tab && $is_ajax !== true ) {
			$container->class( 'bf-with-tabs' );
			$tabs_container = Better_Framework::html()->add( 'div' )->class( 'bf-metabox-tabs' );
			$tabs_container->text( $this->get_tabs() );
			if ( $has_wrapper ) {
				$wrapper->text( $tabs_container->display() );
			}
			Better_Framework()->assets_manager()->add_admin_css( '#bf_' . $this->id . ' .inside{margin: 0 !important; padding: 0 !important;}' );
		}

		if ( isset( $this->items['panel-id'] ) ) {
			$std_id = Better_Framework::options()->get_panel_std_id( $this->items['panel-id'] );
		} else {
			$std_id = 'std';
		}

		$metabox_fields = BF_Metabox_Core::get_metabox_fields( $this->id );

		$metabox_std = BF_Metabox_Core::get_metabox_std( $this->id );

		foreach ( $metabox_fields as $field_id => $field ) {

			if ( ! empty( $field['type'] ) && $field['type'] === 'id-holder' ) {
				continue;
			}

			if ( $is_ajax !== true && ! empty( $field['ajax-tab-field'] ) ) {  // Backward compatibility
				continue;
			}

			if ( $is_ajax !== true && ! empty( $field['ajax-section-field'] ) ) {
				continue;
			}

			$field['input_name'] = $this->input_name( $field );

			if ( $field['type'] === 'info' ) {
				if ( isset( $field['std'] ) ) {
					$field['value'] = $field['std'];
				} else {
					$field['value'] = '';
				}
			} else {
				$field['value'] = isset( $field['id'] ) && isset( $this->values[ $field['id'] ] ) ? $this->values[ $field['id'] ] : null;
			}

			if ( is_null( $field['value'] ) && isset( $metabox_std[ $field_id ][ $std_id ] ) ) {
				$field['value'] = $metabox_std[ $field_id ][ $std_id ];
			} elseif ( is_null( $field['value'] ) && isset( $metabox_std[ $field_id ]['std'] ) ) {
				$field['value'] = $metabox_std[ $field_id ]['std'];
			}

			if ( isset( $field['filter-field'] ) && $field['filter-field-value'] ) {

				// Get value if is available
				$filter_field_value = isset( $this->values[ $field['filter-field'] ] ) ? $this->values[ $field['filter-field'] ] : null;

				// is null means this is post create screen and filter field default value should be used for
				// default comparison
				if ( is_null( $filter_field_value ) ) {

					if ( isset( $metabox_std[ $field['filter-field'] ][ $std_id ] ) ) {
						$filter_field_value = $metabox_std[ $field['filter-field'] ][ $std_id ];
					} elseif ( isset( $metabox_std[ $field['filter-field'] ]['std'] ) ) {
						$filter_field_value = $metabox_std[ $field['filter-field'] ]['std'];
					} else {
						$filter_field_value = false;
					}

				}

				if ( $field['filter-field-value'] !== $filter_field_value ) {
					$field['section-css']['display'] = "none";
				}

			}

			if ( $field['type'] == 'repeater' ) {
				$field['clone-name-format'] = 'bf-metabox-option[$3][$4][$5][$6]';
				$field['metabox-id']        = $this->id;
				$field['metabox-field']     = true;
			}

			if ( $field['type'] == 'tab' || $field['type'] == 'subtab' ) {

				if ( $has_tab ) {

					// close all opened groups
					foreach ( array_reverse( $group_counter ) as $level_k => $level_v ) {

						if ( $level_v === 0 ) {
							continue;
						}

						for ( $i = 0; $i < $level_v; $i ++ ) {
							$container->text( $this->get_fields_group_close( $field ) );
						}

						$group_counter[ $level_k ] = 0;
					}
				}
				$is_subtab = $field['type'] == 'subtab';

				if ( $tab_counter != 0 ) {
					$container->text( '</div><!-- /Section -->' );
				}

				if ( $is_subtab ) {
					$container->text( "\n\n<!-- Section -->\n<div class='group subtab-group' id='bf-metabox-{$this->id}-{$field["id"]}'>\n" );
				} else {
					$container->text( "\n\n<!-- Section -->\n<div class='group' id='bf-metabox-{$this->id}-{$field["id"]}'>\n" );
				}
				$has_tab = true;
				$tab_counter ++;
				continue;
			}
			//
			// Close group
			//
			if ( $field['type'] == 'group_close' ) {

				if ( isset( $field['level'] ) && $field['level'] === 'all' ) {

					krsort( $group_counter );

					// close all opened groups
					foreach ( $group_counter as $level_k => $level_v ) {

						if ( $level_v === 0 ) {
							continue;
						}

						for ( $i = 0; $i < $level_v; $i ++ ) {
							$container->text( $this->get_fields_group_close( $field ) );
						}

						$group_counter[ $level_k ] = 0;
					}

				} else {

					krsort( $group_counter );

					// close last opened group
					foreach ( $group_counter as $level_k => $level_v ) {

						if ( ! $level_v ) {
							continue;
						}

						for ( $i = 0; $i < $level_v; $i ++ ) {
							$container->text( $this->get_fields_group_close( $field ) );
							$group_counter[ $level_k ] --;
							break;
						}

					}
				}


				continue;
			}

			//
			// Group
			// All nested groups and same level groups should be closed
			//
			if ( $field['type'] == 'group' ) {

				if ( ! isset( $field['level'] ) ) {
					$field['level'] = 0;
				}

				if ( ! isset( $group_counter[ $field['level'] ] ) ) {
					$group_counter[ $field['level'] ] = 0;
				}

				krsort( $group_counter );

				foreach ( $group_counter as $level_k => $level_v ) {

					if ( $level_k < $field['level'] ) {
						continue;
					}

					for ( $i = 0; $i < $level_v; $i ++ ) {
						$container->text( $this->get_fields_group_close( $field ) );
					}

					$group_counter[ $level_k ] = 0;
				}

				$container->text( $this->get_fields_group_start( $field ) );

				$group_counter[ $field['level'] ] ++;
			}


			if ( ! in_array( $field['type'], $this->supported_fields ) ) {
				continue;
			}

			// Filter Each Field For Post Formats!
			if ( isset( $field['post_format'] ) ) {

				if ( is_array( $field['post_format'] ) ) {
					$field_post_formats = implode( ',', $field['post_format'] );
				} else {
					$field_post_formats = $field['post_format'];
				}
				$container->text( "<div class='bf-field-post-format-filter' data-bf_pf_filter='{$field_post_formats}'>" );
			}

			$container->text(
				$this->section(
					call_user_func(
						array( $this, $field['type'] ),
						$field
					),
					$field
				)
			);

			// End Post Format Filter Wrapper
			if ( isset( $field['post_format'] ) ) {

				$container->text( "</div>" );
			}
		}

		// last sub tab closing
		if ( $has_tab ) {
			$container->text( "</div><!-- /Section -->" );
		}

		if ( $has_wrapper ) {
			$wrapper->text(
				$container->display()
			);
			echo $wrapper;  // escaped before
		} else {
			echo $container->display();
		}
	} // callback
}
<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


// Prevent Direct Access
defined( 'ABSPATH' ) or die;


// initialize all metaboxe
BF_Metabox_Core::init_metabox();


/**
 * This class handles all functionality of BetterFramework Meta box feature for creating, saving, editing
 * and another functionality like filtering metaboxe's for post types, pages and etc
 *
 * @package    BetterFramework
 * @since      1.0
 */
class BF_Metabox_Core {

	/**
	 * Contains all metabox's
	 *
	 * @var array
	 */
	public static $metabox = array();


	/**
	 * Contains config for all metabox's
	 *
	 * @var array
	 */
	public static $config = array();


	/**
	 * Contains all fields
	 *
	 * @var array
	 */
	public static $fields = array();


	/**
	 * Contains all std
	 *
	 * @var array
	 */
	public static $std = array();


	/**
	 * Contains all css
	 *
	 * @var array
	 */
	public static $css = array();


	/**
	 * Initializes all metaboxes
	 */
	public static function init_metabox() {

		static $loaded;

		if ( $loaded ) {
			return;
		}

		self::$metabox = apply_filters( 'better-framework/metabox/add', array() );

	}


	/**
	 * loads and returns metabox config
	 *
	 * @param string $metabox_id
	 *
	 * @return array
	 */
	public static function get_metabox_config( $metabox_id = '' ) {

		if ( empty( $metabox_id ) ) {
			return array();
		}

		if ( isset( self::$config[ $metabox_id ] ) ) {
			return self::$config[ $metabox_id ];
		}

		return self::$config[ $metabox_id ] = apply_filters( 'better-framework/metabox/' . $metabox_id . '/config', array() );
	}


	/**
	 * loads and returns metabox std values
	 *
	 * @param string $metabox_id
	 *
	 * @return array
	 */
	public static function get_metabox_std( $metabox_id = '' ) {

		if ( empty( $metabox_id ) || ! isset( self::$metabox[ $metabox_id ] ) ) {
			return array();
		}

		if ( isset( self::$std[ $metabox_id ] ) ) {
			return self::$std[ $metabox_id ];
		}

		return self::$std[ $metabox_id ] = apply_filters( 'better-framework/metabox/' . $metabox_id . '/std', array() );
	}


	/**
	 * loads and returns metabox std values
	 *
	 * @param string $metabox_id
	 *
	 * @return array
	 */
	public static function get_metabox_fields( $metabox_id = '' ) {

		if ( empty( $metabox_id ) || ! isset( self::$metabox[ $metabox_id ] ) ) {
			return array();
		}

		if ( isset( self::$fields[ $metabox_id ] ) ) {
			return self::$fields[ $metabox_id ];
		}

		return self::$fields[ $metabox_id ] = apply_filters( 'better-framework/metabox/' . $metabox_id . '/fields', array() );
	}


	/**
	 * loads and returns metabox css
	 *
	 * @param string $metabox_id
	 *
	 * @return array
	 */
	public static function get_metabox_css( $metabox_id = '' ) {

		if ( empty( $metabox_id ) || ! isset( self::$metabox[ $metabox_id ] ) ) {
			return array();
		}

		if ( isset( self::$css[ $metabox_id ] ) ) {
			return self::$css[ $metabox_id ];
		}

		return self::$css[ $metabox_id ] = apply_filters( 'better-framework/metabox/' . $metabox_id . '/css', array() );
	}


	/**
	 * Used to add action for constructing the meta box
	 *
	 * @since     1.0
	 * @access    public
	 */
	public function __construct() {

		self::init_metabox();

		add_action( 'add_meta_boxes', array( $this, 'add_meta_boxes' ) );

		add_action( 'pre_post_update', array( $this, 'save' ), 1 );

		add_action( 'better-framework/metabox/ajax-tab', array( $this, 'ajax_tab' ), 10, 3 );
	}


	/**
	 * Used for creating meta boxes
	 *
	 * Callback: add_meta_boxes action
	 *
	 * @since   1.0
	 * @access  public
	 */
	public function add_meta_boxes() {

		if ( ! class_exists( 'BF_Metabox_Front_End_Generator' ) ) {
			require BF_PATH . 'metabox/class-bf-metabox-front-end-generator.php';
		}

		foreach ( (array) self::$metabox as $metabox_id => $metabox ) {

			$metabox_config = self::get_metabox_config( $metabox_id );

			if ( empty( $metabox_config ) ) {
				continue;
			}

			if ( ! $this->can_output( $metabox_config ) ) {
				continue;
			}

			$metabox_config['fields'] = self::get_metabox_fields( $metabox_id );
			$metabox_value            = $this->get_meta_data( $metabox_id );
			$title                    = empty( $metabox_config['title'] ) ? '' : $metabox_config['title'];
			$generator                = new BF_Metabox_Front_End_Generator( $metabox_config, $metabox_id, $metabox_value );

			if ( is_array( $metabox_config['pages'] ) ) {

				foreach ( $metabox_config['pages'] as $page ) {
					add_meta_box(
						'bf_' . $metabox_id,
						$title,
						array( $generator, 'callback' ),
						$page,
						isset( $metabox_config['context'] ) ? $metabox_config['context'] : 'normal',
						isset( $metabox_config['priority'] ) ? $metabox_config['priority'] : 'default'
					);
				}

			} elseif ( is_string( $metabox_config['pages'] ) ) {

				add_meta_box(
					'bf_' . $metabox_id,
					$title,
					array( $generator, 'callback' ),
					$metabox_config['pages'],
					isset( $metabox_config['context'] ) ? $metabox_config['context'] : 'normal',
					isset( $metabox_config['priority'] ) ? $metabox_config['priority'] : 'default'
				);

			}
		}// foreach

	} // add_meta_boxes


	/**
	 * Used for retrieve meta data values
	 *
	 * @param   string $id      meta box id
	 * @param   int    $post_id meta box id
	 *
	 * @since    1.0
	 * @return  array
	 * @access   public
	 */
	public function get_meta_data( $id = '', $post_id = 0 ) {

		global $pagenow;

		$output = array();

		if ( isset( self::$metabox['panel-id'] ) ) {
			$std_id = Better_Framework::options()->get_panel_std_id( self::$metabox['panel-id'] );
		} else {
			$std_id = 'std';
		}

		$metabox_std = self::get_metabox_std( $id );

		if ( $pagenow == 'post-new.php' ) {

			if ( ! empty( $metabox_std ) ) {

				foreach ( (array) $metabox_std as $field_id => $field ) {

					if ( isset( $field[ $std_id ] ) ) {
						$output[ $field_id ] = $field[ $std_id ];
					} elseif ( isset( $field['std'] ) ) {
						$output[ $field_id ] = $field['std'];
					}
				}

			}

			return $output;
		}

		$meta = get_post_custom( $post_id );

		foreach ( (array) $metabox_std as $field_id => $field ) {

			if ( isset( $meta[ $field_id ] ) ) {

				if ( is_serialized( $meta[ $field_id ][0] ) ) {
					$output[ $field_id ] = unserialize( $meta[ $field_id ][0] );
				} else {
					$output[ $field_id ] = $meta[ $field_id ][0];
				}

			} else {

				if ( isset( $field[ $std_id ] ) ) {
					$output[ $field_id ] = $field[ $std_id ];
				} elseif ( isset( $field['std'] ) ) {
					$output[ $field_id ] = $field['std'];
				}
			}

		}

		return $output;
	}


	/**
	 * Generates fields of ajaxified tab
	 *
	 * @param $tab_id
	 * @param $metabox_id
	 * @param $object_id
	 */
	public function ajax_tab( $tab_id, $metabox_id, $object_id ) {

		$metabox_config           = self::get_metabox_config( $metabox_id );
		$metabox_config['fields'] = self::get_metabox_fields( $metabox_id );
		$metabox_values           = array();
		$use_generator            = true;

		if ( empty( $metabox_config['fields'][ $tab_id ]['ajax-section-handler'] ) ) {

			$metabox_values = $this->get_meta_data( $metabox_id, $object_id );

			foreach ( $metabox_config['fields'] as $idx => $field ) {

				// Backward compatibility
				if ( isset( $field['ajax-tab-field'] ) ) {
					$field['ajax-section-field'] = $field['ajax-tab-field'];
				}

				if ( empty( $field['ajax-section-field'] ) || $field['ajax-section-field'] !== $tab_id ) {
					unset( $metabox_config['fields'][ $idx ] );
				}
			}
		} else {

			$parent_field = $metabox_config['fields'][ $tab_id ];

			$args = isset( $parent_field['ajax-section-handler-args'] ) ? $parent_field['ajax-section-handler-args'] : array();
			$args = array_merge( $args, compact( 'metabox_id', 'section_id' ) );

			if (
				! isset( $parent_field['ajax-section-handler-type'] ) ||
				$parent_field['ajax-section-handler-type'] === 'field-generator'
			) {

				$metabox_config['fields'] = call_user_func( $parent_field['ajax-section-handler'], $args );

				foreach ( $metabox_config['fields'] as $key => $field ) {
					$metabox_values[ $field['id'] ] = bf_get_post_meta( $field['id'], $object_id );
				}
			} else {

				$use_generator = false;
				$out           = call_user_func( $parent_field['ajax-section-handler'], $args );

			}
		}

		if ( $use_generator ) {

			if ( ! class_exists( 'BF_Metabox_Front_End_Generator' ) ) {
				require BF_PATH . 'metabox/class-bf-metabox-front-end-generator.php';
			}

			self::$fields[ $metabox_id ] = $metabox_config['fields'];
			$generator                   = new BF_Metabox_Front_End_Generator( $metabox_config, $metabox_id, $metabox_values );

			ob_start();
			$generator->callback( true );
			$out = ob_get_clean();

		}

		wp_send_json( array( 'out' => $out, 'tab_id' => $tab_id ) );

	}


	/**
	 * Calculate when meta box can added
	 *
	 * @param   array $config Configuration values of meta box
	 *
	 * @return bool
	 * @since   1.1.1
	 * @access  public
	 */
	public function can_output( $config ) {

		$post_id = bf_get_admin_current_post_id();

		// post types
		switch ( true ) {
			case ( ! isset( $config['pages'] ) || empty( $config['pages'] ) ):
				$post_types = array();
				break;
			case ( is_array( $config['pages'] ) ):
				$post_types = $config['pages'];
				break;
			case ( is_string( $config['pages'] ) ):
				$post_types[] = $config['pages'];
				break;
		}

		// include_template
		switch ( true ) {

			case( ! isset( $config['include_template'] ) || empty( $config['include_template'] ) ):
				$include_template = array();
				break;

			case( is_array( $config['include_template'] ) ):
				$include_template = $config['include_template'];
				break;

			case ( is_string( $config['include_template'] ) ):
				$include_template[] = $config['include_template'];
				break;
		}

		// exclude_template
		switch ( true ) {

			case ( ! isset( $config['exclude_template'] ) || empty( $config['exclude_template'] ) ):
				$exclude_template = array();
				break;

			case ( is_array( $config['exclude_template'] ) ):
				$exclude_template = $config['exclude_template'];
				break;

			case ( is_string( $config['exclude_template'] ) ):
				$exclude_template[] = $config['exclude_template'];
				break;

		}


		if ( ! empty( $include_template ) || ! empty( $exclude_template ) ) {
			$template_file = get_post_meta( $post_id, '_wp_page_template', true );
		}

		$can_output = true;

		// processing order: "exclude" then "include"
		// processing order: "template"

		if ( ! empty( $include_template ) || ! empty( $exclude_template ) ) {

			if ( ! empty( $exclude_template ) ) {
				if ( in_array( $template_file, $exclude_template ) ) {
					$can_output = false;
				}
			}

			// excludes are not set use "include only" mode
			if ( empty( $exclude_template ) ) {
				$can_output = false;
			}

			if ( ! empty( $include_template ) ) {

				if ( in_array( $template_file, $include_template ) ) {
					$can_output = true;
				}

			}
		}

		// Filter for post types
		$current_post_type = bf_get_admin_current_post_type();

		if ( isset( $current_post_type ) && ! in_array( $current_post_type, $post_types ) ) {
			$can_output = false;
		}

		return $can_output;
	}


	/**
	 * Update Post Meta
	 *
	 * @param   string $id  The id post
	 * @param   string $key Post meta key name
	 * @param   string $val Post meta key value
	 *
	 * @static
	 * @since   1.0
	 * @return  bool
	 */
	public static function update( $id, $key, $val ) {

		return update_post_meta( $id, $key, $val );
	}


	/**
	 * Save post meta box values
	 *
	 * Callback: pre_post_update action
	 *
	 * @param   int $post_id
	 *
	 * @static
	 * @return  mixed
	 * @since   1.0
	 */
	public function save( $post_id ) {

		if (
			empty( $_POST['bf-metabox-option'] )
			|| ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
			|| ( ! isset( $_POST['post_ID'] )
			     || $post_id != $_POST['post_ID'] )
			|| ! current_user_can( 'edit_post', $post_id )
		) {
			return $post_id;
		}


		foreach ( self::$metabox as $metabox_id => $metabox ) {

			if ( ! isset( $_POST['bf-metabox-option'][ $metabox_id ] ) ) {
				continue;
			}

			$metabox_std = self::get_metabox_std( $metabox_id );

			if ( empty( $metabox_std ) || ! is_array( $metabox_std ) ) {
				continue;
			}

			$new_value = &$_POST['bf-metabox-option'][ $metabox_id ];

			foreach ( $metabox_std as $field_key => $_field_value ) {

				// value not passed
				if ( ! isset( $new_value[ $field_key ] ) ) {
					continue;
				}

				$field_value = &$new_value[ $field_key ];

				if ( isset( $metabox['panel-id'] ) ) {
					$std_id = Better_Framework::options()->get_panel_std_id( $metabox['panel-id'] );
				} else {
					$std_id = 'std';
				}

				// Save value if save-std is true or not defined
				if ( ! isset( $metabox_std[ $field_key ]['save-std'] ) || $metabox_std[ $field_key ]['save-std'] == true ) {
					self::update( $post_id, $field_key, $field_value );
				} // Don't Save Default Value
				elseif ( isset( $metabox_std[ $field_key ]['save-std'] ) ) {

					// If style std defined then save it
					if ( isset( $metabox_std[ $field_key ][ $std_id ] ) ) {

						if ( $metabox_std[ $field_key ][ $std_id ] != $field_value ) {
							self::update( $post_id, $field_key, $field_value );
						} else {
							delete_post_meta( $post_id, $field_key );
						}

					} // If style std defined then save it
					elseif ( isset( $metabox_std[ $field_key ]['std'] ) ) {

						if ( $metabox_std[ $field_key ]['std'] != $field_value ) {
							self::update( $post_id, $field_key, $field_value );
						} else {
							delete_post_meta( $post_id, $field_key );
						}

					}

				} // Delete Custom field
				else {
					delete_post_meta( $post_id, $field_key );
				}
			}
		} // foreach
	} // save
}
<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


if ( ! function_exists( 'bf_get_post_meta' ) ) {

	/**
	 * Used for retrieving meta fields ofr  posts and pages
	 *
	 * @param null        $key           Field ID
	 * @param null        $post_id       Post ID (Optional)
	 * @param null|string $force_default Default value (Optional)
	 *
	 * @global WPDB       $wpdb          WordPress database access object.
	 *
	 * @return mixed|void
	 */
	function bf_get_post_meta( $key = null, $post_id = null, $force_default = null ) {

		global $wp_query;

		if ( is_null( $post_id ) ) {
			global $post;
			$post_id = isset( $post->ID ) ? $post->ID : 0;
		}

		/**
		 * Detecting the BuddyPress $post object resetting to prevent returning false as default value.
		 *
		 * @see bp_theme_compat_reset_post function for more info
		 */
		static $bp_component_post_id;

		if ( empty( $post_id ) && $wp_query->is_main_query() ) {

			if ( ! isset( $bp_component_post_id ) ) {
				$bp_component_post_id = bf_bp_get_component_page_id();
			}

			$post_id = $bp_component_post_id;
		}

		$meta = get_post_meta( $post_id, $key, true );

		if ( $meta == '' && ! is_null( $force_default ) ) {
			return $force_default;
		}

		// If Meta check for default value
		if ( $meta !== '' ) {
			return $meta;
		}

		// initialize base BF metabox
		if ( ! class_exists( 'BF_Metabox_Core' ) ) {
			Better_Framework()->post_meta();
		}

		foreach ( (array) BF_Metabox_Core::$metabox as $metabox_id => $metabox ) {

			// get style id for current metabox
			if ( isset( $metabox['panel-id'] ) ) {
				$std_id = Better_Framework()->options()->get_panel_std_id( $metabox['panel-id'] );
			} else {
				$std_id = 'std';
			}

			$metabox_std = BF_Metabox_Core::get_metabox_std( $metabox_id );

			if ( isset( $metabox_std[ $key ] ) ) {
				if ( isset( $metabox_std[ $key ][ $std_id ] ) ) {
					return $metabox_std[ $key ][ $std_id ];
				} elseif ( isset( $metabox_std[ $key ]['std'] ) ) {
					return $metabox_std[ $key ]['std'];
				} else {
					return '';
				}
			}

		}

		return '';
	}
}


if ( ! function_exists( 'bf_echo_post_meta' ) ) {

	/**
	 * Used for retrieving meta fields ofr  posts and pages
	 *
	 * @param null        $key           Field ID
	 * @param null        $post_id       Post ID (Optional)
	 * @param null|string $force_default Default value (Optional)
	 *
	 * @return mixed|void
	 */
	function bf_echo_post_meta( $key = null, $post_id = null, $force_default = null ) {

		echo bf_get_post_meta( $key, $post_id, $force_default ); // escaped before
	}
}<?php
die;<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


$classes = $this->get_classes( $options );
$iri     = isset( $options['repeater_item'] ) && $options['repeater_item'] == true; // Is this section for a repeater item

$section_classes   = $classes['section'];
$container_classes = $classes['container'];

$heading_classes  = $classes['heading'];
$controls_classes = $classes['controls'];
$explain_classes  = $classes['explain'];

if ( $iri ) {

	$section_classes  .= ' ' . $classes['repeater-section'];
	$heading_classes  .= ' ' . $classes['repeater-heading'];
	$controls_classes .= ' ' . $classes['repeater-controls'];
	$explain_classes  .= ' ' . $classes['repeater-explain'];

} else {

	$section_classes  .= ' ' . $classes['nonrepeater-section'];
	$heading_classes  .= ' ' . $classes['nonrepeater-heading'];
	$controls_classes .= ' ' . $classes['nonrepeater-controls'];
	$explain_classes  .= ' ' . $classes['nonrepeater-explain'];

}

$section_classes  .= ' ' . $classes['section-class-by-filed-type'];
$heading_classes  .= ' ' . $classes['heading-class-by-filed-type'];
$controls_classes .= ' ' . $classes['controls-class-by-filed-type'];
$explain_classes  .= ' ' . $classes['explain-class-by-filed-type'];

if ( empty( $options['desc'] ) ) {
	$section_classes .= ' no-desc ';
}


$section_css_attr = $this->get_section_css_attr( $options );
$section_attr     = $this->get_section_filter_attr( $options );

?>
<div
		class="<?php echo esc_attr( $container_classes ); ?> bf-section-container bf-metabox bf-clearfix" <?php echo $section_css_attr; // escaped before ?> <?php echo $section_attr; // escaped before ?>>
	<div class="<?php echo esc_attr( $section_classes ); ?> bf-clearfix"
	     data-id="<?php echo esc_attr( $options['id'] ); ?>">

		<div class="<?php echo esc_attr( $heading_classes ); ?> bf-clearfix">
			<h3><label
						for="<?php echo esc_attr( $options['input_name'] ); ?>"><?php echo esc_html( $options['name'] ); ?></label>
			</h3>
		</div>

		<div class="<?php echo esc_attr( $controls_classes ); ?> bf-clearfix">
			<?php echo $input; // escaped before ?>
		</div>

		<?php if ( ! empty( $options['desc'] ) ) { ?>
			<div
					class="<?php echo esc_attr( $explain_classes ); ?> bf-clearfix"><?php echo wp_kses( $options['desc'], bf_trans_allowed_html() ); ?></div>
		<?php } ?>

	</div>
</div><?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

?>
<div class="bf-section-container bf-clearfix">
	<div class="bf-section-hr bf-clearfix">
		<?php echo $input; // escaped before ?>
	</div>
</div><?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

$style = ! empty( $options['layout'] ) ? $options['layout'] : 'style-1';

?>
<div class="bf-section-container bf-metabox bf-clearfix">
	<div class="bf-section-heading bf-clearfix <?php echo $style; ?>"
	     data-id="<?php echo esc_attr( $options['id'] ); ?>"
	     id="<?php echo esc_attr( $options['id'] ); ?>">
		<div class="bf-section-heading-title bf-clearfix">
			<h3><?php echo esc_html( $options['name'] ); ?></h3>
		</div>
		<?php if ( ! empty( $options['desc'] ) ) { ?>
			<div
					class="bf-section-heading-desc bf-clearfix"><?php echo wp_kses( $options['desc'], bf_trans_allowed_html() ); ?></div>
		<?php } ?>
	</div>
</div><?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


$classes = $this->get_classes( $options );
$iri     = isset( $options['repeater_item'] ) && $options['repeater_item'] == true; // Is this section for a repeater item

$section_classes = $classes['section'] . ' bf-widget-field-section';

$heading_classes  = $classes['heading'] . ' bf-heading';
$controls_classes = $classes['controls'] . ' bf-control not-prepared';
$explain_classes  = $classes['explain'] . ' bf-desc';

if ( $iri ) {

	$section_classes  .= ' ' . $classes['repeater-section'];
	$heading_classes  .= ' ' . $classes['repeater-heading'];
	$controls_classes .= ' ' . $classes['repeater-controls'];
	$explain_classes  .= ' ' . $classes['repeater-explain'];

} else {

	$section_classes  .= ' ' . $classes['nonrepeater-section'];
	$heading_classes  .= ' ' . $classes['nonrepeater-heading'];
	$controls_classes .= ' ' . $classes['nonrepeater-controls'];
	$explain_classes  .= ' ' . $classes['nonrepeater-explain'];

}

$section_classes  .= ' ' . $classes['section-class-by-filed-type'];
$heading_classes  .= ' ' . $classes['heading-class-by-filed-type'];
$controls_classes .= ' ' . $classes['controls-class-by-filed-type'];
$explain_classes  .= ' ' . $classes['explain-class-by-filed-type'];


if ( ! isset( $options['info-type'] ) ) {
	$options['info-type'] = 'info';
}

if ( ! isset( $options['state'] ) ) {
	$options['state'] = 'open';
}

$section_attr = $this->get_section_filter_attr( $options );

?>
<div class="bf-section-container bf-metabox bf-clearfix" <?php echo $section_attr; ?>>
	<div
			class="bf-section-info <?php echo esc_attr( $options['info-type'] ); ?> <?php echo esc_attr( $options['state'] ); ?> bf-clearfix">
		<div class="bf-section-info-title bf-clearfix">
			<h3><?php

				switch ( $options['info-type'] ) {

					case 'help':
						echo '<i class="fa fa-support"></i> ';
						break;

					case 'info':
						echo '<i class="fa fa-info"></i> ';
						break;

					case 'warning':
						echo '<i class="fa fa-warning"></i> ';
						break;

					case 'danger':
						echo '<i class="fa fa-exclamation"></i> ';
						break;

					default:
						echo '<i class="fa fa-info"></i> ';
						break;


				}

				echo esc_html( $options['name'] ); ?></h3>
		</div>
		<div class="<?php echo esc_attr( $controls_classes ); ?>  bf-clearfix">
			<?php echo $input; // escaped before ?>
		</div>
	</div>
</div><?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


if ( ! function_exists( 'bf_get_query_var_paged' ) ) {
	/**
	 * Handy function used to find current page paged query var
	 * This is home page firendly
	 *
	 * @since 2.0
	 *
	 * @param int $default
	 *
	 * @return int|mixed
	 */
	function bf_get_query_var_paged( $default = 1 ) {

		return get_query_var( 'paged' ) ? get_query_var( 'paged' ) : ( get_query_var( 'page' ) ? get_query_var( 'page' ) : $default );

	}
}


if ( ! function_exists( 'bf_is_search_page' ) ) {
	/**
	 * Used for detecting current page is search page or not
	 */
	function bf_is_search_page() {

		if ( stripos( $_SERVER['REQUEST_URI'], '/?s=' ) === false && stripos( $_SERVER['REQUEST_URI'], '/search/' ) === false ) {
			return false;
		} elseif ( ! is_search() ) {
			return false;
		}

		return true;
	}
}


if ( ! function_exists( 'bf_get_author_archive_user' ) ) {
	/**
	 * Used for finding user in author archive page
	 *
	 * @since   2.0
	 * @return WP_User|false WP_User object on success, false on failure.
	 */
	function bf_get_author_archive_user() {

		global $author_name, $author;

		return isset( $_GET['author_name'] ) ? get_user_by( 'slug', $author_name ) : get_userdata( intval( $author ) );

	}
}


if ( ! function_exists( 'bf_get_admin_current_post_type' ) ) {
	/**
	 * Used to check for the current post type, works when creating or editing a
	 * new post, page or custom post type.
	 *
	 * @since    1.0
	 * @return    string [custom_post_type], page or post
	 */
	function bf_get_admin_current_post_type() {

		// admin side
		if ( is_admin() ) {

			$uri = isset( $_SERVER['REQUEST_URI'] ) ? $_SERVER['REQUEST_URI'] : null;

			if ( isset( $uri ) ) {

				$uri_parts = parse_url( $uri );

				$file = basename( $uri_parts['path'] );

				$_check = array(
					'post.php'     => '',
					'post-new.php' => '',
				);

				// Post types
				if ( $uri AND isset( $_check[ $file ] ) ) {
					$post_id = bf_get_admin_current_post_id();

					$post_type = isset( $_GET['post_type'] ) ? $_GET['post_type'] : null;

					$post_type = $post_id ? get_post_type( $post_id ) : $post_type;

					if ( isset( $post_type ) ) {

						return $post_type;

					} else {

						// because of the 'post.php' and 'post-new.php' checks above, we can default to 'post'
						return 'post';

					}
				} // Taxonomies
				elseif ( $uri AND ( $file === 'edit-tags.php' || $file === 'term.php' ) ) {

					$taxonomy = isset( $_GET['taxonomy'] ) ? $_GET['taxonomy'] : null;

					return $taxonomy;

				} // Pages custom css
				elseif ( isset( $_GET['bs_per_page_custom_css'] ) && ! empty( $_GET['bs_per_page_custom_css'] ) ) {

					if ( isset( $_GET['post_id'] ) && ! empty( $_GET['post_id'] ) ) {

						return get_post_type( $_GET['post_id'] );

					}

				}
			}

		} // if used in front end
		else {

			return get_post_type( bf_get_admin_current_post_id() );

		}


		return null;
	}
}


if ( ! function_exists( 'bf_get_admin_current_post_id' ) ) {
	/**
	 * Used to get the current post id.
	 *
	 * @since    1.0
	 * @return    int post ID
	 */
	function bf_get_admin_current_post_id() {

		global $post;

		$p_post_id = isset( $_POST['post_ID'] ) ? $_POST['post_ID'] : null;

		$g_post_id = isset( $_GET['post'] ) ? $_GET['post'] : null;

		$post_id = $g_post_id ? $g_post_id : $p_post_id;

		$post_id = isset( $post->ID ) ? $post->ID : $post_id;

		if ( isset( $post_id ) ) {
			return (integer) $post_id;
		} else {
			return 0;
		}

	}
}<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


if ( ! function_exists( 'bf_enqueue_modal' ) ) {
	/**
	 * Enqueue BetterFramework modals safely
	 *
	 * @param $modal_key
	 */
	function bf_enqueue_modal( $modal_key = '' ) {

		Better_Framework::assets_manager()->add_modal( $modal_key );

	}
}


if ( ! function_exists( 'bf_enqueue_style' ) ) {
	/**
	 * @see   wp_enqueue_style for more documentation.
	 *
	 * @param string           $handle
	 * @param string           $src
	 * @param array            $deps
	 * @param string           $file_path
	 * @param string|bool|null $ver
	 */
	function bf_enqueue_style( $handle, $src = '', $deps = array(), $file_path = '', $ver = false ) {

		// check list to change for backward compatibility
		$check = array(
			'better-social-font-icon' => 'bs-icons'
		);

		if ( isset( $check[ $handle ] ) ) {
			$handle = $check[ $handle ];
		}

		if ( ! function_exists( 'bf_booster_is_active' ) ||
		     ! bf_booster_is_active( 'minify-css' )
		) {
			wp_enqueue_style( $handle, $src, $deps, $ver );

			return;
		}

		if ( $src ) {
			bf_styles()->add( $handle, $src, $deps, $ver, 'all' );
		}

		if ( $file_path ) {
			bf_styles()->files_path[ $handle ] = $file_path;
		}

		bf_styles()->enqueue( $handle );
	}
}


if ( ! function_exists( 'bf_enqueue_wp_script_deps' ) ) {

	function bf_enqueue_wp_script_deps( $handle ) {

		if ( ! isset( bf_scripts()->registered[ $handle ] ) ) {
			return;
		}

		$deps = &bf_scripts()->registered[ $handle ]->deps;
		foreach ( $deps as $index => $dep ) {

			if ( ! isset( bf_scripts()->registered[ $dep ] ) ) {

				if ( ! isset( wp_scripts()->registered[ $dep ] ) ) {
					continue;
				}

				unset( $deps[ $index ] );

				if ( wp_scripts()->registered[ $dep ]->args === 1 ) {
					wp_scripts()->registered[ $dep ]->args = null;
				}

				if ( ! wp_script_is( $dep ) ) {
					wp_enqueue_script( $dep );
				}

			} else {

				bf_enqueue_wp_script_deps( $dep );
			}
		}
	}
}


if ( ! function_exists( 'bf_enqueue_script' ) ) {
	/**
	 * Enqueue BetterFramework scripts safely
	 *
	 * @see   wp_enqueue_script for more documentation.
	 *
	 * @param string           $handle
	 * @param string           $src
	 * @param array            $deps
	 * @param string           $file_path
	 * @param string|bool|null $ver
	 */
	function bf_enqueue_script( $handle, $src = '', $deps = array(), $file_path = '', $ver = false ) {

		if ( ! function_exists( 'bf_booster_is_active' ) ||
		     ! bf_booster_is_active( 'minify-js' )
		) {
			wp_enqueue_script( $handle, $src, $deps, $ver, true );

			return;
		}

		if ( $src ) {
			bf_scripts()->add( $handle, $src, $deps, $ver, '1' );
		}

		if ( $file_path ) {
			bf_scripts()->files_path[ $handle ] = $file_path;
		}

		bf_enqueue_wp_script_deps( $handle );

		bf_scripts()->enqueue( $handle );
	}
}


if ( ! function_exists( 'bf_register_script' ) ) {

	function bf_register_script( $handle, $src = '', $deps = array(), $file_path = '', $ver = false ) {

		if ( ! function_exists( 'bf_booster_is_active' ) ||
		     ! bf_booster_is_active( 'minify-js' )
		) {
			wp_register_script( $handle, $src, $deps, $ver );

			return;
		}

		if ( $file_path ) {
			bf_scripts()->files_path[ $handle ] = $file_path;
		}

		bf_scripts()->add( $handle, $src, $deps, $ver, '1' );
	}
}


if ( ! function_exists( 'bf_deregister_script' ) ) {

	function bf_deregister_script( $handle ) {

		if ( function_exists( 'bf_booster_is_active' ) &&
		     bf_booster_is_active( 'minify-js' )
		) {
			bf_scripts()->remove( $handle );
		} else {
			bf_call_func( 'wp' . '_' . 'deregister' . '_script', $handle );
		}
	}
}


if ( ! function_exists( 'bf_print_scripts' ) ) {

	/**
	 * Print scripts in document head that are in the $handles queue.
	 *
	 * @param string|bool|array $handles
	 *
	 * @return array
	 */
	function bf_print_scripts( $handles = false ) {

		if ( ! function_exists( 'bf_booster_is_active' ) ||
		     ! bf_booster_is_active( 'minify-js' )
		) {
			return wp_print_scripts( $handles );
		}

		return bf_scripts()->do_items( $handles );
	}
}


if ( ! function_exists( 'bf_add_style_file' ) ) {

	/**
	 * Append inline css content into a file
	 *
	 * @param string   $id unique name
	 * @param callable $content_cb
	 *
	 * @since 2.9.0
	 */
	function bf_add_style_file( $id, $content_cb ) {

		if ( function_exists( 'bf_styles' ) ) {

			bf_styles()->add_css_file( $id, $content_cb );

		} elseif ( function_exists( 'wp_add_inline_style' ) ) {

			if ( $style = call_user_func( $content_cb ) ) {

				wp_add_inline_style( $id, $style );
			}
		}
	}
}


if ( ! function_exists( 'bf_register_style' ) ) {

	function bf_register_style( $handle, $src = '', $deps = array(), $file_path = '', $ver = false, $media = '1' ) {

		if ( ! function_exists( 'bf_booster_is_active' ) ||
		     ! bf_booster_is_active( 'minify-css' )
		) {
			wp_register_style( $handle, $src, $deps, $ver );

			return;
		}

		if ( $file_path ) {
			bf_styles()->files_path[ $handle ] = $file_path;
		}

		bf_styles()->add( $handle, $src, $deps, $ver, $media );
	}
}


if ( ! function_exists( 'bf_deregister_style' ) ) {

	function bf_deregister_style( $handle ) {

		if ( function_exists( 'bf_booster_is_active' ) &&
		     bf_booster_is_active( 'minify-css' )
		) {
			bf_styles()->remove( $handle );
		} else {
			wp_deregister_style( $handle );
		}
	}
}


if ( ! function_exists( 'bf_print_styles' ) ) {

	/**
	 * Print scripts in document head that are in the $handles queue.
	 *
	 * @param string|bool|array $handles
	 *
	 * @return array
	 */
	function bf_print_styles( $handles ) {

		if ( ! function_exists( 'bf_booster_is_active' ) ||
		     ! bf_booster_is_active( 'minify-css' )
		) {
			return wp_print_styles( $handles );
		}

		return bf_styles()->do_items( $handles );
	}
}


if ( ! function_exists( 'bf_add_jquery_js' ) ) {
	/**
	 * Used for adding inline js to front end
	 *
	 * @param string $code
	 * @param bool   $to_top
	 * @param bool   $force
	 */
	function bf_add_jquery_js( $code = '', $to_top = false, $force = false ) {

		Better_Framework::assets_manager()->add_jquery_js( $code, $to_top, $force );

	}
}


if ( ! function_exists( 'bf_add_js' ) ) {
	/**
	 * Used for adding inline js to front end
	 *
	 * @param string $code
	 * @param bool   $to_top
	 * @param bool   $force
	 */
	function bf_add_js( $code = '', $to_top = false, $force = false ) {

		Better_Framework::assets_manager()->add_js( $code, $to_top, $force );

	}
}


if ( ! function_exists( 'bf_add_css' ) ) {
	/**
	 * Used for adding inline css to front end
	 *
	 * @param string $code
	 * @param bool   $to_top
	 * @param bool   $force
	 */
	function bf_add_css( $code = '', $to_top = false, $force = false ) {

		Better_Framework::assets_manager()->add_css( $code, $to_top, $force );

	}
}


if ( ! function_exists( 'bf_add_admin_js' ) ) {
	/**
	 * Used for adding inline js to back end
	 *
	 * @param string $code
	 * @param bool   $to_top
	 * @param bool   $force
	 */
	function bf_add_admin_js( $code = '', $to_top = false, $force = false ) {

		Better_Framework::assets_manager()->add_admin_js( $code, $to_top, $force );

	}
}


if ( ! function_exists( 'bf_add_admin_css' ) ) {
	/**
	 * Used for adding inline css to back end
	 *
	 * @param string $code
	 * @param bool   $to_top
	 * @param bool   $force
	 */
	function bf_add_admin_css( $code = '', $to_top = false, $force = false ) {

		Better_Framework::assets_manager()->add_admin_css( $code, $to_top, $force );

	}
}


if ( ! function_exists( 'bf_append_suffix' ) ) {
	/**
	 * Used for adding .min quickly
	 *
	 * @param string $before
	 * @param string $after
	 *
	 * @return string
	 */
	function bf_append_suffix( $before = '', $after = '' ) {

		static $suffix;

		if ( is_null( $suffix ) ) {
			$suffix = bf_is( 'dev' ) ? '' : '.min';
		}

		return $before . $suffix . $after;
	}
}

if ( ! function_exists( 'bf_enqueue_tinymce_style' ) ) {
	/**
	 * Register style for tinymce view add-on
	 *
	 * @param string $type inline|custom|extra|registered
	 * @param string $data
	 *                     bf_add_style_file() handle id if $type == extra
	 *                     unique handle id              if $type == registered
	 *                     custom inline css code        if $type == inline
	 *                     stylesheet url                if $type == inline
	 *
	 *
	 * @since 3.0.0
	 */
	function bf_enqueue_tinymce_style( $type, $data ) {

		$enqueue = array();

		if ( $type === 'inline' ) {
			$enqueue = array(
				'type' => 'inline',
				'data' => $data,
			);
		} elseif ( $type === 'custom' ) {
			$enqueue = array(
				'type' => 'custom',
				'url'  => $data,
			);
		} elseif ( $type === 'extra' ) {
			$enqueue = array(
				'type'    => 'extra',
				'handles' => (array) $data,
			);
		} elseif ( $type === 'registered' ) {
			$enqueue = array(
				'type'    => 'registered',
				'handles' => (array) $data,
			);
		}
		if ( empty( BF_Shortcodes_Manager::$tinymce_extra_enqueues['styles'] ) ) {
			BF_Shortcodes_Manager::$tinymce_extra_enqueues['styles'] = array();
		}

		BF_Shortcodes_Manager::$tinymce_extra_enqueues['styles'][] = $enqueue;
	}
}


if ( ! function_exists( '_bf_normalize_enqueue_tinymce' ) ) {
	/**
	 * @see   bf_enqueue_tinymce_style for documentation
	 * @see   BF_Shortcodes_Manager::tinymce_view_shortcode
	 *
	 * @param string $type
	 * @param string $data
	 *
	 * @since 3.0.0
	 * @return array
	 */
	function _bf_normalize_enqueue_tinymce( $type, $data ) {

		$enqueue = array();

		if ( $type === 'inline' ) {
			$enqueue = array(
				'type' => 'inline',
				'data' => $data,
			);
		} elseif ( $type === 'custom' ) {
			$enqueue = array(
				'type' => 'custom',
				'url'  => $data,
			);
		} elseif ( $type === 'extra' ) {
			$enqueue = array(
				'type'    => 'extra',
				'handles' => (array) $data,
			);
		} elseif ( $type === 'registered' ) {
			$enqueue = array(
				'type'    => 'registered',
				'handles' => (array) $data,
			);
		}

		return $enqueue;
	}

}
if ( ! function_exists( 'bf_enqueue_tinymce_style' ) ) {
	/**
	 * Register style for tinymce view add-on
	 *
	 * @param string $type inline|custom|extra|registered
	 * @param string $data
	 *                     bf_add_style_file() handle id if $type == extra
	 *                     unique handle id              if $type == registered
	 *                     custom inline css code        if $type == inline
	 *                     stylesheet url                if $type == custom
	 *
	 *
	 * @since 3.0.0
	 * @return true on success or false on failure
	 */
	function bf_enqueue_tinymce_style( $type, $data ) {

		if ( class_exists( 'BF_Shortcodes_Manager' ) ) {

			if ( empty( BF_Shortcodes_Manager::$tinymce_extra_enqueues['styles'] ) ) {
				BF_Shortcodes_Manager::$tinymce_extra_enqueues['styles'] = array();
			}

			BF_Shortcodes_Manager::$tinymce_extra_enqueues['styles'][] = _bf_normalize_enqueue_tinymce( $type, $data );

			return true;
		}

		return false;
	}
}
if ( ! function_exists( 'bf_enqueue_tinymce_script' ) ) {
	/**
	 * Register style for tinymce view add-on
	 *
	 * @param string $type inline|custom|extra|registered
	 * @param string $data
	 *                     bf_add_style_file() handle id if $type == extra
	 *                     unique handle id              if $type == registered
	 *                     custom inline css code        if $type == inline
	 *                     stylesheet url                if $type == custom
	 *
	 *
	 * @since 3.0.0
	 * @return true on success or false on failure
	 */
	function bf_enqueue_tinymce_script( $type, $data ) {

		if ( class_exists( 'BF_Shortcodes_Manager' ) ) {
			if ( empty( BF_Shortcodes_Manager::$tinymce_extra_enqueues['scripts'] ) ) {
				BF_Shortcodes_Manager::$tinymce_extra_enqueues['scripts'] = array();
			}

			BF_Shortcodes_Manager::$tinymce_extra_enqueues['scripts'][] = _bf_normalize_enqueue_tinymce( $type, $data );

			return true;
		}

		return false;
	}
}
<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


// Callback For Video Format auto-embed
add_filter( 'better-framework/content/video-embed', 'bf_auto_embed_content' );
add_filter( 'better-framework/content/auto-embed', 'bf_auto_embed_content' );


if ( ! function_exists( 'bf_auto_embed_content' ) ) {
	/**
	 * Filter Callback: Auto-embed using a link
	 *
	 * @param string $content
	 *
	 * @return string
	 */
	function bf_auto_embed_content( $content ) {

		//
		// Custom External Videos
		//
		preg_match( '#^(http|https)://.+\.(mp4|m4v|webm|ogv|wmv|flv)$#i', $content, $matches );
		if ( ! empty( $matches[0] ) ) {
			return array(
				'type'    => 'external-video',
				'content' => do_shortcode( '[video src="' . $matches[0] . '"]' ),
			);
		}


		//
		// Custom External Audio
		//
		preg_match( '#^(http|https)://.+\.(mp3|m4a|ogg|wav|wma)$#i', $content, $matches );
		if ( ! empty( $matches[0] ) ) {
			return array(
				'type'    => 'external-audio',
				'content' => do_shortcode( '[audio src="' . $matches[0] . '"]' ),
			);
		}


		//
		// Default embeds and other registered
		//

		global $wp_embed;

		if ( ! is_object( $wp_embed ) ) {
			return array(
				'type'    => 'unknown',
				'content' => $content,
			);
		}

		$embed = $wp_embed->autoembed( $content );

		if ( $embed !== $content ) {
			return array(
				'type'    => 'embed',
				'content' => $embed,
			);
		}

		// No embed detected!
		return array(
			'type'    => 'unknown',
			'content' => $content,
		);
	}
}
<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


if ( ! function_exists( 'bf_get_menu_location_name_from_id' ) ) {
	/**
	 * Used For retrieving current sidebar
	 *
	 * #since 2.0
	 *
	 * @param $location
	 *
	 * @return
	 */
	function bf_get_menu_location_name_from_id( $location ) {

		$locations = get_registered_nav_menus();

		if ( isset( $locations[ $location ] ) ) {
			return $locations[ $location ];
		}

	}
}


if ( ! function_exists( 'bf_get_menus_option' ) ) {
	/**
	 * Handy function to get select option for using this as deferred callback
	 *
	 * @since 2.5.5
	 *
	 * @param bool   $default
	 * @param string $default_label
	 * @param string $menus_label
	 *
	 * @return array
	 */
	function bf_get_menus_option( $default = false, $default_label = '', $menus_label = '', $args = array() ) {

		$menus = array();

		if ( $default ) {
			$menus['default'] = ! empty( $default_label ) ? $default_label : __( 'Default Navigation', 'better-studio' );
		}

		$menus[] = array(
			'label'   => ! empty( $menus_label ) ? $menus_label : __( 'Menus', 'better-studio' ),
			'options' => bf_get_menus(),
		);

		if ( isset( $args['append'] ) ) {
			$menus = array_merge( $menus, $args['append'] );
		}

		return $menus;

	} // bf_get_menus_option
} // if


if ( ! function_exists( 'bf_get_menus_animations_option' ) ) {
	/**
	 * Handy function to get select option of all menu animations for using as deferred callback
	 *
	 * @since 2.5.5
	 *
	 * @param array $args used for future changes
	 *
	 * @return array
	 */
	function bf_get_menus_animations_option( $args = array() ) {

		$animations = array(

			'default' => __( '-- Default --', 'better-studio' ),
			'none'    => __( 'No Animation', 'better-studio' ),
			'random'  => __( 'Random Animation', 'better-studio' ),

			array(
				'label'   => __( 'Fading', 'better-studio' ),
				'options' => array(
					'fade'       => __( 'Simple Fade', 'better-studio' ),
					'slide-fade' => __( 'Fading Slide', 'better-studio' ),
				),
			),

			array(
				'label'   => __( 'Attention Seekers', 'better-studio' ),
				'options' => array(
					'bounce' => __( 'Bounce', 'better-studio' ),
					'tada'   => __( 'Tada', 'better-studio' ),
					'shake'  => __( 'Shake', 'better-studio' ),
					'swing'  => __( 'Swing', 'better-studio' ),
					'wobble' => __( 'Wobble', 'better-studio' ),
					'buzz'   => __( 'Buzz', 'better-studio' ),
				),
			),

			array(
				'label'   => __( 'Sliding', 'better-studio' ),
				'options' => array(
					'slide-top-in'    => __( 'Slide &#x2193; In', 'better-studio' ),
					'slide-bottom-in' => __( 'Slide &#x2191; In', 'better-studio' ),
					'slide-left-in'   => __( 'Slide &#x2192; In', 'better-studio' ),
					'slide-right-in'  => __( 'Slide &#x2190; In', 'better-studio' ),
				),
			),

			array(
				'label'   => __( 'Flippers', 'better-studio' ),
				'options' => array(
					'filip-in-x' => __( 'Filip In X - &#x2195;', 'better-studio' ),
					'filip-in-y' => __( 'Filip In Y - &#x2194;', 'better-studio' ),
				),
			),

		);

		return $animations;

	} // bf_get_menus_animations_option
} // if


<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


if ( ! function_exists( 'bf_get_current_sidebar' ) ) {
	/**
	 * Used For retrieving current sidebar
	 *
	 * @since 2.5.5
	 *
	 * @return string
	 */
	function bf_get_current_sidebar() {

		return Better_Framework::widget_manager()->get_current_sidebar();
	}
}


if ( ! function_exists( 'bf_get_sidebar_name_from_id' ) ) {
	/**
	 * Used For retrieving current sidebar
	 *
	 * @since 2.0
	 *
	 * @param $sidebar_id
	 *
	 * @return
	 */
	function bf_get_sidebar_name_from_id( $sidebar_id ) {

		global $wp_registered_sidebars;

		if ( isset( $wp_registered_sidebars[ $sidebar_id ] ) ) {
			return $wp_registered_sidebars[ $sidebar_id ]['name'];
		}

	}
}
<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


if ( ! function_exists( 'bf_shortcode_show_title' ) ) {
	/**
	 * Used to show shortcodes heading in standard way!
	 * You can redefine this function or use 'better-framework/shortcodes/title' filter
	 * for changing values.
	 *
	 * @param array $atts
	 *
	 * @since 2.5.5
	 *
	 * @return string
	 */
	function bf_shortcode_show_title( $atts = array() ) {

		if ( isset( $atts['show_title'] ) && $atts['show_title'] == false ) {
			return;
		}

		if ( isset( $atts['hide_title'] ) && $atts['hide_title'] == true ) {
			return;
		}

		if ( empty( $atts['title'] ) ) {
			return;
		}

		if ( bf_get_current_sidebar() && bf_get_current_sidebar() !== 'bs-vc-sidebar-column' ) {
			return;
		}

		$result = apply_filters( 'better-framework/shortcodes/title', $atts );

		if ( is_string( $result ) ) {
			echo $result; // escaped before
		}

	}
}


if ( ! function_exists( 'bf_shortcode_custom_css_prop' ) ) {
	/**
	 * @param        $css
	 * @param        $prop_name
	 * @param string $default
	 *
	 * @return string
	 *
	 * @since 2.5.2
	 */
	function bf_shortcode_custom_css_prop( $css, $prop_name, $default = '' ) {

		preg_match( '/' . $prop_name . ':([^!]*)/', $css, $css );

		if ( ! empty( $css[1] ) ) {
			return trim( $css[1] );
		}

		return $default;
	}
}


if ( ! function_exists( 'bf_shortcode_custom_css_class' ) ) {
	/**
	 * Custom function used to get custom css class name form VC/Shortcode css atribute
	 *
	 * @param        $param_value
	 * @param string $prefix
	 * @param string $css_key
	 *
	 * @return string
	 *
	 * @since 2.5.2
	 */
	function bf_shortcode_custom_css_class( $param_value, $prefix = '', $css_key = 'css' ) {

		$css_class = '';

		// prepare field
		if ( is_array( $param_value ) && ! empty( $param_value[ $css_key ] ) ) {
			$param_value = $param_value[ $css_key ];
		} else {
			return $css_class;
		}

		if ( is_string( $param_value ) ) {
			$css_class = preg_match( '/\s*\.([^\{]+)\s*\{\s*([^\}]+)\s*\}\s*/', $param_value ) ? $prefix . preg_replace( '/\s*\.([^\{]+)\s*\{\s*([^\}]+)\s*\}\s*/', '$1', $param_value ) : '';
		}

		return $css_class;
	}
}


if ( ! function_exists( 'bf_vc_edit_form_classes' ) ) {
	/**
	 * Filter: vc_edit_form_class
	 * Description: add some class to visual composer edit form. used in admin-scripts.js setup_interactive_fields_for_vc() method
	 *
	 * @see setup_interactive_fields_for_vc method on `Better_Framework` JS Object
	 *
	 * @param array $classes
	 * @param array $atts
	 * @param array $params
	 *
	 * @return mixed
	 */
	function bf_vc_edit_form_classes( $classes, $atts, $params ) {

		$added_fields      = array();
		$interactive_added = false;
		foreach ( $params as $param ) {
			if ( ! empty( $param['show_on'] ) ) {
				if ( ! $interactive_added ) {
					array_push( $classes, 'bf-interactive-fields', 'bf-has-filters' );
					$interactive_added = true;
				}

				foreach ( (array) $param['show_on'] as $conditions ) {
					foreach ( (array) $conditions as $condition ) {
						$field_name = explode( '=', $condition, 2 );
						$field_name = $field_name[0];
						if ( ! in_array( $field_name, $added_fields ) ) {
							array_push( $classes, 'bf-filter-field-' . $field_name );
							$added_fields[] = $field_name;
						}
					}
				}
			}
		}

		return array_unique( $classes );
	}

	add_filter( 'vc_edit_form_class', 'bf_vc_edit_form_classes', 8, 3 );
}


if ( ! function_exists( 'bf_vc_layout_state' ) ) {
	/**
	 * Returns VC Columns state
	 *
	 * @return array
	 */
	function bf_vc_layout_state() {

		global $_bf_override_vc_layout_state, $_bf_vc_column_atts, $_bf_vc_column_inner_atts, $_bf_vc_row_columns;

		if ( ! empty( $_bf_override_vc_layout_state ) ) {
			return $_bf_override_vc_layout_state; # Allow to override state value
		}

		$_bf_vc_column_atts = array_filter( (array) $_bf_vc_column_atts );
		$_bf_vc_column_atts = bf_merge_args( $_bf_vc_column_atts, array(
			'width'      => '1',
			'list'       => $_bf_vc_row_columns,
			'list_count' => $_bf_vc_row_columns ? bf_count( $_bf_vc_row_columns ) : 0,
		) );

		$_bf_vc_column_inner_atts = array_filter( (array) $_bf_vc_column_inner_atts );
		$_bf_vc_column_inner_atts = bf_merge_args( $_bf_vc_column_inner_atts, array(
			'width' => '1'
		) );

		return array(
			'column' => $_bf_vc_column_atts,
			'row'    => $_bf_vc_column_inner_atts,
		);
	}
}


add_filter( 'vc_shortcode_set_template_vc_column', 'bf_vc_column_filter' );

if ( ! function_exists( 'bf_vc_column_filter' ) ) {
	/**
	 * Callback: Handy filter to calculate columns state
	 * Filter: vc_shortcode_set_template_vc_column
	 *
	 * @param $file
	 *
	 * @return string
	 */
	function bf_vc_column_filter( $file ) {

		global $_vc_column_template_file;

		$_vc_column_template_file = $file;

		return BF_PATH . 'page-builder/compatibility/vc/vc_column.php';
	}
}


add_filter( 'vc_shortcode_set_template_vc_column_inner', 'bf_vc_column_inner_filter' );

if ( ! function_exists( 'bf_vc_column_inner_filter' ) ) {
	/**
	 * Callback: Handy filter to calculate columns state
	 * Filter: vc_shortcode_set_template_vc_column_inner
	 *
	 * @param $file
	 *
	 * @return string
	 */
	function bf_vc_column_inner_filter( $file ) {

		global $_vc_column_inner_template_file;

		$_vc_column_inner_template_file = $file;

		return BF_PATH . 'page-builder/compatibility/vc/vc_column_inner.php';
	}
}


add_filter( 'better-framework/shortcodes/design-fields', 'bf_shortcpdes_design_fields', 10, 2 );

if ( ! function_exists( 'bf_shortcpdes_design_fields' ) ) {
	/**
	 * Generates general design options for shortcodes
	 *
	 * @param array  $fields
	 * @param string $shortcode_id
	 *
	 * @return array
	 */
	function bf_shortcpdes_design_fields( $fields = array(), $shortcode_id = '' ) {

		$fields['design_tab']       = array(
			'type' => 'tab',
			'name' => __( 'Design Options', 'better-studio' ),
			'id'   => 'design_tab',
		);
		$fields['bs-show-desktop']  = array(
			"type"           => 'switchery',
			"name"           => __( 'Show on Desktop', 'better-studio' ),
			"id"             => 'bs-show-desktop',
			'section_class'  => 'style-floated-left bordered bf-css-edit-switch',
			//
			"vc_admin_label" => false,
		);
		$fields['bs-show-tablet']   = array(
			"type"           => 'switchery',
			"name"           => __( 'Show on Tablet Portrait', 'better-studio' ),
			"id"             => 'bs-show-tablet',
			'section_class'  => 'style-floated-left bordered bf-css-edit-switch',
			'group'          => __( 'Design options', 'better-studio' ),
			//
			"vc_admin_label" => false,
		);
		$fields['bs-show-phone']    = array(
			"type"           => 'switchery',
			"name"           => __( 'Show on Phone', 'better-studio' ),
			"id"             => 'bs-show-phone',
			'section_class'  => 'style-floated-left bordered bf-css-edit-switch',
			//
			"vc_admin_label" => false,
		);
		$fields['css']              = array(
			'type'           => 'css_editor',
			'name'           => __( 'CSS box', 'better-studio' ),
			'id'             => 'css',
			"vc_admin_label" => false,
		);
		$fields['custom-css-class'] = array(
			'type'           => 'text',
			'name'           => __( 'Custom CSS Class', 'better-studio' ),
			'id'             => 'custom-css-class',
			'section_class'  => 'bf-section-two-column',
			//
			'vc_admin_label' => false,
		);
		$fields['custom-id']        = array(
			'type'           => 'text',
			'name'           => __( 'Custom ID', 'better-studio' ),
			'id'             => 'custom-id',
			'value'          => '',
			'section_class'  => 'bf-section-two-column',
			//
			'vc_admin_label' => false,
		);

		return $fields;
	}
}
<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


if ( ! function_exists( 'bf_get_current_lang_raw' ) ) {
	/**
	 * Used for finding current language in multilingual
	 *
	 * @sine 2.0
	 *
	 * @return string
	 */
	function bf_get_current_lang_raw() {

		static $lang;

		if ( $lang ) {
			return $lang;
		}

		// WPML : https://wpml.org/
		if ( defined( 'ICL_SITEPRESS_VERSION' ) ) {

			$lang = icl_get_current_language();

			// Fix conditions WPML is active but not setup
			if ( is_null( $lang ) ) {
				$lang = 'none';
			}

		} // xili-language : https://wordpress.org/plugins/xili-language/
		elseif ( function_exists( 'xili_curlang' ) ) {

			// Tip for separating admin language when user selects specific locale
			if ( is_admin() ) {

				// get all xili active languages
				$languages = bf_get_all_languages();

				// get current locale
				$locale = get_locale();

				foreach ( (array) $languages as $_lang ) {

					if ( $_lang['locale'] == $locale ) {
						$lang = $_lang['id'];
					}

				}

			} else {
				$lang = xili_curlang();
			}

			if ( empty( $lang ) ) {
				$lang = 'all';
			}
		} // qTranslate : http://www.qianqin.de/qtranslate/
		elseif ( function_exists( 'qtrans_getLanguage' ) ) {
			$lang = qtrans_getLanguage();
		} // WPGlobe : http://www.wpglobus.com/
		elseif ( class_exists( 'WPGlobus' ) ) {

			// Tip for separating admin language when user selects specific locale
			if ( is_admin() ) {

				// get all xili active languages
				$languages = bf_get_all_languages();

				// get current locale
				$locale = get_locale();

				foreach ( (array) $languages as $_lang ) {

					if ( $_lang['locale'] == $locale ) {
						$lang = $_lang['id'];
					}

				}

			} else {
				$lang = WPGlobus::Config()->language;
			}

		} // Polylang : https://wordpress.org/plugins/polylang/
		elseif ( function_exists( 'pll_languages_list' ) ) {
			$lang = pll_current_language();

			$langs_list = pll_languages_list();

			// Fix conditions Polylang is active but not setup
			if ( ! $langs_list ) {
				$lang = 'none';
			} elseif ( $lang == false ) {
				$lang = 'all';
			}

		} else {
			$lang = 'none';
		}

		return $lang;
	}
}


if ( ! function_exists( 'bf_get_current_lang' ) ) {
	/**
	 * Used for finding current language in multilingual
	 *
	 * @sine 2.0
	 *
	 * @return string
	 */
	function bf_get_current_lang() {

		$lang = bf_get_current_lang_raw();

		// Default language is en!
		if ( $lang == 'en' ) {
			$lang = 'none';
		}

		return $lang;
	}
}


if ( ! function_exists( 'bf_get_all_languages' ) ) {
	/**
	 * Returns all active multilingual languages
	 *
	 * @since 2.0
	 *
	 * @return array
	 */
	function bf_get_all_languages() {

		$languages = array();

		// WPML : https://wpml.org/
		if ( defined( 'ICL_SITEPRESS_VERSION' ) ) {

			global $sitepress;

			// get filtered active language informations
			$temp_lang = icl_get_languages( 'skip_missing=1' );

			foreach ( $temp_lang as $lang ) {

				// Get language raw data from DB
				$_lang = $sitepress->get_language_details( $lang['language_code'] );

				$languages[] = array(
					'id'     => $lang['language_code'],
					'name'   => $_lang['english_name'], // english display name
					'flag'   => $lang['country_flag_url'],
					'locale' => $lang['default_locale'],
				);

			}

		} // xili-language : https://wordpress.org/plugins/xili-language/
		elseif ( function_exists( 'xili_curlang' ) ) {

			global $xili_language;

			$languages = array();

			foreach ( (array) $xili_language->get_listlanguages() as $lang ) {

				$desc = unserialize( $lang->description );

				$languages[] = array(
					'id'     => $lang->slug,
					'name'   => $lang->name,
					'flag'   => '',
					'locale' => $desc['locale'],
				);

			}

		} // qTranslate : http://www.qianqin.de/qtranslate/
		elseif ( function_exists( 'qtrans_getLanguage' ) ) {

			global $q_config;

			$languages = array();

			foreach ( (array) $q_config['enabled_languages'] as $lang ) {

				$languages[] = array(
					'id'     => $lang,
					'name'   => $q_config['language_name'][ $lang ],
					'flag'   => trailingslashit( WP_CONTENT_URL ) . $q_config['flag_location'] . $q_config['flag'][ $lang ],
					'locale' => $q_config['locale'][ $lang ],
				);

			}

		} // WPGlobe : http://www.wpglobus.com/
		elseif ( class_exists( 'WPGlobus' ) ) {

			$_languages = WPGlobus::Config()->enabled_languages;

			foreach ( (array) $_languages as $lang ) {

				$languages[] = array(
					'id'     => $lang,
					'name'   => WPGlobus::Config()->en_language_name[ $lang ], // english display name
					'flag'   => WPGlobus::Config()->flags_url . WPGlobus::Config()->flag[ $lang ],
					'locale' => WPGlobus::Config()->locale[ $lang ],
				);
			}

		} // Polylang : https://wordpress.org/plugins/polylang/
		elseif ( function_exists( 'pll_languages_list' ) ) {

			$_languages = pll_languages_list( array( 'fields' => 'locale' ) );

			foreach ( (array) $_languages as $_lang ) {

				//get_language
				global $polylang;

				$_raw_lang = $polylang->model->get_language( $_lang );

				$languages[] = array(
					'id'     => $_raw_lang->slug,
					'name'   => $_raw_lang->name, // english display name
					'flag'   => $_raw_lang->flag_url,
					'locale' => $_raw_lang->locale,
				);
			}

		}

		return $languages;

	}
}


if ( ! function_exists( 'bf_get_language_data' ) ) {
	/**
	 * Returns multilingual language information
	 *
	 * @since 2.0
	 *
	 * @param null $lang
	 *
	 * @return array
	 */
	function bf_get_language_data( $lang = null ) {

		$output = array(
			'id'     => '',
			'name'   => '',
			'flag'   => '',
			'locale' => '',
		);

		if ( is_null( $lang ) ) {
			return $output;
		}

		$languages = bf_get_all_languages();

		foreach ( $languages as $_language ) {

			if ( $_language['id'] == $lang ) {

				$output = $_language;

			}

		}

		return $output;

	}
}


if ( ! function_exists( 'bf_get_language_name' ) ) {
	/**
	 * Returns multilingual language name from ID
	 *
	 * @since 2.0
	 *
	 * @param null $lang
	 *
	 * @return array
	 */
	function bf_get_language_name( $lang = null ) {

		$lang = bf_get_language_data( $lang );

		if ( isset( $lang['name'] ) ) {
			return $lang['name'];
		}

		return '';
	}
}


if ( ! function_exists( 'bf_get_current_language_option_code' ) ) {
	/**
	 * Returns multilingual language option id that starts with _
	 * ex: _fa
	 * for english and all language code returns empty
	 *
	 * @since 2.3
	 *
	 * @return array
	 */
	function bf_get_current_language_option_code( $lang = null ) {

		static $_lang;

		// for special codes that passes the lang
		if ( ! is_null( $lang ) ) {

			$lang = bf_get_current_lang();

			if ( $lang == 'none' || $lang == 'all' ) {
				$lang = '';
			} else {
				$lang = '_' . $lang;
			}

			return $lang;
		}

		// from cache
		if ( $_lang ) {
			return $_lang;
		}

		$_lang = bf_get_current_lang();

		if ( $_lang == 'none' || $_lang == 'all' ) {
			$_lang = '';
		} else {
			$_lang = '_' . $_lang;
		}

		return $_lang;
	}
}<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Handy functions for making development quicker in getting addresses.
 *
 * @package    BetterFramework
 * @author     BetterStudio <info@betterstudio.com>
 * @copyright  Copyright (c) 2015, BetterStudio
 */


if ( ! function_exists( 'bf_get_dir' ) ) {
	/**
	 * Get BetterFramework directory path
	 *
	 * @param string $append
	 *
	 * @return string
	 */
	function bf_get_dir( $append = '' ) {

		return BF_PATH . $append;
	}
}


if ( ! function_exists( 'bf_require' ) ) {
	/**
	 * Used to require file inside BetterFramework
	 *
	 * @param string $append
	 *
	 * @return string
	 */
	function bf_require( $append = '' ) {

		require BF_PATH . $append;
	}
}


if ( ! function_exists( 'bf_require_once' ) ) {
	/**
	 * Used to require_once file inside BetterFramework
	 *
	 * @param string $append
	 *
	 * @return string
	 */
	function bf_require_once( $append = '' ) {

		require_once BF_PATH . $append;
	}
}


if ( ! function_exists( 'bf_get_uri' ) ) {
	/**
	 * Get BetterFramework directory URI (URL)
	 *
	 * @param string $append
	 *
	 * @return string
	 */
	function bf_get_uri( $append = '' ) {

		return BF_URI . $append;
	}
}


if ( ! function_exists( 'bf_get_theme_dir' ) ) {
	/**
	 * Parent theme directory.
	 *
	 * @param string $append
	 *
	 * @return string
	 */
	function bf_get_theme_dir( $append = '' ) {

		static $directory;

		if ( ! $directory ) {
			$directory = get_template_directory() . '/';
		}

		return $directory . $append;
	}
}


if ( ! function_exists( 'bf_get_theme_uri' ) ) {
	/**
	 * Parent theme directory URI.
	 *
	 * @param string $append
	 *
	 * @return string
	 */
	function bf_get_theme_uri( $append = '' ) {

		static $uri;

		if ( ! $uri ) {
			$uri = get_template_directory_uri() . '/';
		}

		return $uri . $append;
	}
}


if ( ! function_exists( 'bf_get_child_theme_dir' ) ) {
	/**
	 * Child theme directory.
	 *
	 * @param string $append
	 *
	 * @return string
	 */
	function bf_get_child_theme_dir( $append = '' ) {

		static $directory;

		if ( ! $directory ) {
			$directory = get_stylesheet_directory() . '/';
		}

		return $directory . $append;
	}
}


if ( ! function_exists( 'bf_get_child_theme_uri' ) ) {
	/**
	 * Child theme directory URI.
	 *
	 * @param string $append
	 *
	 * @return string
	 */
	function bf_get_child_theme_uri( $append = '' ) {

		static $uri;

		if ( ! $uri ) {
			$uri = get_stylesheet_directory_uri() . '/';
		}

		return $uri . $append;
	}
}


if ( ! function_exists( 'bf_basename' ) ) {
	/**
	 * Fixes basename functionality when file name start with an accent
	 * https://stackoverflow.com/questions/32115609/basename-fail-when-file-name-start-by-an-accent
	 *
	 * @param $url
	 *
	 * @return mixed
	 */
	function bf_basename( $url ) {

		$file_name = explode( '/', $url );

		return end( $file_name );
	}
}<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


if ( ! function_exists( 'bf_get_pages' ) ) {
	/**
	 * Get Pages
	 *
	 * @param array $extra Extra Options.
	 *
	 * @since 2.3
	 *
	 * @return array
	 */
	function bf_get_pages( $extra = array() ) {

		/*
			Extra Usage:

			array(
				'sort_order'        =>  'ASC',
				'sort_column'       =>  'post_title',
				'hierarchical'      =>  1,
				'exclude'           =>  '',
				'include'           =>  '',
				'meta_key'          =>  '',
				'meta_value'        =>  '',
				'authors'           =>  '',
				'child_of'          =>  0,
				'parent'            =>  -1,
				'exclude_tree'      =>  '',
				'number'            =>  '',
				'offset'            =>  0,
				'post_type'         =>  'page',
				'post_status'       =>  'publish'
			)

		*/

		if ( ! empty( $extra['advanced-label'] ) ) {
			$advanced_label = true;
			unset( $extra['advanced-label'] );

			if ( 'page' == get_option( 'show_on_front' ) && get_option( 'page_on_front' ) ) {
				$front_page = get_option( 'page_on_front' );
			} else {
				$front_page = - 1;
			}
		} else {
			$advanced_label = false;
			$front_page     = - 1;
		}

		$output = array();

		if ( empty( $extra['post_type'] ) ) {
			$extra['post_type'] = 'page';
		}

		$query = get_posts( $extra );

		foreach ( $query as $page ) {

			/** @var WP_Post $page */

			if ( $advanced_label ) {

				$append = '';

				if ( $page->post_status === 'private' ) {
					$append .= '(' . __( 'Private', 'better-studio' ) . ')';
				} elseif ( $page->post_status === 'draft' ) {
					$append .= '(' . __( 'Draft', 'better-studio' ) . ')';
				}

				if ( $page->ID == $front_page ) {
					$append .= '(' . __( 'Front Page', 'better-studio' ) . ')';
				}

				if ( ! empty( $append ) ) {
					$output[ $page->ID ] = $page->post_title . ' - ' . $append;
				} else {
					$output[ $page->ID ] = $page->post_title;
				}

			} else {
				$output[ $page->ID ] = $page->post_title;
			}
		}

		return $output;

	} // bf_get_pages
} // if


if ( ! function_exists( 'bf_get_posts' ) ) {

	/**
	 * Get Posts
	 *
	 * @param array $extra Extra Options.
	 *
	 * @since 2.3
	 *
	 * @return array
	 */
	function bf_get_posts( $extra = array() ) {

		/*
			Extra Usage:

			array(
				'posts_per_page'  => 5,
				'offset'          => 0,
				'category'        => '',
				'orderby'         => 'post_date',
				'order'           => 'DESC',
				'include'         => '',
				'exclude'         => '',
				'meta_key'        => '',
				'meta_value'      => '',
				'post_type'       => 'post',
				'post_mime_type'  => '',
				'post_parent'     => '',
				'post_status'     => 'publish',
				'suppress_filters' => true
			)
		*/

		$output = array();

		$query = get_posts( $extra );

		foreach ( $query as $post ) {
			$output[ $post->ID ] = $post->post_title;
		}

		return $output;

	} // bf_get_posts

} // if


if ( ! function_exists( 'bf_get_random_post_link' ) ) {
	/**
	 * Get an link for a random post
	 *
	 * @param bool $echo
	 *
	 * @return bool|string
	 */
	function bf_get_random_post_link( $echo = true ) {

		$query = new WP_Query(
			array(
				'orderby'        => 'rand',
				'posts_per_page' => '1'
			)
		);

		if ( $echo ) {
			echo get_permalink( $query->posts[0] ); // escaped before inside WP Core
		} else {
			return get_permalink( $query->posts[0] );
		}

	} // bf_get_random_post_link
} // if


if ( ! function_exists( 'bf_get_categories' ) ) {
	/**
	 * Get categories
	 *
	 * @param array $extra Extra Options.
	 *
	 * @since 1.0
	 * @return array
	 */
	function bf_get_categories( $extra = array() ) {

		/*
			Extra Usage:

			array(
				'type'          => 'post',
				'child_of'      => 0,
				'parent'        => '',
				'orderby'       => 'name',
				'order'         => 'ASC',
				'hide_empty'    => 1,
				'hierarchical'  => 1,
				'exclude'       => '',
				'include'       => '',
				'number'        => '',
				'taxonomy'      => 'category',
				'pad_counts'    => false
			)
		*/

		$output = array();

		$query = get_categories( $extra );

		foreach ( $query as $cat ) {
			$output[ $cat->cat_ID ] = $cat->name;
		}

		return $output;

	} // bf_get_categories
} // if


if ( ! function_exists( 'bf_get_categories_by_slug' ) ) {
	/**
	 * Get categories
	 *
	 * @param array $extra Extra Options.
	 *
	 * @since 1.0
	 * @return array
	 */
	function bf_get_categories_by_slug( $extra = array() ) {

		/*
			Extra Usage:

			array(
				'type'          => 'post',
				'child_of'      => 0,
				'parent'        => '',
				'orderby'       => 'name',
				'order'         => 'ASC',
				'hide_empty'    => 1,
				'hierarchical'  => 1,
				'exclude'       => '',
				'include'       => '',
				'number'        => '',
				'taxonomy'      => 'category',
				'pad_counts'    => false
			)
		*/

		$output = array();

		$query = get_categories( $extra );

		foreach ( $query as $cat ) {
			$output[ $cat->slug ] = $cat->name;
		}

		return $output;

	} // bf_get_categories_by_slug
} // if


if ( ! function_exists( 'bf_get_tags' ) ) {
	/**
	 * Get Tags
	 *
	 * @param array $extra Extra Options.
	 *
	 * @since 1.0
	 * @return mixed
	 */
	function bf_get_tags( $extra = array() ) {

		$output = array();
		$query  = get_tags( $extra );

		foreach ( $query as $tag ) {
			$output[ $tag->term_id ] = $tag->name;
		}

		return $output;

	} // bf_get_tags
} // if


if ( ! function_exists( 'bf_get_users' ) ) {
	/**
	 * Get users
	 *
	 * @param array      $extra           Extra Options.
	 * @param array|bool $advanced_output Advanced Query is the results with query other resutls
	 *
	 * @since 1.0
	 * @return array
	 */
	function bf_get_users( $extra = array(), $advanced_output = false ) {

		$output = array();

		$extra = bf_merge_args(
			$extra,
			array(
				'orderby' => 'post_count',
				'order'   => 'DESC'
			)
		);

		$advanced_label = isset( $extra['advanced-label'] ) && $extra['advanced-label'];

		if ( $advanced_label ) {

			$current_user = wp_get_current_user();
		}

		$query = new WP_User_Query( $extra );

		foreach ( $query->results as $user ) {

			if ( $advanced_label ) {

				$label = $user->data->display_name . " ({$user->data->user_login})";

				if ( $user->data->ID === $current_user->get( 'ID' ) ) {
					$label = __( 'Me: ', 'better-studio' ) . $label;
				}

				$output[ $user->data->ID ] = $label;
			} else {
				$output[ $user->data->ID ] = $user->data->display_name;
			}
		}

		if ( $advanced_output ) {
			// Unset the result for make free the memory
			unset( $query->results );

			return array( $output, $query );
		}

		return $output;

	} // bf_get_users
} // if


if ( ! function_exists( 'bf_get_post_types' ) ) {
	/**
	 * Get Post Types
	 *
	 * @param array $extra Extra Options.
	 *
	 * @since 1.0
	 * @return array
	 */
	function bf_get_post_types( $extra = array() ) {

		$output = array();

		if ( ! isset( $extra['exclude'] ) || ! is_array( $extra['exclude'] ) ) {
			$extra['exclude'] = array();
		}

		// Add revisions, nave menu and attachment post types to excludes
		$extra['exclude'] = array_merge( $extra['exclude'], array( 'revision', 'nav_menu_item', 'attachment' ) );

		$query = get_post_types();

		foreach ( $query as $key => $val ) {

			if ( in_array( $key, $extra['exclude'] ) ) {
				continue;
			}

			$output[ $key ] = ucfirst( $val );
		}

		return $output;

	} // bf_get_post_types
} // if


if ( ! function_exists( 'bf_get_page_templates' ) ) {
	/**
	 * Get Page Templates
	 *
	 * @param array $extra Extra Options.
	 *
	 * @since 1.0
	 * @return mixed
	 */
	function bf_get_page_templates( $extra = array() ) {

		$output = array();

		if ( ! isset( $extra['exclude'] ) || ! is_array( $extra['exclude'] ) ) {
			$extra['exclude'] = array();
		}

		$query = wp_get_theme()->get_page_templates();

		foreach ( $query as $key => $val ) {

			if ( in_array( $key, $extra['exclude'] ) ) {
				continue;
			}

			$output[ $key ] = $val;
		}

		return $output;

	} // bf_get_page_templates
} // if


if ( ! function_exists( 'bf_get_taxonomies' ) ) {
	/**
	 * Get Taxonomies
	 *
	 * @param array $extra Extra Options.
	 *
	 * @since 1.0
	 * @return array
	 */
	function bf_get_taxonomies( $extra = array() ) {

		$output = array();

		$query = get_taxonomies();

		if ( ! isset( $extra['exclude'] ) || ! is_array( $extra['exclude'] ) ) {
			$extra['exclude'] = array();
		}

		foreach ( $query as $key => $val ) {

			if ( in_array( $key, $extra['exclude'] ) ) {
				continue;
			}

			$output[ $key ] = ucfirst( str_replace( '_', ' ', $val ) );
		}

		return $output;

	} // bf_get_taxonomies
} // if


if ( ! function_exists( 'bf_get_terms' ) ) {
	/**
	 * Get All Terms of Specific Taxonomy
	 *
	 * @param array|string $tax   Taxonomy Slug
	 * @param array        $extra Extra Options.
	 *
	 * @since 1.0
	 * @return array
	 */
	function bf_get_terms( $tax = 'category', $extra = array() ) {

		if ( ! isset( $extra['exclude'] ) || ! is_array( $extra['exclude'] ) ) {
			$extra['exclude'] = array();
		}

		$query  = get_terms( $tax, $extra );
		$output = array();

		foreach ( $query as $taxonomy ) {

			if ( in_array( $taxonomy->slug, $extra['exclude'] ) ) {
				continue;
			}

			$output[ $taxonomy->slug ] = $taxonomy->name;
		}

		return $output;

	} // bf_get_terms
}// if


if ( ! function_exists( 'bf_get_roles' ) ) {
	/**
	 * Get Roles
	 *
	 * @param array $extra Extra Options.
	 *
	 * @since 1.0
	 * @return array
	 */
	function bf_get_roles( $extra = array() ) {

		global $wp_roles;

		$output = array();

		if ( ! isset( $extra['exclude'] ) || ! is_array( $extra['exclude'] ) ) {
			$extra['exclude'] = array();
		}

		foreach ( $wp_roles->roles as $key => $val ) {

			if ( in_array( $key, $extra['exclude'] ) ) {
				continue;
			}

			$output[ $key ] = $val['name'];
		}

		return $output;

	} // bf_get_roles
} // if


if ( ! function_exists( 'bf_get_menus' ) ) {
	/**
	 * Get Menus
	 *
	 * @param bool $hide_empty
	 *
	 * @since 1.0
	 * @return array
	 */
	function bf_get_menus( $hide_empty = false ) {

		$output = array();

		$menus = get_terms( 'nav_menu', array( 'hide_empty' => $hide_empty ) );

		foreach ( $menus as $menu ) {
			$output[ $menu->term_id ] = $menu->name;
		}

		return $output;

	} // bf_get_menus
} // if

if ( ! function_exists( 'bf_is_a_category' ) ) {
	/**
	 * Used to detect category from id
	 *
	 * todo: change the algorithm
	 *
	 * @param null $id
	 *
	 * @return bool|mixed
	 */
	function bf_is_a_category( $id = null ) {

		if ( is_null( $id ) ) {
			return false;
		}

		$cat = get_category( $id );

		if ( $cat && ! is_wp_error( $cat ) ) {
			return current( $cat );
		} else {
			return false;
		}

	}// bf_is_a_category
} // if


if ( ! function_exists( 'bf_is_a_tag' ) ) {
	/**
	 * Used to detect tag from id
	 *
	 * todo: change the algorithm
	 *
	 * @param null $id
	 *
	 * @return bool|mixed
	 */
	function bf_is_a_tag( $id = null ) {

		if ( is_null( $id ) ) {
			return false;
		}

		$tag = get_tag( $id );

		if ( $tag && ! is_wp_error( $tag ) ) {
			return current( $tag );
		} else {
			return false;
		}

	} // bf_is_a_tag
} // if


if ( ! function_exists( 'bf_get_rev_sliders' ) ) {
	/**
	 * Used to find list of all RevolutionSlider Sliders.zip
	 *
	 * @return array
	 */
	function bf_get_rev_sliders() {

		if ( ! class_exists( 'RevSlider' ) ) {
			return array();
		}

		try {

			$slider = new RevSlider();

			return $slider->getArrSlidersShort();

		} catch( Exception $e ) {
			return array();
		}

	} // bf_get_rev_sliders
} // if


if ( ! function_exists( 'bf_get_wp_query_vars' ) ) {
	/**
	 * Creats flatted and valid query_vars from an instance of WP_Query object
	 *
	 * @param WP_Query $wp_query
	 *
	 * @return array
	 */
	function bf_get_wp_query_vars( $wp_query ) {

		if ( ! is_a( $wp_query, 'WP_Query' ) ) {
			return array();
		}

		$args = $wp_query->query_vars;

		// remove empty vars
		foreach ( $args as $_a => $_v ) {
			if ( is_array( $_v ) ) {
				if ( count( $_v ) === 0 ) {
					unset( $args[ $_a ] );
				}
			} else {
				if ( empty( $_v ) || $_v === 0 ) {
					unset( $args[ $_a ] );
				}
			}
		}

		// Remove extra vars
		unset( $args['suppress_filters'] );
		unset( $args['cache_results'] );
		unset( $args['update_post_term_cache'] );
		unset( $args['update_post_meta_cache'] );
		unset( $args['comments_per_page'] );
		unset( $args['no_found_rows'] );
		unset( $args['search_orderby_title'] );

		// create tax query
		if ( ! empty( $args['tax_query']['queries'] ) ) {
			$args['tax_query'] = $args['tax_query']['queries'];
		}

		return $args;

	} // bf_get_wp_query_vars
} // if


if ( ! function_exists( 'bf_get_wp_query_total_pages' ) ) {
	/**
	 * Calculates query total pages with support of offset and custom posts per page
	 *
	 * @param WP_Query $wp_query
	 * @param int      $offset
	 * @param int      $posts_per_page
	 * @param bool     $use_query_offset
	 *
	 * @return float|int
	 */
	function bf_get_wp_query_total_pages( &$wp_query, $offset = 0, $posts_per_page = 0, $use_query_offset = true ) {

		$offset = intval( $offset );

		$posts_per_page = intval( $posts_per_page );
		if ( $posts_per_page <= 0 ) {
			$posts_per_page = $wp_query->get( 'posts_per_page' );

			if ( $posts_per_page <= 0 ) {
				$posts_per_page = $wp_query->get( 'showposts' );
			}
		}

		// use the query offset if it was set
		if ( $use_query_offset && $offset <= 0 ) {

			if ( ! $offset = $wp_query->get( 'original_offset' ) ) { # original_offset is our custom name
				$offset = $wp_query->get( 'offset' );
			}

			$offset = intval( $offset );
		}

		if ( $offset > 0 && empty( $wp_query->_bs_optimization['found-rows'] ) && $posts_per_page > 0 ) {
			$total = ceil( ( $wp_query->found_posts - $offset ) / $posts_per_page );
		} else {
			$total = $wp_query->max_num_pages;
		}

		return $total;
	}
}

if ( ! function_exists( 'bf_get_comment_query_total_pages' ) ) {
	/**
	 * Calculates query total pages with support of offset and custom posts per page
	 *
	 * @param WP_Comment_Query $cm_query
	 * @param int              $offset
	 * @param int              $posts_per_page
	 * @param bool             $use_query_offset
	 *
	 * @return float|int
	 */
	function bf_get_comment_query_total_pages( &$cm_query, $offset = 0, $posts_per_page = 0, $use_query_offset = true ) {

		$offset = intval( $offset );


		$posts_per_page = intval( $posts_per_page );
		if ( $posts_per_page <= 0 ) {
			$posts_per_page = $cm_query->query_vars['number'];
		}

		// use the query offset if it was set
		if ( $use_query_offset && $offset <= 0 ) {
			$offset = $cm_query->query_vars['offset'];
		}


		if ( $offset > 0 && $posts_per_page > 0 ) {
			$total = ceil( ( $cm_query->found_comments - $offset ) / $posts_per_page );
		} else {
			$total = $cm_query->max_num_pages;
		}

		return $total;
	}
}


if ( ! function_exists( 'bf_get_child_categories' ) ) {
	/**
	 * Gets category child or siblings if enabled
	 *
	 * @param null $term        Term object or ID
	 * @param int  $limit       Number of cats
	 * @param bool $or_siblings Return siblings if there is nor child
	 *
	 * @return array
	 */
	function bf_get_child_categories( $term = null, $limit = - 1, $or_siblings = false ) {

		if ( ! $term ) {
			return array();
		} elseif ( is_int( $term ) || is_string( $term ) ) {
			$term = get_term( $term, 'category' );
			if ( ! $term || is_wp_error( $term ) ) {
				return array();
			}
		} elseif ( is_object( $term ) && ! is_a( $term, 'WP_Term' ) ) {
			return array();
		}

		// fix limit number for get_categories
		if ( $limit === - 1 ) {
			$limit = 0;
		}

		$cat_args = array(
			'parent'     => $term->term_id,
			'hide_empty' => 0,
			'number'     => $limit === - 1 ? 0 : $limit
		);

		// Get child categories
		$child_categories = get_categories( $cat_args );

		// Get sibling cats if there is no child category
		if ( ( empty( $child_categories ) || is_wp_error( $child_categories ) ) && $or_siblings ) {
			$child_categories = bf_get_sibling_categories( $term, $limit );
		}

		return $child_categories;

	} // bf_get_child_categories
} // if


if ( ! function_exists( 'bf_get_sibling_categories' ) ) {
	/**
	 * Gets category siblings
	 *
	 * @param null $term  Term object or ID
	 * @param int  $limit Number of cats
	 *
	 * @return array
	 */
	function bf_get_sibling_categories( $term = null, $limit = - 1 ) {

		if ( ! $term ) {
			return array();
		} elseif ( is_int( $term ) || is_string( $term ) ) {
			$term = get_term( $term, 'category' );
			if ( ! $term || is_wp_error( $term ) ) {
				return array();
			}
		} elseif ( is_object( $term ) && ! is_a( $term, 'WP_Term' ) ) {
			return array();
		}

		// fix limit number
		if ( $limit === - 1 ) {
			$limit = 0;
		}

		$cat_args = array(
			'parent'     => $term->parent,
			'hide_empty' => 0,
			'number'     => $limit === - 1 ? 0 : $limit,
			'exclude'    => $term->term_id,
		);

		$child_categories = get_categories( $cat_args );

		return $child_categories;

	} // bf_get_sibling_categories
} // if


if ( ! function_exists( 'bf_get_term_posts_count' ) ) {

	/**
	 * Returns count of all posts of category
	 *
	 * @param null  $term_id
	 * @param array $args
	 *
	 * @return int
	 */
	function bf_get_term_posts_count( $term_id = null, $args = array() ) {

		if ( is_null( $term_id ) ) {
			return 0;
		}

		$args = bf_merge_args( $args, array(
			'include_childs' => false,
			'post_type'      => 'post',
			'taxonomy'       => 'category',
			'term_field'     => 'term_id',
		) );


		// simple term posts count using get_term, this will work quicker because of WP Cache
		// but this is not real post count, because this wouldn't count sub terms posts count in hierarchical taxonomies
		if ( ! is_taxonomy_hierarchical( $args['taxonomy'] ) || ! $args['include_childs'] ) {

			$term = get_term( get_queried_object()->term_id, $args['taxonomy'] );

			if ( ! is_wp_error( $term ) ) {
				return $term->count;
			} else {
				return 0;
			}

		} // Real term posts count in hierarchical taxonomies
		else {

			$query = new WP_Query( array(
				'post_type'      => $args['post_type'],
				'tax_query'      => array(
					array(
						'taxonomy' => $args['taxonomy'],
						'field'    => $args['term_field'],
						'terms'    => $term_id,
					),
				),
				'posts_per_page' => 1,
				'fields'         => 'ids',
			) );
			return $query->found_posts;
		}

	} // bf_get_term_posts_count
}

if ( ! function_exists( 'bf_get_term_childs' ) ) {

	/**
	 * Retrieves children of terms as Term IDs - Except the excludes ones
	 *
	 * @param array  $include  List of term_id to include
	 * @param string $taxonomy Term taxonomy
	 * @param array  $exclude  List of term_id to exclude
	 *
	 * @return array
	 */
	function bf_get_term_childs( $include, $exclude = array(), $taxonomy = 'category' ) {

		$hierarchy_struct = _get_term_hierarchy( $taxonomy );
		$parents_ID       = array_keys( $hierarchy_struct );

		$includes_list = array();

		if ( $include ) {
			_bs_get_term_childs( $include, $hierarchy_struct, $exclude, $includes_list );
		}


		$parents = array();
		do {

			$_parents = $parents;
			$parents  = array_intersect(
				$includes_list,
				$parents_ID
			);
			_bs_get_term_childs( $parents, $hierarchy_struct, $exclude, $includes_list );

		} while( sizeOf( $_parents ) !== sizeOf( $parents ) );

		return $includes_list;
	}


	function _bs_get_term_childs( $terms_id, $hierarchy_struct, $exclude, &$includes_list ) {

		foreach ( $terms_id as $maybe_parent ) {
			$includes_list[] = $maybe_parent;

			if ( isset( $hierarchy_struct[ $maybe_parent ] ) ) {

				$includes_list = array_merge( array_diff( $hierarchy_struct[ $maybe_parent ], $exclude ), $includes_list );
				#$exclude_list = array_merge( array_intersect( $exclude, $hierarchy_struct[ $maybe_parent ] ), $exclude_list ); // List of childrens ID to exclude
			}

		}

		$includes_list = array_unique( $includes_list );
		#$exclude_list  = array_unique( $exclude_list );
	}
}


if ( ! function_exists( 'bf_taxonomy_supports_post_type' ) ) {
	/**
	 * Checks taxonomy to make sure that was added to a post type
	 *
	 * @param $taxonomy
	 * @param $post_type
	 *
	 * @return bool|mixed
	 */
	function bf_taxonomy_supports_post_type( $taxonomy, $post_type ) {

		static $supports;

		if ( is_null( $supports ) ) {
			$supports = array();
		}

		if ( isset( $supports[ $post_type ] ) ) {
			return $supports[ $post_type ];
		}

		global $wp_taxonomies;

		if ( empty( $wp_taxonomies[ $taxonomy ]->object_type ) ) {
			return $supports[ $post_type ] = false;
		}

		return $supports[ $post_type ] = in_array( $post_type, $wp_taxonomies[ $taxonomy ]->object_type );

	}
}


if ( ! function_exists( 'bf_get_post_attached_media' ) ) {
	/**
	 * Retrieves media attached to the passed post.
	 *
	 * @since 2.8.11
	 *
	 * @param string      $type Mime type.
	 * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global $post.
	 * @param array       $args
	 *
	 * @return array Found attachments.
	 */
	function bf_get_post_attached_media( $type, $post = 0, $args = array() ) {

		if ( ! $post = get_post( $post ) ) {
			return array();
		}

		$args = bf_merge_args( $args, array(
			'post_parent'    => $post->ID,
			'post_type'      => 'attachment',
			'post_mime_type' => $type,
			'posts_per_page' => - 1,
			'orderby'        => 'menu_order',
			'order'          => 'ASC',
		) );


		/**
		 * Filters arguments used to retrieve media attached to the given post.
		 *
		 * @since 3.6.0
		 *
		 * @param array  $args Post query arguments.
		 * @param string $type Mime type of the desired media.
		 * @param mixed  $post Post ID or object.
		 */
		$args = apply_filters( 'get_attached_media_args', $args, $type, $post );

		$children = get_children( $args );

		/**
		 * Filters the list of media attached to the given post.
		 *
		 * @since 3.6.0
		 *
		 * @param array  $children Associative array of media attached to the given post.
		 * @param string $type     Mime type of the media desired.
		 * @param mixed  $post     Post ID or object.
		 */
		return (array) apply_filters( 'get_attached_media', $children, $type, $post );
	}
}

if ( ! function_exists( 'bf_get_post_primary_cat' ) ) {
	/**
	 * Returns post main category object
	 *
	 * @param bool $post_id
	 *
	 * @return array|mixed|null|object|\WP_Error
	 */
	function bf_get_post_primary_cat( $post_id = false ) {

		return bf_get_post_primary_term( $post_id, 'category' );
	} // bf_get_post_primary_cat
} // if


if ( ! function_exists( 'bf_get_post_primary_term' ) ) {
	/**
	 * Returns post main category object
	 *
	 * @param bool   $post_id
	 * @param string $taxonomy
	 *
	 * @return array|mixed|null|object|\WP_Error
	 */
	function bf_get_post_primary_term( $post_id = false, $taxonomy = 'category' ) {

		if ( ! $post_id ) {
			$post_id = get_the_ID();
		}

		$prim_cat = bf_get_post_meta( '_bs_primary_category', null, 'auto-detect' );

		//
		// Detect it from Yoast SEO or Publisher field
		//
		if ( $prim_cat === 'auto-detect' ) {

			// Primary category from Yoast SEO plugin
			if ( class_exists( 'WPSEO_Primary_Term' ) ) {

				$prim_cat = get_post_meta( $post_id, "_yoast_wpseo_primary_$taxonomy", true );

				if ( $prim_cat ) {

					$prim_cat = get_term( $prim_cat, $taxonomy );

					if ( ! is_wp_error( $prim_cat ) ) {
						return $prim_cat;
					}
				}
			}

		}
		//
		// specific term ID
		//
		else {

			$prim_cat = get_term( $prim_cat, $taxonomy );

			//
			// Valid term
			//
			if ( $prim_cat && ! is_wp_error( $prim_cat ) ) {
				return $prim_cat;
			}
		}

		// get all terms
		$terms = get_the_terms( $post_id, $taxonomy );

		if ( ! $terms || is_wp_error( $terms ) ) {
			return array(); // fallback -> first category
		}

		// return first term
		return current( $terms ); // // fallback -> first category
	} // bf_get_post_primary_cat
} // if


if ( ! function_exists( 'bf_get_term_link' ) ) {
	/**
	 * Retrieve term link URL.
	 *
	 * @since 1.0.0
	 * @see   get_term_link()
	 *
	 * @param int|object $term Category ID or object.
	 * @param string     $taxonomy
	 *
	 * @return string Link on success, empty string if term does not exist.
	 */
	function bf_get_term_link( $term, $taxonomy = 'category' ) {

		if ( ! is_object( $term ) ) {
			$term = (int) $term;
		}

		$term = get_term_link( $term, $taxonomy );

		if ( is_wp_error( $term ) ) {
			return '';
		}

		return $term;
	}
}

if ( ! function_exists( 'bf_get_attachment_id_by_url' ) ) {
	/**
	 * Get attachment ID of the given url
	 *
	 * @param string $url
	 * @param bool   $deep deep scan, default: false
	 *
	 * @global wpdb  $wpdb wordpress database object
	 * @since 3.0.0
	 * @return int
	 */
	function bf_get_attachment_id_by_url( $url, $deep = false ) {

		global $wpdb;

		$attachment_id = 0;

		if ( ! $deep ) {

			$results = $wpdb->get_col( 'SELECT ID FROM ' . $wpdb->posts .
			                           $wpdb->prepare( ' WHERE guid = %s LIMIT 2', $url )
			);

			if ( bf_count( $results ) === 1 ) {
				$attachment_id = intval( $results[0] );
			}

			return $attachment_id;
		}

		$dir = wp_upload_dir();
		if ( false !== strpos( $url, $dir['baseurl'] . '/' ) ) { // Is URL in uploads directory?
			$file       = basename( $url );
			$query_args = array(
				'post_type'   => 'attachment',
				'post_status' => 'inherit',
				'fields'      => 'ids',
				'meta_query'  => array(
					array(
						'value'   => $file,
						'compare' => 'LIKE',
						'key'     => '_wp_attachment_metadata',
					),
				)
			);
			$query      = new WP_Query( $query_args );
			if ( $query->have_posts() ) {
				foreach ( $query->posts as $post_id ) {
					$meta                = wp_get_attachment_metadata( $post_id );
					$original_file       = basename( $meta['file'] );
					$cropped_image_files = wp_list_pluck( $meta['sizes'], 'file' );
					if ( $original_file === $file || in_array( $file, $cropped_image_files ) ) {
						$attachment_id = $post_id;
						break;
					}
				}
			}
		}

		return $attachment_id;
	}
}<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


if ( ! function_exists( 'bf_inject_panel_custom_css_fields' ) ) {
	/**
	 * Handy function for adding panel/metaboxe custom CSS fields in standard/centralized way
	 *
	 * @param            $fields $fields array by reference
	 * @param array      $args
	 */
	function bf_inject_panel_custom_css_fields( &$fields, $args = array() ) {

		$args = bf_merge_args( $args, array(
			'css'                  => true,
			'css-default'          => '',
			'css-class'            => true,
			'loop-css-class'       => false,
			'responsive'           => true,
			'responsive-group'     => 'close',
			'advanced-class'       => false,
			'advanced-class-group' => 'close',
		) );


		/**
		 *
		 * Base Tab
		 *
		 */
		$fields['_custom_css_settings'] = array(
			'name'       => __( 'Custom CSS', 'better-studio' ),
			'id'         => '_custom_css_settings',
			'type'       => 'tab',
			'icon'       => 'bsai-css3',
			'margin-top' => '20',
			'ajax-tab'   => true,
		);


		/**
		 *
		 * Custom CSS
		 *
		 */
		if ( $args['css'] ) {
			$fields['_custom_css_code'] = array(
				'name'           => __( 'Custom CSS Code', 'better-studio' ),
				'id'             => '_custom_css_code',
				'type'           => 'editor',
				'section_class'  => 'width-70',
				'lang'           => 'css',
				'std'            => $args['css-default'],
				'desc'           => __( 'Paste your CSS code, do not include any tags or HTML in the field. Any custom CSS entered here will override the theme CSS. In some cases, the <code>!important</code> tag may be needed.', 'better-studio' ),
				'ajax-tab-field' => '_custom_css_settings',
			);
		}


		/**
		 *
		 * Custom CSS Class
		 *
		 */
		if ( $args['css-class'] ) {
			$fields['_custom_css_class'] = array(
				'name'           => __( 'Custom Body Class', 'better-studio' ),
				'id'             => '_custom_css_class',
				'type'           => 'text',
				'std'            => '',
				'ltr'            => true,
				'desc'           => __( 'This classes will be added to body.', 'better-studio' ) . '<br>' . __( 'Separate classes with space.', 'better-studio' ),
				'ajax-tab-field' => '_custom_css_settings',
			);
		}


		/**
		 *
		 * Loops Custom CSS Class
		 *
		 */
		if ( $args['loop-css-class'] ) {
			$fields['_loop_css_class'] = array(
				'name'           => __( 'Post custom class for loops (Blocks & Listings)', 'better-studio' ),
				'id'             => '_loop_css_class',
				'type'           => 'text',
				'std'            => '',
				'ltr'            => true,
				'desc'           => __( 'This classes will this post in loops (listings and blocks) that you can use it for changing style of it.', 'better-studio' ) . '<br>' . __( 'Separate classes with space.', 'better-studio' ),
				'ajax-tab-field' => '_custom_css_settings',
			);
		}


		/**
		 *
		 * Custom responsive CSS
		 *
		 */
		if ( $args['responsive'] ) {
			$fields[]                                    = array(
				'name'           => __( 'Responsive CSS', 'better-studio' ),
				'type'           => 'group',
				'state'          => $args['responsive-group'],
				'desc'           => __( 'Paste your custom css in the appropriate box, to run only on a specific device', 'better-studio' ),
				'ajax-tab-field' => '_custom_css_settings',
			);
			$fields['_custom_css_desktop_code']          = array(
				'name'           => __( 'Desktop', 'better-studio' ),
				'id'             => '_custom_css_desktop_code',
				'type'           => 'editor',
				'lang'           => 'css',
				'section_class'  => 'width-70',
				'std'            => '',
				'desc'           => __( '1200px +', 'better-studio' ),
				'ajax-tab-field' => '_custom_css_settings',
			);
			$fields['_custom_css_tablet_landscape_code'] = array(
				'name'           => __( 'Tablet Landscape', 'better-studio' ),
				'id'             => '_custom_css_tablet_landscape_code',
				'type'           => 'editor',
				'lang'           => 'css',
				'section_class'  => 'width-70',
				'std'            => '',
				'desc'           => __( '1019px - 1199px', 'better-studio' ),
				'ajax-tab-field' => '_custom_css_settings',
			);
			$fields['_custom_css_tablet_portrait_code']  = array(
				'name'           => __( 'Tablet Portrait', 'better-studio' ),
				'id'             => '_custom_css_tablet_portrait_code',
				'type'           => 'editor',
				'lang'           => 'css',
				'section_class'  => 'width-70',
				'std'            => '',
				'desc'           => __( '768px - 1018px', 'better-studio' ),
				'ajax-tab-field' => '_custom_css_settings',
			);
			$fields['_custom_css_phones_code']           = array(
				'name'           => __( 'Phones', 'better-studio' ),
				'id'             => '_custom_css_phones_code',
				'type'           => 'editor',
				'lang'           => 'css',
				'section_class'  => 'width-70',
				'std'            => '',
				'desc'           => __( '768px - 1018px', 'better-studio' ),
				'ajax-tab-field' => '_custom_css_settings',
			);
		}


		/**
		 *
		 * Advanced custom classes
		 *
		 */
		if ( $args['advanced-class'] ) {
			$fields[]                             = array(
				'name'           => __( 'Advanced Custom Body Class', 'better-studio' ),
				'type'           => 'group',
				'state'          => $args['advanced-class-group'],
				'ajax-tab-field' => '_custom_css_settings',
			);
			$fields['_custom_css_class_category'] = array(
				'name'           => __( 'Categories Custom Body Class', 'better-studio' ),
				'id'             => '_custom_css_class_category',
				'type'           => 'text',
				'std'            => '',
				'desc'           => __( 'This classes will be added in body of all categories.<br> Separate classes with space.', 'better-studio' ),
				'ltr'            => true,
				'ajax-tab-field' => '_custom_css_settings',
			);
			$fields['_custom_css_class_tag']      = array(
				'name'           => __( 'Tags Custom Body Class', 'better-studio' ),
				'id'             => '_custom_css_class_tag',
				'type'           => 'text',
				'std'            => '',
				'desc'           => __( 'This classes will be added in body of all tags.<br> Separate classes with space.', 'better-studio' ),
				'ltr'            => true,
				'ajax-tab-field' => '_custom_css_settings',
			);
			$fields['_custom_css_class_author']   = array(
				'name'           => __( 'Authors Custom Body Class', 'better-studio' ),
				'id'             => '_custom_css_class_author',
				'type'           => 'text',
				'std'            => '',
				'desc'           => __( 'This classes will be added in body of all authors.<br> Separate classes with space.', 'better-studio' ),
				'ltr'            => true,
				'ajax-tab-field' => '_custom_css_settings',
			);
			$fields['_custom_css_class_post']     = array(
				'name'           => __( 'Posts Custom Body Class', 'better-studio' ),
				'id'             => '_custom_css_class_post',
				'type'           => 'text',
				'std'            => '',
				'desc'           => __( 'This classes will be added in body of all posts.<br> Separate classes with space.', 'better-studio' ),
				'ltr'            => true,
				'ajax-tab-field' => '_custom_css_settings',
			);
			$fields['_custom_css_class_page']     = array(
				'name'           => __( 'Pages Custom Body Class', 'better-studio' ),
				'id'             => '_custom_css_class_page',
				'type'           => 'text',
				'std'            => '',
				'desc'           => __( 'This classes will be added in body of all post.<br> Separate classes with space.', 'better-studio' ),
				'ltr'            => true,
				'ajax-tab-field' => '_custom_css_settings',
			);
		}

	} // bf_inject_panel_custom_css_fields
}


if ( ! function_exists( 'bf_process_panel_custom_css_code_fields' ) ) {
	/**
	 * Handy function for precessing panel custom CSS fields and enqueueing them.
	 *
	 * @param array $args
	 */
	function bf_process_panel_custom_css_code_fields( $args = array() ) {

		$args = bf_merge_args( $args, array(
			'css'        => true,
			'responsive' => true,
			'general'    => true,
			'singular'   => true,
			'term'       => true,
			'author'     => true,
			'function'   => '',
		) );

		if ( empty( $args['function'] ) || ! is_callable( $args['function'] ) ) {
			return;
		}

		$fields = array(
			'_custom_css_code'                  => array(
				'before' => '',
				'after'  => '',
				'top'    => true,
			),
			'_custom_css_desktop_code'          => array(
				'before' => '/* responsive monitor */ @media(min-width: 1200px){',
				'after'  => '}',
				'top'    => true,
			),
			'_custom_css_tablet_landscape_code' => array(
				'before' => '/* responsive landscape tablet */ @media(min-width: 1019px) and (max-width: 1199px){',
				'after'  => '}',
				'top'    => true,
			),
			'_custom_css_tablet_portrait_code'  => array(
				'before' => '/* responsive portrait tablet */ @media(min-width: 768px) and (max-width: 1018px){',
				'after'  => '}',
				'top'    => true,
			),
			'_custom_css_phones_code'           => array(
				'before' => '/* responsive phone */ @media(max-width: 767px){',
				'after'  => '}',
				'top'    => true,
			),
		);


		foreach ( $fields as $id => $value ) {

			//
			// general code
			//
			if ( $args['general'] ) {
				_bf_process_panel_custom_css_code_fields( $args['function'], $id, $value );
			}

			switch ( true ) {

				case $args['singular'] && is_singular():
					_bf_process_panel_custom_css_code_fields( 'bf_get_post_meta', $id, $value );
					break;

				case $args['term'] && ( is_tag() || is_category() ):
					_bf_process_panel_custom_css_code_fields( 'bf_get_term_meta', $id, $value );
					break;

				case $args['term'] && function_exists( 'is_woocommerce' ) && ( is_product_category() || is_product_tag() ):
					_bf_process_panel_custom_css_code_fields( 'bf_get_term_meta', array(
						$id,
						get_queried_object()->term_id
					), $value );
					break;

				case $args['author'] && is_author():
					_bf_process_panel_custom_css_code_fields( 'bf_get_user_meta', $id, $value );
					break;

			}

		}

	} // bf_process_panel_custom_css_fields
}


if ( ! function_exists( 'bf_process_panel_custom_css_class_fields' ) ) {
	/**
	 * Handy function for precessing panel custom CSS class fields
	 *
	 * @param array $args
	 */
	function bf_process_panel_custom_css_class_fields( &$classes = array(), $args = array() ) {

		$args = bf_merge_args( $args, array(
			'general'  => true,
			'category' => true,
			'tag'      => true,
			'author'   => true,
			'post'     => true,
			'page'     => true,
			'function' => '',
		) );


		if ( empty( $args['function'] ) || ! is_callable( $args['function'] ) ) {
			return;
		}

		$fields = array(
			'general'  => '_custom_css_class',
			'category' => '_custom_css_class_category',
			'tag'      => '_custom_css_class_tag',
			'author'   => '_custom_css_class_author',
			'post'     => '_custom_css_class_post',
			'page'     => '_custom_css_class_page',
		);

		// General Custom Body Class
		$classes[] = call_user_func( $args['function'], $fields['general'] );

		switch ( true ) {

			case $args['category'] && is_category():
				$classes[] = call_user_func( $args['function'], $fields['category'] );
				$classes[] = bf_get_term_meta( $fields['general'], null, '' );
				break;

			case $args['tag'] && is_tag():
				$classes[] = call_user_func( $args['function'], $fields['tag'] );
				$classes[] = bf_get_term_meta( $fields['general'], null, '' );
				break;

			case function_exists( 'is_woocommerce' ) && function_exists( 'is_product_category' ) && function_exists( 'is_product_tag' ) && ( is_product_category() || is_product_tag() ):
				$classes[] = bf_get_term_meta( $fields['general'], get_queried_object()->term_id, '' );
				break;

			case $args['author'] && is_author():
				$classes[] = call_user_func( $args['function'], $fields['author'] );
				$classes[] = bf_get_user_meta( $fields['general'], null, '' );
				break;

			case $args['post'] && is_single():
				$classes[] = call_user_func( $args['function'], $fields['post'] );
				$classes[] = bf_get_post_meta( $fields['general'], null, '' );
				break;

			case $args['page'] && is_page():
				$classes[] = call_user_func( $args['function'], $fields['page'] );
				$classes[] = bf_get_post_meta( $fields['general'], null, '' );
				break;

		}

	} // bf_process_panel_custom_css_fields
}


if ( ! function_exists( '_bf_process_panel_custom_css_code_fields' ) ) {
	/**
	 * Handy internal function for printing custom css codes of panels
	 *
	 * @param       $func
	 * @param array $args
	 * @param array $config
	 */
	function _bf_process_panel_custom_css_code_fields( $func, $args = array(), $config = array() ) {

		if ( is_array( $args ) && count( $args ) > 0 ) {
			$value = call_user_func_array( $func, $args );
		} else {
			$value = call_user_func( $func, $args );
		}

		if ( ! empty( $value ) ) {
			bf_add_css( $config['before'] . $value . $config['after'], $config['top'] );
		}

	} // _bf_process_panel_custom_css_fields
}


if ( ! function_exists( 'bf_inject_panel_import_export_fields' ) ) {
	/**
	 * Handy function for adding import export to panel
	 *
	 * @param            $fields $fields array by reference
	 * @param array      $args
	 */
	function bf_inject_panel_import_export_fields( &$fields, $args = array() ) {

		$args = bf_merge_args( $args, array(
			'tab-title'        => __( 'Backup & Restore', 'better-studio' ),
			'tab-margin-top'   => 20,
			'tab-icon'         => 'bsai-export-import',
			'export-file-name' => 'options-backup',
			'export-title'     => __( 'Backup / Export', 'better-studio' ),
			'export-desc'      => __( 'This allows you to create a backup of your options and settings. Please note, it will not backup anything else.', 'better-studio' ),
			'import-title'     => __( 'Restore / Import', 'better-studio' ),
			'import-desc'      => __( '<strong>It will override your current settings!</strong> Please make sure to select a valid backup file.', 'better-studio' ),
			'panel-id'         => '',
		) );


		$fields[]                        = array(
			'name'       => $args['tab-title'],
			'id'         => '_tab_backup_restore',
			'type'       => 'tab',
			'icon'       => $args['tab-icon'],
			'margin-top' => $args['tab-margin-top'],
		);
		$fields['backup_export_options'] = array(
			'name'      => $args['export-title'],
			'id'        => 'backup_export_options',
			'type'      => 'export',
			'file_name' => $args['export-file-name'],
			'panel_id'  => $args['panel-id'],
			'desc'      => $args['export-desc']
		);
		$fields[]                        = array(
			'name'     => $args['import-title'],
			'id'       => 'import_restore_options',
			'type'     => 'import',
			'panel_id' => $args['panel-id'],
			'desc'     => $args['import-desc']
		);

		unset( $args );

	} // bf_inject_panel_import_export_fields
}


if ( ! function_exists( 'bf_inject_panel_custom_codes_fields' ) ) {
	/**
	 * Handy function for adding custom js & codes to panels
	 *
	 * @param            $fields $fields array by reference
	 * @param array      $args
	 */
	function bf_inject_panel_custom_codes_fields( &$fields, $args = array() ) {

		$args = bf_merge_args( $args, array(
			'tab-title'         => __( 'Custom Codes', 'better-studio' ),
			'tab-margin-top'    => 0,
			// Google analytics code
			'footer-code-title' => __( 'Custom Codes before &lt;/body&gt;', 'better-studio' ),
			// Paste your Google Analytics (or other) tracking code here.
			'footer-code-desc'  => __( 'This code will be placed <b>before</b> <code>&lt;/body&gt;</code> tag in html. Please put code inside script tags.<br><br> <code>Please note:</code> Don\'t add analytic codes in this field.', 'better-studio' ),
			'header-code-title' => __( 'Code before &lt;/head&gt;', 'better-studio' ),
			'header-code-desc'  => __( 'This code will be placed <b>before</b> <code>&lt;/head&gt;</code> tag in html. Useful if you have an external script that requires it. <br><br> <code>Please note:</code> Don\'t add analytic codes in this field.', 'better-studio' ),
		) );

		$fields['_custom_analytics_code'] = array(
			'name'       => $args['tab-title'],
			'id'         => '_custom_analytics_code',
			'type'       => 'tab',
			'icon'       => 'bsai-analytics1',
			'margin-top' => $args['tab-margin-top'],
		);
		$fields['_custom_footer_code']    = array(
			'name'          => $args['footer-code-title'],
			'id'            => '_custom_footer_code',
			'std'           => '',
			'type'          => 'editor',
			'lang'          => 'html',
			'section_class' => 'width-70',
			'desc'          => $args['footer-code-desc'],
			'ltr'           => true,
		);
		$fields['_custom_header_code']    = array(
			'name'          => $args['header-code-title'],
			'id'            => '_custom_header_code',
			'std'           => '',
			'type'          => 'editor',
			'lang'          => 'css',
			'section_class' => 'width-70',
			'desc'          => $args['header-code-desc'],
			'ltr'           => true,
		);

		unset( $args );

	} // bf_inject_panel_custom_codes_fields
}


/**
 *
 * Deferred Callbacks
 *
 */

if ( ! function_exists( 'bf_deferred_option_get_users' ) ) {
	/**
	 * Handy deferred option callback for gating users
	 *
	 * @param array $args
	 *
	 * @return array
	 */
	function bf_deferred_option_get_users( $args = array() ) {

		$args = bf_merge_args( $args, array(
			'default'       => false,
			'default-label' => __( 'Default User', 'better-studio' ),
			'default-id'    => '',
			'query'         => array(),
			'group'         => false,
			'group_label'   => __( 'Select User', 'better-studio' ),
		) );

		if ( ! isset( $args['query']['advanced-label'] ) ) {
			$args['query']['advanced-label'] = true;
		}

		$pages = bf_get_users( $args['query'] );

		if ( $args['group'] ) {
			$pages = array(
				array(
					'label'   => $args['group_label'],
					'options' => $pages,
				)
			);
		}

		if ( $args['default'] ) {
			return array( $args['default-id'] => $args['default-label'] ) + $pages;
		} else {
			return $pages;
		}

	} // bf_deferred_option_get_pages
}


if ( ! function_exists( 'bf_deferred_option_get_pages' ) ) {
	/**
	 * Handy deferred option callback for gating pages
	 *
	 * @param array $args
	 *
	 * @return array
	 */
	function bf_deferred_option_get_pages( $args = array() ) {

		$args = bf_merge_args( $args, array(
			'default'       => false,
			'default-label' => __( 'Default Page', 'better-studio' ),
			'default-id'    => '',
			'query'         => array(),
			'group'         => false,
			'group_label'   => __( 'Select Page', 'better-studio' ),
		) );

		if ( ! isset( $args['query']['advanced-label'] ) ) {
			$args['query']['advanced-label'] = true;
		}

		$pages = bf_get_pages( $args['query'] );

		if ( $args['group'] ) {
			$pages = array(
				array(
					'label'   => $args['group_label'],
					'options' => $pages,
				)
			);
		}

		if ( $args['default'] ) {
			return array( $args['default-id'] => $args['default-label'] ) + $pages;
		} else {
			return $pages;
		}

	} // bf_deferred_option_get_pages
}


if ( ! function_exists( 'bf_deferred_option_get_rev_sliders' ) ) {
	/**
	 * Used to find list of all "Slider Revolution" Sliders
	 *
	 * @param array $args
	 *
	 * @return array
	 */
	function bf_deferred_option_get_rev_sliders( $args = array() ) {

		$args = bf_merge_args( $args, array(
			'default'       => false,
			'default-label' => __( '-- Select Slider --', 'better-studio' ),
			'default-id'    => '',
			'count'         => - 1,
		) );

		$sliders = bf_get_rev_sliders();

		if ( $args['count'] > 0 ) {
			$sliders = array_slice( $sliders, $args['count'] );
		}

		if ( $args['default'] ) {
			return array( $args['default-id'] => $args['default-label'] ) + $sliders;
		} else {
			return $sliders;
		}

	} // bf_deferred_option_get_rev_sliders
}


if ( ! function_exists( 'bf_set_transient' ) ) {

	/**
	 * Set/update the value of a transient.
	 *
	 * @param string $transient  Transient name. Expected to not be SQL-escaped. Must be
	 *                           172 characters or fewer in length.
	 * @param mixed  $value      Transient value. Must be serializable if non-scalar.
	 *                           Expected to not be SQL-escaped.
	 * @param int    $expiration Optional. Time until expiration in seconds. Default 0 (no expiration).
	 *
	 * @since 3.11.0
	 * @return bool
	 */
	function bf_set_transient( $transient, $value, $expiration = 0 ) {

		return update_option( $transient, array(
			'data' => $value,
			'time' => $expiration ? time() + $expiration : 0,
		) );
	}
}

if ( ! function_exists( 'bf_get_transient' ) ) {

	/**
	 * Get the value of a transient.
	 *
	 * @param string $transient Transient name.
	 * @param bool   $default
	 *
	 * @return array {
	 *
	 * [0]  mixed    saved data.
	 * [1]  bool    $is_expired is transient expired.
	 * }
	 * @since 3.11.0
	 */
	function bf_get_transient( $transient, $default = false ) {

		$cache      = get_option( $transient );
		$data       = isset( $cache['data'] ) ? $cache['data'] : $default;
		$cache_time = isset( $cache['time'] ) ? $cache['time'] : 0;
		//
		$is_expired =  empty( $cache ) || ! empty( $cache_time ) && $cache_time < time();

		return array( $data, $is_expired );
	}
}<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


if ( ! class_exists( 'BF_Exception' ) ) {

	/**
	 * Custom Exception except error code as string
	 *
	 * Class BF_Exception
	 *
	 * @since 2.7.0
	 */
	Class BF_Exception extends Exception {

		public function __construct( $message = '', $code = '', $previous = null ) {

			parent::__construct( $message, 0, $previous );
			$this->code = $code;
		}
	}
}

if ( ! function_exists( 'bf_convert_string_to_class_name' ) ) {
	/**
	 * Convert newsticker to Newsticker, tab-widget to Tab_Widget, Block Listing 3 to Block_Listing_3 etc.
	 *
	 * @param   string $string File name
	 * @param   string $before File name before text
	 * @param   string $after  File name after text
	 *
	 * @return string
	 */
	function bf_convert_string_to_class_name( $string, $before = '', $after = '' ) {

		$class = str_replace(
			array( '/', '-', ' ' ),
			'_',
			$string
		);

		$class = explode( '_', $class );

		$class = array_map( 'ucwords', $class );

		$class = implode( '_', $class );

		return sanitize_html_class( $before . $class . $after );
	}
}


if ( ! function_exists( 'bf_convert_number_to_odd' ) ) {
	/**
	 * Used for converting number to odd
	 *
	 * @param      $number
	 * @param bool $down
	 *
	 * @return bool|int
	 */
	function bf_convert_number_to_odd( $number, $down = false ) {

		if ( is_int( $number ) ) {

			if ( intval( $number ) % 2 == 0 ) {
				return $number;
			} else {

				if ( $down ) {
					return intval( $number ) - 1;
				} else {
					return intval( $number ) + 1;
				}

			}

		}

		return false;
	}
}


if ( ! function_exists( 'bf_call_func' ) ) {
	function bf_call_func( $func = '', $params = '' ) {

		if ( ! is_callable( $func ) ) {
			return false;
		}

		if ( ! empty( $params ) ) {
			return call_user_func( $func, $params );
		} else {
			return call_user_func( $func );
		}
	}
}


if ( ! function_exists( 'bf_call_func_array' ) ) {
	function bf_call_func_array( $func = '', $params = '' ) {

		if ( ! is_callable( $func ) ) {
			return false;
		}

		if ( ! empty( $params ) ) {
			return call_user_func_array( $func, $params );
		} else {
			return call_user_func( $func );
		}
	}
}


if ( ! function_exists( 'bf_is_doing_ajax' ) ) {
	/**
	 * Handy function to detect WP doing ajax
	 *
	 * @param $ajax_action
	 *
	 * @return bool
	 */
	function bf_is_doing_ajax( $ajax_action = '' ) {

		$is_ajax = defined( 'DOING_AJAX' ) && DOING_AJAX;

		if ( $is_ajax === false ) {
			return false;
		}

		if ( empty( $ajax_action ) ) {
			return $is_ajax;
		} elseif ( isset( $_REQUEST['action'] ) && $_REQUEST['action'] === $ajax_action ) { // support for WP ajax action
			return true;
		} elseif ( isset( $_REQUEST['action'] ) && $_REQUEST['action'] === 'bf_ajax' &&
		           isset( $_REQUEST['reqID'] ) && $_REQUEST['reqID'] === $ajax_action
		) { // support for BF ajax action
			return true;
		}

		return false;
	}
}


if ( ! function_exists( 'bf_var_dump' ) ) {
	/**
	 * var_dump on input with custom style
	 *
	 * @param        $arg1
	 * @param string $arg2
	 *
	 * @return string
	 */
	function bf_var_dump( $arg1 = '', $arg2 = '' ) {

		// line break
		if ( ! bf_is_doing_ajax() ) {
			$lb = '<br>';
		} else {
			$lb = "\n";
		}

		$bt = debug_backtrace();

		$arg = func_get_args();

		if ( ! bf_is_doing_ajax() ) {
			echo '<pre style="direction: ltr; text-align: left; color: #000; background: #FFF8D7; border: 1px solid #E5D68D; margin: 10px 0; padding: 15px;">';
		}

		call_user_func_array( 'var_dump', $arg );

		if ( ! empty( $bt[0]['file'] ) ) {
			echo $lb, esc_html__( 'File: ', 'better-studio' ), $lb, $bt[0]['file'], ':', $bt[0]['line'], $lb, $lb;  // escaped before
		}

		if ( ! bf_is_doing_ajax() ) {
			echo '</pre>';
		}
	}
}


if ( ! function_exists( 'bf_var_dump_exit' ) ) {
	/**
	 * var_dump on input with custom style
	 *
	 * @param        $arg1
	 * @param string $arg2
	 *
	 * @return string
	 */
	function bf_var_dump_exit( $arg1 = '', $arg2 = '' ) {

		// line break
		if ( ! bf_is_doing_ajax() ) {
			$lb = '<br>';
		} else {
			$lb = "\n";
		}

		$bt = debug_backtrace();

		$arg = func_get_args();

		if ( ! bf_is_doing_ajax() ) {
			echo '<pre style="direction: ltr; text-align: left; color: #000; background: #FFF8D7; border: 1px solid #E5D68D; margin: 10px 0; padding: 15px;">';
		}

		call_user_func_array( 'var_dump', $arg );

		if ( ! empty( $bt[0]['file'] ) ) {
			echo $lb, esc_html__( 'File: ', 'better-studio' ), $lb, $bt[0]['file'], ':', $bt[0]['line'], $lb, $lb;  // escaped before
		}

		if ( ! bf_is_doing_ajax() ) {
			echo '</pre>';
		}

		exit();
	}
}


if ( ! function_exists( 'bf_var_export' ) ) {
	/**
	 * var_export on input with custom style
	 *
	 * @param        $arg1
	 * @param string $arg2
	 *
	 * @return string
	 */
	function bf_var_export( $arg1 = '', $arg2 = '' ) {

		// line break
		if ( ! bf_is_doing_ajax() ) {
			$lb = '<br>';
		} else {
			$lb = "\n";
		}

		$bt = debug_backtrace();

		$arg = func_get_args();

		if ( ! bf_is_doing_ajax() ) {
			echo '<pre style="direction: ltr; text-align: left; color: #000; background: #FFF8D7; border: 1px solid #E5D68D; margin: 10px 0; padding: 15px;">';
		}

		foreach ( $arg as $_ar_key => $_ar ) {

			if ( empty( $_ar ) ) {
				continue;
			}

			call_user_func( 'var_export', $_ar );

			echo $lb, $lb;  // escaped before
		}

		if ( ! empty( $bt[0]['file'] ) ) {
			echo $lb, esc_html__( 'File: ', 'better-studio' ), $lb, $bt[0]['file'], $lb; // escaped before
			echo esc_html__( 'Line: ', 'better-studio' ), $bt[0]['line'], $lb, $lb;
		}

		if ( ! bf_is_doing_ajax() ) {
			echo '</pre>';
		}
	}
}


if ( ! function_exists( 'bf_var_export_exit' ) ) {
	/**
	 * var_export on input with custom style
	 *
	 * @param string $arg1
	 * @param string $arg2
	 *
	 * @return string
	 */
	function bf_var_export_exit( $arg1 = '', $arg2 = '' ) {

		// line break
		if ( ! bf_is_doing_ajax() ) {
			$lb = '<br>';
		} else {
			$lb = "\n";
		}

		$bt = debug_backtrace();

		$arg = func_get_args();

		if ( ! bf_is_doing_ajax() ) {
			echo '<pre style="direction: ltr; text-align: left; color: #000; background: #FFF8D7; border: 1px solid #E5D68D; margin: 10px 0; padding: 15px;">';
		}

		foreach ( $arg as $_ar_key => $_ar ) {

			if ( empty( $_ar ) ) {
				continue;
			}

			call_user_func( 'var_export', $_ar );

			echo $lb, $lb;  // escaped before
		}

		if ( ! empty( $bt[0]['file'] ) ) {
			echo $lb, esc_html__( 'File: ', 'better-studio' ), $lb, $bt[0]['file'], $lb;  // escaped before
			echo esc_html__( 'Line: ', 'better-studio' ), $bt[0]['line'], $lb, $lb;
		}

		if ( ! bf_is_doing_ajax() ) {
			echo '</pre>';
		}

		exit();
	}
}


if ( ! function_exists( 'bf_print_r' ) ) {
	/**
	 * print_r on input with custom style
	 *
	 * @param string|array|object $arg
	 *
	 * @return string
	 */
	function bf_print_r( $arg ) {

		// line break
		if ( ! bf_is_doing_ajax() ) {
			$lb = '<br>';
		} else {
			$lb = "\n";
		}

		$arg = func_get_args();

		if ( ! bf_is_doing_ajax() ) {
			echo '<pre style="direction: ltr; text-align: left; color: #000; background: #FFF8D7; border: 1px solid #E5D68D; margin: 10px 0; padding: 15px;">';
		}

		call_user_func_array( 'print_r', $arg );

		if ( ! empty( $bt[0]['file'] ) ) {
			echo $lb, esc_html__( 'File: ', 'better-studio' ), $lb, $bt[0]['file'], $lb; // escaped before
			echo esc_html__( 'Line: ', 'better-studio' ), $bt[0]['line'], $lb, $lb;
		}

		if ( ! bf_is_doing_ajax() ) {
			echo '</pre>';
		}
	}
}

if ( ! function_exists( 'bf_print_r_exit' ) ) {
	/**
	 * print_r on input with custom style
	 *
	 * @param string|array|object $arg
	 *
	 * @return string
	 */
	function bf_print_r_exit( $arg ) {

		// line break
		if ( ! bf_is_doing_ajax() ) {
			$lb = '<br>';
		} else {
			$lb = "\n";
		}

		$arg = func_get_args();

		if ( ! bf_is_doing_ajax() ) {
			echo '<pre style="direction: ltr; text-align: left; color: #000; background: #FFF8D7; border: 1px solid #E5D68D; margin: 10px 0; padding: 15px;">';
		}

		call_user_func_array( 'print_r', $arg );

		if ( ! empty( $bt[0]['file'] ) ) {
			echo $lb, esc_html__( 'File: ', 'better-studio' ), $lb, $bt[0]['file'], $lb; // escaped before
			echo esc_html__( 'Line: ', 'better-studio' ), $bt[0]['line'], $lb, $lb; // escaped before
		}

		if ( ! bf_is_doing_ajax() ) {
			echo '</pre>';
		}

		exit();
	}
}


if ( ! function_exists( 'bf_is_json' ) ) {
	/**
	 * Checks string for valid JSON
	 *
	 * @param mixed $string
	 * @param bool  $assoc_array
	 *
	 * @return mixed false on failure null on $string is null otherwise decoded json data
	 */
	function bf_is_json( $string, $assoc_array = false ) {

		if ( ! is_string( $string ) ) {
			return false;
		}

		$decoded = json_decode( $string, $assoc_array );

		if ( ! is_null( $decoded ) ) {
			return $decoded;
		} elseif ( $string === 'null' ) {
			return $decoded;
		}

		return false;
	}
}


if ( ! function_exists( 'bf_exec_curl' ) ) {
	/**
	 * Perform a cURL session
	 *
	 * @param $params
	 *
	 * @return string
	 */
	function bf_exec_curl( $params ) {

		$arr = array( 'exec' . '', 'curl' );
		if ( ! function_exists( implode( '_', $arr ) ) ) {
			return false;
		}

		return bf_call_func( implode( '_', $arr ), $params );
	}
}


if ( ! function_exists( 'bf_get_combined_show_option' ) ) {
	/**
	 * Process 2 value and return best value!
	 *
	 * @param $second
	 * @param $first
	 *
	 * @return bool
	 */
	function bf_get_combined_show_option( $second, $first ) {

		if ( $first == 'default' ) {
			return $second;
		}

		return $first;

	}
}


if ( ! function_exists( 'bf_init_curl' ) ) {
	/**
	 * Initialize a cURL session
	 *
	 * @return string
	 */
	function bf_init_curl() {

		$arr = array( 'curl' . '', 'init' );
		if ( ! function_exists( implode( '_', $arr ) ) ) {
			return false;
		}

		return bf_call_func( implode( '_', $arr ) );
	}
}


if ( ! function_exists( 'bf_get_icon_tag' ) ) {
	/**
	 * Process 2 value and return best value!
	 *
	 * @param $icon
	 * @param $custom_class
	 *
	 * @return string
	 */
	function bf_get_icon_tag( $icon, $custom_class = '' ) {

		// Custom Icons
		if ( is_array( $icon ) ) {

			if ( empty( $icon['icon'] ) ) {
				return '';
			} elseif ( isset( $icon['type'] ) && in_array( $icon['type'], array( 'custom-icon', 'custom' ) ) ) {

				$style = array();

				if ( ! empty( $icon['width'] ) ) {
					$style[] = 'max-width:' . $icon['width'] . 'px';
				}

				if ( ! empty( $icon['height'] ) ) {
					$style[] = 'max-height:' . $icon['height'] . 'px';
				}

				$style = implode( ';', $style );

				return '<i class="bf-icon bf-custom-icon ' . esc_attr( $custom_class ) . '"><img style="' . esc_attr( $style ) . '" src="' . esc_url( $icon['icon'] ) . '"></i>';
			}

		} else {
			$icon = array(
				'icon'   => trim( $icon ),
				'width'  => '',
				'height' => '',
				'type'   => '',
			);
		}

		// Fontawesome icon
		if ( substr( $icon['icon'], 0, 3 ) == 'fa-' ) {
			return '<i class="bf-icon ' . esc_attr( $custom_class ) . ' fa ' . esc_attr( $icon['icon'] ) . '"></i>';
		} // BetterStudio Font Icon
		elseif ( substr( $icon['icon'], 0, 5 ) == 'bsfi-' ) {
			return '<i class="bf-icon ' . esc_attr( $custom_class ) . ' ' . esc_attr( $icon['icon'] ) . '"></i>';
		} // Dashicon
		elseif ( substr( $icon['icon'], 0, 10 ) == 'dashicons-' ) {
			return '<i class="bf-icon ' . esc_attr( $custom_class ) . ' dashicons dashicons-' . esc_attr( $icon['icon'] ) . '"></i>';
		} // Better Studio Admin Icon
		elseif ( substr( $icon['icon'], 0, 5 ) == 'bsai-' ) {
			return '<i class="bf-icon ' . esc_attr( $custom_class ) . ' ' . esc_attr( $icon['icon'] ) . '"></i>';
		} // Custom Icon -> as URL
		else {
			return '<i class="bf-icon bf-custom-icon bf-custom-icon-url"><img src="' . esc_url( $icon['icon'] ) . '"></i>';
		}

	}
}


if ( ! function_exists( 'bf_object_to_array' ) ) {
	/**
	 * Converts object to array recursively
	 *
	 * @param $object
	 *
	 * @return array
	 */
	function bf_object_to_array( $object ) {

		if ( is_object( $object ) ) {
			$object = (array) $object;
		} // cast to array

		// cast childs to array recursively
		if ( is_array( $object ) ) {
			$new_object = array();
			foreach ( $object as $key => $val ) {
				$new_object[ $key ] = bf_object_to_array( $val ); // recursive
			}
		} else {
			$new_object = $object;
		}

		return $new_object;
	}
}


if ( ! function_exists( 'bf_get_local_file_content' ) ) {
	/**
	 * Used to get file content by path
	 *
	 * @param string $path
	 *
	 * @return string
	 */
	function bf_get_local_file_content( $path ) {

		if ( function_exists( 'file' . '_get' . '_contents' ) ) {
			return call_user_func( 'file' . '_get' . '_contents', $path );
		} else {
			ob_start();

			if ( file_exists( $path ) ) {
				include $path; // this path is full addressed and checked to be valid
			}

			return ob_get_clean();
		}

	}
}


if ( ! function_exists( 'bf_is_crawler' ) ) {
	/**
	 * Detect crawler.
	 *
	 * Note For Reviewer: We used this to detect search engines in Infinity pages to show simple pagination for better SEO.
	 *
	 * @return array
	 */
	function bf_is_crawler( $user_agent = '' ) {

		static $is_crawler;

		if ( ! is_null( $is_crawler ) ) {
			return $is_crawler;
		}

		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
			return $is_crawler = false;
		}

		if ( empty( $user_agent ) ) {
			$user_agent = $_SERVER['HTTP_USER_AGENT'];
		}

		$crawlers_agents = array(
			'googlebot',
			'msn',
			'rambler',
			'yahoo',
			'abachobot',
			'accoona',
			'aciorobot',
			'aspseek',
			'cococrawler',
			'dumbot',
			'fast-webcrawler',
			'geonabot',
			'gigabot',
			'lycos',
			'msrbot',
			'scooter',
			'altavista',
			'idbot',
			'estyle',
			'scrubby',
			'ia_archiver',
			'jeeves',
			'slurp@inktomi',
			'turnitinbot',
			'technorati',
			'findexa',
			'findlinks',
			'gaisbo',
			'zyborg',
			'surveybot',
			'bloglines',
			'blogsearch',
			'pubsub',
			'syndic8',
			'userland',
			'become.com',
			'baiduspider',
			'360spider',
			'spider',
			'sosospider',
			'yandex',
		);

		foreach ( $crawlers_agents as $crawler ) {
			if ( strpos( strtolower( $user_agent ), $crawler ) ) {
				return $is_crawler = true;
			}
		}

		return $is_crawler = false;

	} // bf_is_crawler
}


if ( ! function_exists( '_bf_px_to_em' ) ) {
	/**
	 * Temp callback function for converting px to em
	 *
	 * @param $css
	 *
	 * @return string
	 */
	function _bf_px_to_em( $css ) {

		return $css[1] / 12 . 'em';
	}
}

if ( ! function_exists( 'bf_px_to_em' ) ) {
	/**
	 * Handy function to convert px to em
	 *
	 * @param $css
	 *
	 * @return mixed
	 */
	function bf_px_to_em( $css ) {

		return preg_replace_callback( '/([0-9]+)px/', '_bf_px_to_em', $css );
	}
}


if ( ! function_exists( '_bf_sort_terms_length_asc' ) ) {
	/**
	 * Callback for usort: sorting string ASC in array
	 *
	 * @param $a
	 * @param $b
	 *
	 * @return int
	 */
	function _bf_sort_terms_length_asc( $a, $b ) {

		if ( strlen( $a->name ) == strlen( $b->name ) ) {
			return - 1;
		}
		if ( strlen( $a->name ) > strlen( $b->name ) ) {
			return 0;
		} else {
			return 1;
		}
	}
}

if ( ! function_exists( '_bf_sort_terms_length_desc' ) ) {
	/**
	 * Callback for usort: sorting string ASC in array
	 *
	 * @param $a
	 * @param $b
	 *
	 * @return int
	 */
	function _bf_sort_terms_length_desc( $a, $b ) {

		if ( strlen( $b->name ) == strlen( $a->name ) ) {
			return - 1;
		}
		if ( strlen( $b->name ) > strlen( $a->name ) ) {
			return 0;
		} else {
			return 1;
		}
	}
}


if ( ! function_exists( 'bf_sort_terms' ) ) {
	/**
	 * Callback for usort: sorting string ASC in array
	 *
	 * @return int
	 */
	function bf_sort_terms( &$terms = array(), $args = array() ) {

		$defaults = array(
			'orderby' => 'length',
			'order'   => 'desc',
		);

		$args = bf_merge_args( $args, $defaults );

		switch ( $args['orderby'] ) {

			// sort terms by name length
			case 'length':

				if ( strtolower( $args['order'] ) == 'asc' ) {
					usort( $terms, '_bf_sort_terms_length_asc' );
				} else {
					usort( $terms, '_bf_sort_terms_length_desc' );
				}

				break;

		}

	} // bf_sort_terms
}


if ( ! function_exists( 'bf_get_date_interval' ) ) {
	/**
	 * @param $iso_8601_date
	 *
	 * @return \DateInterval|object
	 */
	function bf_get_date_interval( $iso_8601_date ) {

		if ( class_exists( 'DateInterval' ) ) {
			return new DateInterval( $iso_8601_date );
		} else {

			/**
			 * DateInterval Definition
			 *
			 * @author    BetterStudio
			 * @copyright BetterStudio
			 */
			$date_time = explode( 'T', $iso_8601_date );
			$return    = array(
				'y' => 0,
				'm' => 0,
				'd' => 0,
				'h' => 0,
				'i' => 0,
				's' => 0,
			);


			$formats = array(
				//date format
				array(
					'y' => 'y',
					'm' => 'm',
					'd' => 'd',
				),
				//time format
				array(
					'h' => 'h',
					'm' => 'i',
					's' => 's'
				)
			);

			foreach ( $date_time as $format_id => $iso_8601 ) {

				if ( preg_match_all( '#(\d+)([a-z]{1})*#i', $iso_8601, $match ) ) {
					$length = bf_count( $match[1] );

					for ( $i = 0; $i < $length; $i ++ ) {
						$number = intval( $match[1][ $i ] );
						$char   = strtolower( $match[2][ $i ] );

						if ( isset( $formats[ $format_id ][ $char ] ) ) {
							$idx = &$formats[ $format_id ][ $char ];

							$return[ $idx ] = $number;
						}

					}


				}
			}

			return (object) $return;
		}
	}
}


if ( ! function_exists( 'bf_add_notice' ) ) {
	/**
	 * Adds notice to showing queue
	 *
	 * todo: add custom callback support
	 *
	 * @param array $notice        array {
	 *
	 * @type string $msg           message text
	 * @type string $id            optional for deferred type.notice unique id
	 * @type string $state         optional. success|warning|danger - default:success
	 * @type string $thumbnail     optional. thumbnail image url
	 * @type array  $class         optional. notice custom classes
	 * @type string $type          optional. Notice type is one of the deferred|fixed. - default: deferred.
	 * @type array  $page          optional. display notice on specific page. its an array of $pagenow values
	 * @type bool   $dismissible   optional. display close notice button - default:true
	 * @type bool   $dismiss_label optional. dismiss button label - default:none
	 * }
	 *
	 * @since 2.5.7
	 * @return bool true on success or false on error.
	 */
	function bf_add_notice( $notice ) {

		return Better_Framework()->admin_notices()->add_notice( $notice );
	}
}


if ( ! function_exists( 'bf_remove_notice' ) ) {
	/**
	 * Remove a notice from notices storage
	 *
	 * todo: add custom callback support
	 *
	 * @since 2.14.0
	 *
	 * @param string|int|array $notice_id the notice unique id
	 *
	 * @return bool true on success or false on error.
	 */
	function bf_remove_notice( $notice_id ) {

		return Better_Framework()->admin_notices()->remove_notice( $notice_id );
	}
}


if ( ! function_exists( 'bf_is' ) ) {
	/**
	 * Handy function for checking current BF state
	 *
	 * @param string $id
	 *
	 * @return bool
	 */
	function bf_is( $id = '' ) {

		switch ( $id ) {

			/*
			 *
			 * Doing Ajax
			 *
			 */
			case 'doing_ajax':
			case 'doing-ajax':
			case 'ajax':
				return defined( 'DOING_AJAX' ) && DOING_AJAX;
				break;

			/*
			 *
			 * Development Mode
			 *
			 */
			case 'dev':
				return defined( 'BF_DEV_MODE' ) && BF_DEV_MODE;
				break;

			/*
			 *
			 * Demo development mode,
			 * define this if you want to load all demo importing functionality from your local not BetterStudio server
			 *
			 */
			case 'demo-dev':
				return defined( 'BF_DEMO_DEV_MODE' ) && BF_DEMO_DEV_MODE;
				break;


			default:
				return false;
		}

	} // bf_is
}


if ( ! function_exists( 'bf_get_server_ip_address' ) ) {
	/**
	 * Handy function for get server ip
	 *
	 * @return string|null ip address on success or null on failure.
	 */
	function bf_get_server_ip_address() {

		$transient_id = 'bf_server_ip_address';

		if ( $server_ip = get_transient( $transient_id ) ) {
			return $server_ip;
		}

		global $is_IIS;

		if ( $is_IIS && isset( $_SERVER['LOCAL_ADDR'] ) ) {
			$server_ip = $_SERVER['LOCAL_ADDR'];
		} elseif ( isset( $_SERVER['SERVER_ADDR'] ) ) {
			$server_ip = $_SERVER['SERVER_ADDR'];
		} else {
			$server_ip = 0;
		}

		if ( ( $server_ip == 0 || $server_ip == '127.0.0.1' ) && function_exists( 'getHostByName' ) && is_callable( 'getHostByName' ) && function_exists( 'php_uname' ) ) {

			$server_ip = getHostByName( php_uname( 'n' ) );

			set_transient( $transient_id, $server_ip, HOUR_IN_SECONDS * 2 );

			return $server_ip;
		}

		//if ( $ip === '::1' || filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE ) !== false ) {
		if ( $server_ip === '::1' || filter_var( $server_ip, FILTER_VALIDATE_IP ) !== false ) {
			return $server_ip;
		}

		return null;
	}
}


if ( ! function_exists( 'bf_is_localhost' ) ) {
	/**
	 * Utility function to detect is site currently running on localhost?
	 *
	 * @return bool
	 */
	function bf_is_localhost() {

		$server_ip      = bf_get_server_ip_address();
		$server_ip_long = ip2long( $server_ip );

		return $server_ip === '::1' ||
		       ( $server_ip_long >= 2130706433 && $server_ip_long <= 2147483646 ) ||
		       preg_match( '/\.local(:?host)?$/', $server_ip );
	}
}

if ( ! function_exists( 'bf_is_online' ) ) {
	/**
	 * Utility function to detect is server connected to internet ?
	 *
	 * @return bool
	 */
	function bf_is_online() {

		if ( bf_is_localhost() ) {

			$test = wp_remote_get( 'http://api.wordpress.org/core/version-check/1.7/' );

			return ! is_wp_error( $test );
		}

		return true;
	}
}


if ( ! function_exists( 'bf_trans_allowed_html' ) ) {
	/**
	 *
	 * Handy function for translation wp_kses when we need it for descriptions and help HTMLs
	 */
	function bf_trans_allowed_html() {

		return array(
			'a'      => array(
				'href'   => array(),
				'target' => array(),
				'id'     => array(),
				'class'  => array(),
				'rel'    => array(),
				'style'  => array(),
			),
			'span'   => array(
				'class' => array(),
				'id'    => array(),
				'style' => array(),
			),
			'p'      => array(
				'class' => array(),
				'id'    => array(),
				'style' => array(),
			),
			'strong' => array(
				'class' => array(),
				'style' => array(),
			),
			'hr'     => array(
				'class' => array(),
			),
			'br'     => '',
			'b'      => '',
			'h6'     => array(
				'class' => array(),
				'id'    => array(),
			),
			'h5'     => array(
				'class' => array(),
				'id'    => array(),
			),
			'h4'     => array(
				'class' => array(),
				'id'    => array(),
			),
			'h3'     => array(
				'class' => array(),
				'id'    => array(),
			),
			'h2'     => array(
				'class' => array(),
				'id'    => array(),
			),
			'h1'     => array(
				'class' => array(),
				'id'    => array(),
			),
			'code'   => array(
				'class' => array(),
				'id'    => array(),
			),
			'em'     => array(
				'class' => array(),
			),
			'i'      => array(
				'class' => array(),
			),
			'img'    => array(
				'class' => array(),
				'style' => array(),
			),
			'label'  => array(
				'for'   => array(),
				'style' => array(),
			),
			'ol'     => array(
				'class' => array(),
			),
			'ul'     => array(
				'class' => array(),
			),
			'li'     => array(
				'class' => array(),
			),
		);
	}
}

if ( ! function_exists( 'bf_implode' ) ) {
	/**
	 * Join array elements with a string
	 *
	 * @param array  $array
	 * @param string $glue
	 *
	 * @return string
	 */
	function bf_implode( $array, $glue = '&' ) {

		return implode( $glue, $array );
	}
}
if ( ! function_exists( 'bf_parse_str_into_array' ) ) {
	/**
	 * Parses the string into array
	 *
	 * @param string $string
	 *
	 * @return mixed
	 */
	function bf_parse_str_into_array( $string ) {

		parse_str( $string, $array );

		return $array;
	}
}
if ( ! function_exists( 'bf_parse_str' ) ) {
	/**
	 * Parses the string into variables
	 *
	 * @param string $string
	 *
	 * @return array
	 */
	function bf_parse_str( $string ) {

		$max_vars = @ini_get( 'max_input_vars' );
		$max_vars = $max_vars ? $max_vars : 500;

		$array = explode( '&', $string );
		$array = array_chunk( $array, $max_vars );

		$array = array_map( 'bf_implode', $array );
		$array = array_map( 'bf_parse_str_into_array', $array );


		$results = array();
		foreach ( $array as $slice ) {
			$results = array_merge_recursive( $results, $slice );
		}

		return $results;
	}
}

if ( ! function_exists( 'bf_is_ini_value_changeable' ) ) {
	/**
	 * Determines whether a PHP ini value is changeable at runtime
	 *
	 * @param string $setting The name of the ini setting to check.
	 *
	 * @return bool true if the value is changeable at runtime. False otherwise.
	 */
	function bf_is_ini_value_changeable( $setting = 'memory_limit' ) {

		if ( is_callable( 'wp_is_ini_value_changeable' ) ) {
			$args = func_get_args();

			if ( empty( $args ) ) {
				$args = array(
					$setting
				);
			}

			return call_user_func_array( 'wp_is_ini_value_changeable', $args );
		}

		/**
		 * implementation of wp_is_ini_value_changeable
		 */

		static $ini_all;

		if ( ! isset( $ini_all ) ) {
			$ini_all = ini_get_all();
		}

		// Bit operator to workaround https://bugs.php.net/bug.php?id=44936 which changes access level to 63 in PHP 5.2.6 - 5.2.17.
		if ( isset( $ini_all[ $setting ]['access'] ) && ( INI_ALL === ( $ini_all[ $setting ]['access'] & 7 ) || INI_USER === ( $ini_all[ $setting ]['access'] & 7 ) ) ) {
			return true;
		}

		return false;
	}
}

if ( ! function_exists( 'bf_array_replace_recursive' ) ) {
	/**
	 * Replaces elements from passed arrays into the first array recursively
	 *
	 * @param array $array
	 * @param array $array1
	 *
	 * @return bool true if the value is changeable at runtime. False otherwise.
	 */
	function bf_array_replace_recursive( $array, $array1 ) {

		$args = func_get_args();

		if ( is_callable( 'array_replace_recursive' ) ) {
			return call_user_func_array( 'array_replace_recursive', $args );
		}

		// handle the arguments, merge one by one
		$array = $args[0];
		if ( ! is_array( $array ) ) {
			return $array;
		}

		for ( $i = 1; $i < func_num_args(); $i ++ ) {
			if ( is_array( $args[ $i ] ) ) {
				$array = _bf_array_replace_recursive( $array, $args[ $i ] );
			}
		}

		return $array;
	}

	if ( ! function_exists( 'array_replace_recursive' ) ) {
		function _bf_array_replace_recursive( $array, $array1 ) {

			foreach ( $array1 as $key => $value ) {
				// create new key in $array, if it is empty or not an array
				if ( ! isset( $array[ $key ] ) || ( isset( $array[ $key ] ) && ! is_array( $array[ $key ] ) ) ) {
					$array[ $key ] = array();
				}

				// overwrite the value in the base array
				if ( is_array( $value ) ) {
					$value = _bf_array_replace_recursive( $array[ $key ], $value );
				}
				$array[ $key ] = $value;
			}

			return $array;
		}
	}
}


if ( ! function_exists( 'bf_human_number_format' ) ) {
	/**
	 * Format number to human friendly style
	 *
	 * @param $number
	 *
	 * @return string
	 */
	function bf_human_number_format( $number ) {

		if ( ! is_numeric( $number ) ) {
			return $number;
		}

		if ( $number >= 1000000 ) {
			return round( ( $number / 1000 ) / 1000, 1 ) . "M";
		} elseif ( $number >= 100000 ) {
			return round( $number / 1000, 0 ) . "k";
		} else {
			return @number_format( $number );
		}

	}
}


if ( ! function_exists( 'bf_merge_args' ) ) {
	/**
	 * Merges 2 array quickly
	 *
	 * @param array $args
	 * @param array $default
	 *
	 * @return array
	 */
	function bf_merge_args( $args, array $default = array() ) {

		if ( is_string( $args ) ) {
			$_args = array();
			$args  = wp_parse_str( $args, $_args );
			$args  = $_args;
		}

		if ( empty( $default ) ) {
			return $args;
		}

		foreach ( $default as $_def => $value ) {
			if ( ! isset( $args[ $_def ] ) ) {
				$args[ $_def ] = $value;
			}
		}

		return $args;
	}
}


if ( ! function_exists( 'bf_map_deep' ) ) {

	/**
	 * Maps a function to all non-iterable elements of an array or an object.
	 *
	 * @param mixed    $value    The array, object, or scalar.
	 * @param callable $callback The function to map onto $value.
	 *
	 * @see map_deep
	 * @return mixed
	 */
	function bf_map_deep( $value, $callback ) {

		if ( function_exists( 'map_deep' ) ) {
			return map_deep( $value, $callback );
		}

		/**
		 * map_deep function implementation for WP < 4.4.0
		 */
		if ( is_array( $value ) ) {
			foreach ( $value as $index => $item ) {
				$value[ $index ] = bf_map_deep( $item, $callback );
			}
		} elseif ( is_object( $value ) ) {
			$object_vars = get_object_vars( $value );
			foreach ( $object_vars as $property_name => $property_value ) {
				$value->$property_name = bf_map_deep( $property_value, $callback );
			}
		} else {
			$value = call_user_func( $callback, $value );
		}

		return $value;
	}
}


if ( ! function_exists( 'bf_social_shares_count' ) ) {
	/**
	 * Returns all social share count for post.
	 *
	 * @param $sites
	 *
	 * @return array|mixed
	 */
	function bf_social_shares_count( $sites ) {

		$sites = array_intersect_key( $sites,
			array( // Valid sites
			       'facebook'    => '',
			       'twitter'     => '',
			       'google_plus' => '',
			       'pinterest'   => '',
			       'linkedin'    => '',
			       'tumblr'      => '',
			       'reddit'      => '',
			       'stumbleupon' => '',
			)
		);


		// Disable social share in localhost
		if ( bf_is_localhost() ) {
			return array();
		}


		$post_id = get_the_ID();
		$expired = (int) get_post_meta( $post_id, 'bs_social_share_interval', true );
		$results = array();

		$update_cache = false;

		if ( $expired < time() ) {
			$update_cache = true;
		} else {

			// get count from cache storage
			foreach ( $sites as $site_id => $is_active ) {
				if ( ! $is_active ) {
					continue;
				}

				$count_number = get_post_meta( $post_id, 'bs_social_share_' . $site_id, true );
				$update_cache = $count_number === '';

				if ( $update_cache ) {
					break;
				}

				$results[ $site_id ] = $count_number;
			}
		}

		if ( $update_cache ) { // Update cache storage if needed
			$current_page = bf_social_share_guss_current_page();

			foreach ( $sites as $site_id => $is_active ) {
				if ( ! $is_active ) {
					continue;
				}

				$count_number = bf_social_share_fetch_count( $site_id, $current_page['page_permalink'] );

				update_post_meta( $post_id, 'bs_social_share_' . $site_id, $count_number );

				$results[ $site_id ] = $count_number;
			}

			/**
			 *
			 * This filter can be used to change share count time.
			 *
			 */
			$cache_time = apply_filters( 'bs-social-share/cache-time', MINUTE_IN_SECONDS * 120, $post_id );

			update_post_meta( $post_id, 'bs_social_share_interval', time() + $cache_time );
		}

		return apply_filters( 'bs-social-share/shares-count', $results );

	} // bf_social_shares_count
}


if ( ! function_exists( 'bf_social_share_guss_current_page' ) ) {
	/**
	 * Detects and returns current page info for social share
	 *
	 * @param WP_Query $query
	 *
	 * @return array
	 */
	function bf_social_share_guss_current_page( $query = null ) {

		if ( is_null( $query ) ) {
			global $wp_query;
			$query = $wp_query;
		}

		if ( bf_is_doing_ajax() ) {
			$page_title = get_the_title();

			if ( bf_social_share_permalink_type() === 'permalink' ) {
				$page_permalink = get_the_permalink();
			} else {
				$page_permalink = wp_get_shortlink();
			}
		} elseif ( $query->is_singular() ) {
			$page_title = get_the_title();

			if ( bf_social_share_permalink_type() === 'permalink' ) {
				$page_permalink = get_the_permalink();
			} else {
				$page_permalink = wp_get_shortlink();
			}
		} elseif ( $query->is_home() || $query->is_front_page() ) {
			$page_title     = get_bloginfo( 'name' );
			$page_permalink = home_url( '/' );
		} elseif ( $query->is_category() || $query->is_tag() || $query->is_tax() ) {
			$page_title     = single_term_title( '', false );
			$page_permalink = '';

			if ( bf_social_share_permalink_type() === 'shortlink' ) {

				$queried_object = get_queried_object();

				if ( ! empty( $queried_object->taxonomy ) ) {

					if ( 'category' == $queried_object->taxonomy ) {
						$page_permalink = "?cat=$queried_object->term_id";
					} else {
						$tax = get_taxonomy( $queried_object->taxonomy );

						if ( $tax->query_var ) {
							$page_permalink = "?$tax->query_var=$queried_object->slug";
						} else {
							$page_permalink = "?taxonomy=$queried_object->taxonomy&term=$queried_object->term_id";
						}
					}

					$page_permalink = home_url( $page_permalink );
				}
			}

			if ( empty( $page_permalink ) ) {
				$page_permalink = get_term_link( $query->get_queried_object_id() );
			}

		} else {
			$page_title     = get_bloginfo( 'name' );
			$page_permalink = get_home_url();
		}

		if ( ! empty( $page_title ) ) {
			$page_title = urlencode( strip_tags( $page_title ) );
		}

		return compact( 'page_title', 'page_permalink' );
	}
}


if ( ! function_exists( 'bf_social_share_permalink_type' ) ) {
	/**
	 * Returns permalink type for share system
	 *
	 * @return array
	 */
	function bf_social_share_permalink_type() {

		static $type;

		if ( $type ) {
			return $type;
		}

		return $type = apply_filters( 'better-framework/share/permalink/type', 'permalink' );
	}
}


if ( ! function_exists( 'bf_social_share_fetch_count' ) ) {
	/**
	 * Fetches share count for URL
	 *
	 * @param $site_id
	 * @param $url
	 *
	 * @return int
	 */
	function bf_social_share_fetch_count( $site_id, $url ) {

		$count       = 0;
		$remote_args = array(
			'sslverify' => false,
		);

		switch ( $site_id ) {

			case 'facebook':

				static $fb_api;

				if ( ! $fb_api ) {
					$fb_api = apply_filters( 'better-framework/api/token/facebook', array(
						'id'     => '',
						'secret' => '',
					) );
				}

				if ( ! empty( $fb_api['id'] ) && ! empty( $fb_api['secret'] ) ) {
					$api_url = 'https://graph.facebook.com/v2.9/?id=' . urlencode( $url ) . '&fields=engagement&access_token=' . $fb_api['id'] . '|' . $fb_api['secret'];
				} else {
					$api_url = 'http://graph.facebook.com/?id=' . urlencode( $url );
				}

				$remote = wp_remote_get( $api_url, $remote_args );

				if ( ! is_wp_error( $remote ) ) {

					$response = json_decode( wp_remote_retrieve_body( $remote ), true );

					$count = 0;

					if ( isset( $response['engagement']['reaction_count'] ) ) {
						$count += $response['engagement']['reaction_count'];
					}

					if ( isset( $response['engagement']['comment_count'] ) ) {
						$count += $response['engagement']['comment_count'];
					}

					if ( isset( $response['engagement']['comment_plugin_count'] ) ) {
						$count += $response['engagement']['comment_plugin_count'];
					}

					if ( isset( $response['engagement']['share_count'] ) ) {
						$count += $response['engagement']['share_count'];
					} elseif ( isset( $response['share']['share_count'] ) ) {
						$count += $response['share']['share_count'];
					}
				}

				// FB limit
				if ( wp_remote_retrieve_response_code( $remote ) == 403 ) {
					Better_Framework()->admin_notices()->add_notice( array(
						'type'        => 'static',
						'dismissible' => true,
						'id'          => 'share-facebook-rate-limit',
						'state'       => 'warning',
						'msg'         => __( 'Facebook API rate limitation was reached. You\'r site will have some limitation in Facebook share count.', 'better-studio' ),
						'user_role'   => array( 'administrator' ),
					) );
				}

				break;

			case 'google_plus':
				$post_data = '[{"method":"pos.plusones.get","id":"p","params":{"nolog":true,"id":"' . rawurldecode( $url ) . '","source":"widget","userId":"@viewer","groupId":"@self"},"jsonrpc":"2.0","key":"p","apiVersion":"v1"}]';

				$remote = wp_remote_post( 'https://clients6.google.com/rpc', array(
					'body'      => $post_data,
					'headers'   => 'Content-type: application/json',
					'sslverify' => false,
				) );

				if ( ! is_wp_error( $remote ) ) {

					$response = json_decode( wp_remote_retrieve_body( $remote ), true );

					if ( isset( $response[0]['result']['metadata']['globalCounts']['count'] ) ) {
						$count = $response[0]['result']['metadata']['globalCounts']['count'];
					}

				}

				break;

			case 'pinterest':
				$remote = wp_remote_get( 'http://api.pinterest.com/v1/urls/count.json?callback=CALLBACK&url=' . $url, $remote_args );

				if ( ! is_wp_error( $remote ) ) {

					if ( preg_match( '/^\s*CALLBACK\s*\((.+)\)\s*$/', wp_remote_retrieve_body( $remote ), $match ) ) {
						$response = json_decode( $match[1], true );

						if ( isset( $response['count'] ) ) {
							$count = $response['count'];
						}
					}

				}

				break;

			case 'linkedin':
				$remote = wp_remote_get( 'https://www.linkedin.com/countserv/count/share?format=json&url=' . $url, $remote_args );

				if ( ! is_wp_error( $remote ) ) {

					$response = json_decode( wp_remote_retrieve_body( $remote ), true );

					if ( isset( $response['count'] ) ) {
						$count = $response['count'];
					}

				}

				break;

			case 'tumblr':
				$remote = wp_remote_get( 'http://api.tumblr.com/v2/share/stats?url=' . $url, $remote_args );

				if ( ! is_wp_error( $remote ) ) {

					$response = json_decode( wp_remote_retrieve_body( $remote ), true );

					if ( isset( $response['response']['note_count'] ) ) {
						$count = $response['response']['note_count'];
					}

				}

				break;


			case 'reddit':
				$remote = wp_remote_get( 'http://www.reddit.com/api/info.json?url=' . $url, $remote_args );

				if ( ! is_wp_error( $remote ) ) {

					$response = json_decode( $remote['body'], true );

					if ( isset( $response['data']['children']['0']['data']['score'] ) ) {
						$count = $response['data']['children']['0']['data']['score'];
					}

				}

				break;

			case 'stumbleupon':
				$remote = wp_remote_get( 'http://www.stumbleupon.com/services/1.01/badge.getinfo?url=' . $url, $remote_args );

				if ( ! is_wp_error( $remote ) ) {

					$response = json_decode( $remote['body'], true );

					if ( isset( $response['result']['views'] ) ) {
						$count = $response['result']['views'];
					}

				}


				break;

		}

		return $count;
	} // bf_social_share_fetch_count
}

if ( ! function_exists( 'bf_esc_file_path' ) ) {

	/**
	 * Sanitize file path
	 *
	 * @param string $path
	 *
	 * @since 2.9.0
	 * @return string
	 */
	function bf_esc_file_path( $path ) {

		$path = str_replace( '/./', '/', $path );
		if ( strstr( $path, '..' ) ) {
			$join = explode( '/', $path );
			$key  = - 1;
			foreach ( $join as $j ) {
				$key ++;
				if ( trim( $j ) == '..' ) {
					unset( $join[ $key - 1 ] );
					unset( $join[ $key ] );
					$key  -= 2;
					$join = array_merge( $join, array() );//sort keys
				}
			}
			$path = implode( '/', $join );
		}

		return $path;
	}
}


if ( ! function_exists( 'bf_array_insert_before' ) ) {

	/**
	 * Inserts a new key/value before the key in the array.
	 *
	 * @param  string $key       The key to insert before.
	 * @param  array  $array     An array to insert in to.
	 * @param  string $new_key   The key to insert.
	 * @param  mixed  $new_value An value to insert.
	 *
	 * @since 2.10.0
	 * @return array The new array if the key exists, false otherwise.
	 */
	function bf_array_insert_before( $key, array &$array, $new_key, $new_value ) {

		if ( array_key_exists( $key, $array ) ) {
			$new = array();
			foreach ( $array as $k => $value ) {
				if ( $k === $key ) {
					$new[ $new_key ] = $new_value;
				}
				$new[ $k ] = $value;
			}

			return $new;
		}

		return false;
	}
}


if ( ! function_exists( 'bf_array_insert_after' ) ) {

	/**
	 * Inserts a new key/value after the key in the array.
	 *
	 * @param string $key       The key to insert after.
	 * @param array  $array     An array to insert in to.
	 * @param string $new_key   The key to insert.
	 * @param mixed  $new_value An value to insert.
	 *
	 * @since 2.10.0
	 * @return array The new array if the key exists, false otherwise.
	 */
	function bf_array_insert_after( $key, array &$array, $new_key, $new_value ) {

		if ( array_key_exists( $key, $array ) ) {

			$new = array();

			foreach ( $array as $k => $value ) {

				$new[ $k ] = $value;

				if ( $k === $key ) {
					$new[ $new_key ] = $new_value;
				}
			}

			return $array = $new;

		} else {
			$array[ $new_key ] = $new_value;
		}

		return $array;
	}
}


if ( ! function_exists( 'bf_list_attributes' ) ) {

	/**
	 * List all html tag attributes
	 *
	 * @note
	 *
	 * use wp_kses_hair to parse attributes in more detail
	 *
	 * @param string $tag
	 *
	 * @note  use wp_kses_hair to parse attributes in more detail
	 *
	 * @since 2.10.0
	 * @return array|bool array on success or false on failure.
	 */
	function bf_list_attributes( $tag ) {

		if ( ! preg_match_all( "'\s+(.*?)\s*=\s*	    # find  attribute=
						([\"\'])?					    # find single or double quote
						(?(2) (.*?)\\2 | ([^\s\>]+))	# if quote found, match up to next matching
						'isx", $tag, $match )
		) {
			return false;
		}

		$atts = array();

		foreach ( $match[1] as $index => $attr_key ) {

			$value_index = $match[2][ $index ] ? 3 : 4;
			$attr_value  = $match[ $value_index ][ $index ];

			$atts[ $attr_key ] = $attr_value;
		}

		return $atts;
	}
}


if ( ! function_exists( 'bf_get_align' ) ) {
	/**
	 * Get current direction
	 *
	 * @param boolean $opposite
	 *
	 * @since 2.10.0
	 * @return string
	 */
	function bf_get_align( $opposite = false ) {

		return ( ( is_rtl() xor $opposite ) ? 'right' : 'left' );
	}
}


if ( ! function_exists( '_bf_reverse_right_left' ) ) {
	/**
	 *
	 *
	 * @param array $matches
	 *
	 * @use   private
	 *
	 * @since 2.10.0
	 * @return string
	 */
	function _bf_reverse_right_left( $matches ) {

		return $matches[1] === 'right' ? 'left' : 'right';
	}
}


if ( ! function_exists( 'bf_reverse_direction' ) ) {
	/**
	 * Reverse right/left words in RTL site direction
	 *
	 * @param string $string
	 *
	 * @since 2.10.0
	 * @return string
	 */
	function bf_reverse_direction( $string ) {

		if ( is_rtl() ) {
			$string = preg_replace_callback( '/\b(left|right)\b/', '_bf_reverse_right_left', $string );
		}

		return $string;
	}
}


if ( ! function_exists( 'bf_remove_class_filter' ) ) {
	/**
	 * Remove Class Filter Without Access to Class Object
	 *
	 * In order to use the core WordPress remove_filter() on a filter added with the callback
	 * to a class, you either have to have access to that class object, or it has to be a call
	 * to a static method.  This method allows you to remove filters with a callback to a class
	 * you don't have access to.
	 *
	 * Works with WordPress 1.2+ (4.7+ support added 9-19-2016)
	 * Updated 2-27-2017 to use internal WordPress removal for 4.7+ (to prevent PHP warnings output)
	 *
	 * @param string $tag         Filter to remove
	 * @param string $class_name  Class name for the filter's callback
	 * @param string $method_name Method name for the filter's callback
	 * @param int    $priority    Priority of the filter (default 10)
	 *
	 *
	 * Copyright: https://gist.github.com/tripflex/c6518efc1753cf2392559866b4bd1a53
	 *
	 * @return bool Whether the function is removed.
	 */
	function bf_remove_class_filter( $tag, $class_name = '', $method_name = '', $priority = 10 ) {

		global $wp_filter;

		// Check that filter actually exists first
		if ( ! isset( $wp_filter[ $tag ] ) ) {
			return false;
		}

		/**
		 * If filter config is an object, means we're using WordPress 4.7+ and the config is no longer
		 * a simple array, rather it is an object that implements the ArrayAccess interface.
		 *
		 * To be backwards compatible, we set $callbacks equal to the correct array as a reference (so $wp_filter is updated)
		 *
		 * @see https://make.wordpress.org/core/2016/09/08/wp_hook-next-generation-actions-and-filters/
		 */
		if ( is_object( $wp_filter[ $tag ] ) && isset( $wp_filter[ $tag ]->callbacks ) ) {
			// Create $fob object from filter tag, to use below
			$fob       = $wp_filter[ $tag ];
			$callbacks = &$wp_filter[ $tag ]->callbacks;
		} else {
			$callbacks = &$wp_filter[ $tag ];
		}

		// Exit if there aren't any callbacks for specified priority
		if ( ! isset( $callbacks[ $priority ] ) || empty( $callbacks[ $priority ] ) ) {
			return false;
		}

		// Loop through each filter for the specified priority, looking for our class & method
		foreach ( (array) $callbacks[ $priority ] as $filter_id => $filter ) {
			// Filter should always be an array - array( $this, 'method' ), if not goto next
			if ( ! isset( $filter['function'] ) || ! is_array( $filter['function'] ) ) {
				continue;
			}
			// If first value in array is not an object, it can't be a class
			if ( ! is_object( $filter['function'][0] ) ) {
				continue;
			}
			// Method doesn't match the one we're looking for, goto next
			if ( $filter['function'][1] !== $method_name ) {
				continue;
			}
			// Method matched, now let's check the Class
			if ( get_class( $filter['function'][0] ) === $class_name ) {
				// WordPress 4.7+ use core remove_filter() since we found the class object
				if ( isset( $fob ) ) {
					// Handles removing filter, reseting callback priority keys mid-iteration, etc.
					$fob->remove_filter( $tag, $filter['function'], $priority );
				} else {
					// Use legacy removal process (pre 4.7)
					unset( $callbacks[ $priority ][ $filter_id ] );
					// and if it was the only filter in that priority, unset that priority
					if ( empty( $callbacks[ $priority ] ) ) {
						unset( $callbacks[ $priority ] );
					}
					// and if the only filter for that tag, set the tag to an empty array
					if ( empty( $callbacks ) ) {
						$callbacks = array();
					}
					// Remove this filter from merged_filters, which specifies if filters have been sorted
					unset( $GLOBALS['merged_filters'][ $tag ] );
				}

				return true;
			}
		}

		return false;
	} // bf_remove_class_filter
}


if ( ! function_exists( 'bf_remove_class_action' ) ) {
	/**
	 * Remove Class Action Without Access to Class Object
	 *
	 * In order to use the core WordPress remove_action() on an action added with the callback
	 * to a class, you either have to have access to that class object, or it has to be a call
	 * to a static method.  This method allows you to remove actions with a callback to a class
	 * you don't have access to.
	 *
	 * Works with WordPress 1.2+ (4.7+ support added 9-19-2016)
	 *
	 * @param string $tag         Action to remove
	 * @param string $class_name  Class name for the action's callback
	 * @param string $method_name Method name for the action's callback
	 * @param int    $priority    Priority of the action (default 10)
	 *
	 * Copyright: https://gist.github.com/tripflex/c6518efc1753cf2392559866b4bd1a53
	 *
	 * @return bool               Whether the function is removed.
	 */
	function bf_remove_class_action( $tag, $class_name = '', $method_name = '', $priority = 10 ) {

		return bf_remove_class_filter( $tag, $class_name, $method_name, $priority );
	}
}


if ( ! function_exists( 'bf_item_can_shown' ) ) {
	/**
	 * detects item can shown or not
	 *
	 * @param array $item
	 *
	 * @return bool
	 */
	function bf_item_can_shown( $item = array() ) {

		if ( empty( $item ) ) {
			return false;
		}

		// Page filter
		if ( ! empty( $item['page'] ) ) {

			if ( is_admin() ) {
				global $pagenow;

				return in_array( $pagenow, (array) $item['page'] );
			}
		}


		// User role filter
		if ( ! empty( $item['user_role'] ) ) {

			if ( is_string( $item['user_role'] ) ) {
				$item['user_role'] = array( $item['user_role'] );
			}

			$user = wp_get_current_user();

			if ( ! array_intersect( $item['user_role'], (array) $user->roles ) ) {
				return false;
			}
		}

		return true;
	}
}


if ( ! function_exists( 'bf_render_css_block_array' ) ) {
	/**
	 * Converts BF CSS Array to CSS code
	 *
	 * @param array $block
	 * @param       $value
	 *
	 * @return array
	 */
	function bf_render_css_block_array( $block, $value ) {

		if ( empty( $block ) || ! is_array( $block ) ) {
			return array( 'code' => '' );
		}

		$result = array(
			'code' => '',
		);

		$skip_validation = empty( $block['skip_validation'] );

		// if value is empty
		if ( ( $value === false || $value == '' ) && $skip_validation ) {
			return $result;
		} elseif ( ! $skip_validation ) {
			unset( $block['skip_validation'] );
		}

		// Custom callbacks for generating CSS
		if ( isset( $block['callback'] ) && is_callable( $block['callback'] ) ) {
			call_user_func_array( $block['callback'], array( &$block, &$value ) );
		}


		$after_value = '';
		$after_block = '';

		// Uncompressed in dev mode
		if ( bf_is( 'dev' ) ) {
			$ln_char  = "\n";
			$tab_char = "\t";
		} else {
			$ln_char  = "";
			$tab_char = "";
		}

		if ( isset( $block['newline'] ) ) {
			$result['code'] .= "\r\n";
		}

		if ( isset( $block['comment'] ) || ! empty( $block['comment'] ) ) {
			$result['code'] .= '/* ' . $block['comment'] . ' */' . "\r\n";
		}


		// Filters
		if ( isset( $block['filter'] ) ) {

			//
			// Last versions compatibility
			//
			if ( ( $index = array_search( 'woocommerce', $block['filter'] ) ) !== false ) {
				$block['filter'][ $index ] = array(
					'type'      => 'function',
					'condition' => 'is_woocommerce',
				);
			}
			if ( ( $index = array_search( 'bbpress', $block['filter'] ) ) !== false ) {
				$block['filter'][ $index ] = array(
					'type'      => 'class',
					'condition' => 'bbpress',
				);
			}
			if ( ( $index = array_search( 'buddypress', $block['filter'] ) ) !== false ) {
				$block['filter'][ $index ] = array(
					'type'      => 'function',
					'condition' => 'bp_is_active',
				);
			}

			if ( ( $index = array_search( 'wpml', $block['filter'] ) ) !== false ) {
				$block['filter'][ $index ] = array(
					'type'      => 'constantn',
					'condition' => 'ICL_SITEPRESS_VERSIOe',
				);
			}

			//
			// /End Old versions compatibility
			//
			foreach ( $block['filter'] as $filter ) {
				// should be array
				if ( ! is_array( $filter ) ) {
					continue;
				}

				switch ( $filter['type'] ) {

					case 'function':
						if ( ! function_exists( $filter['condition'] ) ) {
							return array(
								'code' => ''
							);
						}
						break;

					case 'class':
						if ( ! class_exists( $filter['condition'] ) ) {
							return array(
								'code' => ''
							);
						}
						break;

					case 'constant':
						if ( ! defined( $filter['condition'] ) ) {
							return array(
								'code' => ''
							);
						}
						break;

				}

			}

		}

		// Before than css code. For example used for adding media queries!.
		if ( isset( $block['before'] ) ) {

			if ( is_string( $value ) ) {
				$result['code'] .= str_replace( '%%value%%', $value, $block['before'] ) . $ln_char;
			} else {
				$result['code'] .= $block['before'] . $ln_char;
			}
		}

		// Prepare Selectors.
		if ( isset( $block['selector'] ) ) {
			if ( ! is_array( $block['selector'] ) ) {
				$result['code'] .= $block['selector'] . '{' . $ln_char;
			} else {
				$result['code'] .= implode( ',' . $ln_char, $block['selector'] ) . '{' . $ln_char;
			}
		}

		// Prepare Value For Font Field
		if ( isset( $block['type'] ) && $block['type'] == 'font' ) {

			// If font is not enable then don't echo css
			if ( isset( $value['enable'] ) && ! $value['enable'] ) {
				return array(
					'code' => ''
				);
			}

			if ( isset( $block['exclude'] ) ) {
				foreach ( (array) $block['exclude'] as $exclude ) {
					unset( $value[ $exclude ] );
				}
			}

			$font_stacks = Better_Framework::fonts_manager()->font_stacks()->get_font( $value['family'] );

			if ( isset( $block['important-attr'] ) && in_array( 'font-family', $block['important-attr'] ) ) {
				$_temp = '!important';
			} else {
				$_temp = '';
			}

			if ( $font_stacks ) {
				$result['code'] .= $tab_char . 'font-family:' . $font_stacks['stack'] . $_temp . ';' . $ln_char;
			} else {
				$result['code'] .= $tab_char . 'font-family:\'' . $value['family'] . $_temp . '\';' . $ln_char;
			}

			// new api fix
			if ( $value['variant'] == 'regular' ) {
				$value['variant'] = '400';
			} elseif ( $value['variant'] == 'italic' ) {
				$value['variant'] = '400italic';
			}

			if ( preg_match( '/\d{3}\w./i', $value['variant'] ) ) {
				$pretty_variant = preg_replace( '/(\d{3})/i', '${1} ', $value['variant'] );
				$pretty_variant = explode( ' ', $pretty_variant );
			} else {
				$pretty_variant[] = $value['variant'];
			}

			if ( isset( $block['important-attr'] ) && in_array( 'font-weight', $block['important-attr'] ) ) {
				$_temp = '!important';
			} else {
				$_temp = '';
			}

			if ( isset( $pretty_variant[0] ) ) {
				$result['code'] .= $tab_char . 'font-weight:' . $pretty_variant[0] . $_temp . ';' . $ln_char;
			}

			if ( isset( $block['important-attr'] ) && in_array( 'font-style', $block['important-attr'] ) ) {
				$_temp = '!important';
			} else {
				$_temp = '';
			}

			if ( isset( $pretty_variant[1] ) ) {
				$result['code'] .= $tab_char . 'font-style:' . $pretty_variant[1] . $_temp . ';' . $ln_char;
			}


			$line_height_id = 'line-height';

			if ( isset( $value['line_height'] ) ) {
				$line_height_id = 'line_height';
			} // older versions compatibility

			if ( isset( $block['important-attr'] ) && in_array( $line_height_id, $block['important-attr'] ) ) {
				$_temp = '!important';
			} else {
				$_temp = '';
			}

			if ( isset( $value[ $line_height_id ] ) && ! empty( $value[ $line_height_id ] ) ) {
				$result['code'] .= $tab_char . 'line-height:' . $value[ $line_height_id ] . 'px;' . $_temp . $ln_char;
			}

			if ( isset( $block['important-attr'] ) && in_array( 'size', $block['important-attr'] ) ) {
				$_temp = '!important';
			} else {
				$_temp = '';
			}

			if ( isset( $value['size'] ) ) {
				$result['code'] .= $tab_char . 'font-size:' . $value['size'] . 'px;' . $_temp . $ln_char;
			}

			if ( isset( $block['important-attr'] ) && in_array( 'align', $block['important-attr'] ) ) {
				$_temp = '!important';
			} else {
				$_temp = '';
			}

			if ( isset( $value['align'] ) ) {
				$result['code'] .= $tab_char . 'text-align:' . $value['align'] . $_temp . ';' . $ln_char;
			}

			if ( isset( $block['important-attr'] ) && in_array( 'transform', $block['important-attr'] ) ) {
				$_temp = '!important';
			} else {
				$_temp = '';
			}

			if ( isset( $value['transform'] ) ) {
				$result['code'] .= $tab_char . 'text-transform:' . $value['transform'] . $_temp . ';' . $ln_char;
			}

			if ( isset( $block['important-attr'] ) && in_array( 'color', $block['important-attr'] ) ) {
				$_temp = '!important';
			} else {
				$_temp = '';
			}

			if ( isset( $value['color'] ) ) {
				$result['code'] .= $tab_char . 'color:' . $value['color'] . $_temp . ';' . $ln_char;
			}

			if ( isset( $block['important-attr'] ) && in_array( 'letter-spacing', $block['important-attr'] ) ) {
				$_temp = '!important';
			} else {
				$_temp = '';
			}

			if ( ! empty( $value['letter-spacing'] ) ) {
				$result['code'] .= $tab_char . 'letter-spacing:' . $value['letter-spacing'] . $_temp . ';' . $ln_char;
			}

			// Add Font To Fonts Queue
			$result['font'] = array(
				'family'  => $value['family'],
				'variant' => $value['variant'],
				'subset'  => $value['subset'],
			);
		}

		// prepare value for "background-image" type
		if ( isset( $block['type'] ) && $block['type'] == 'background-image' ) {

			if ( empty( $value['img'] ) ) {
				return array(
					'code' => ''
				);
			}

			// Full Cover Image
			if ( $value['type'] == 'cover' ) {
				$after_value .= $tab_char . 'background-repeat: no-repeat;background-position: center center; -webkit-background-size: cover; -moz-background-size: cover;-o-background-size: cover; background-size: cover;'
				                . 'filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' . $value['img'] . '\', sizingMethod=\'scale\');
-ms-filter: "progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' . $value['img'] . '\', sizingMethod=\'scale\')";'
				                . $ln_char;

				$value = 'url(' . $value['img'] . ')';
			} // Fit Cover
			elseif ( $value['type'] == 'fit-cover' ) {
				$after_value .= $tab_char . 'background-repeat: no-repeat;background-position: center center; -webkit-background-size: contain; -moz-background-size: contain;-o-background-size: contain; background-size: contain;'
				                . 'filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' . $value['img'] . '\', sizingMethod=\'scale\');
-ms-filter: "progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' . $value['img'] . '\', sizingMethod=\'scale\')";'
				                . $ln_char;

				$value = 'url(' . $value['img'] . ')';
			} // Parallax Image
			elseif ( $value['type'] == 'parallax' ) {
				$after_value .= $tab_char . 'background-repeat: no-repeat;background-attachment: fixed; background-position: center center; -webkit-background-size: cover; -moz-background-size: cover;-o-background-size: cover; background-size: cover;'
				                . 'filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' . $value['img'] . '\', sizingMethod=\'scale\');
-ms-filter: "progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' . $value['img'] . '\', sizingMethod=\'scale\')";'
				                . $ln_char;

				$value = 'url(' . $value['img'] . ')';
			} else {
				switch ( $value['type'] ) {

					case 'repeat':
					case 'cover':
					case 'repeat-y':
					case 'repeat-x':
						$after_value .= $tab_char . 'background-repeat:' . $value['type'] . ';' . $ln_char;
						break;

					case 'top-left':
						$after_value .= $tab_char . 'background-repeat: no-repeat;' . $ln_char;
						$after_value .= $tab_char . 'background-position: top left;' . $ln_char;
						break;

					case 'top-center':
						$after_value .= $tab_char . 'background-repeat: no-repeat;' . $ln_char;
						$after_value .= $tab_char . 'background-position: top center;' . $ln_char;
						break;

					case 'top-right':
						$after_value .= $tab_char . 'background-repeat: no-repeat;' . $ln_char;
						$after_value .= $tab_char . 'background-position: top right;' . $ln_char;
						break;

					case 'left-center':
						$after_value .= $tab_char . 'background-repeat: no-repeat;' . $ln_char;
						$after_value .= $tab_char . 'background-position: left center;' . $ln_char;
						break;

					case 'center-center':
						$after_value .= $tab_char . 'background-repeat: no-repeat;' . $ln_char;
						$after_value .= $tab_char . 'background-position: center center;' . $ln_char;
						break;

					case 'right-center':
						$after_value .= $tab_char . 'background-repeat: no-repeat;' . $ln_char;
						$after_value .= $tab_char . 'background-position: right center;' . $ln_char;
						break;

					case 'bottom-left':
						$after_value .= $tab_char . 'background-repeat: no-repeat;' . $ln_char;
						$after_value .= $tab_char . 'background-position: bottom left;' . $ln_char;
						break;

					case 'bottom-center':
						$after_value .= $tab_char . 'background-repeat: no-repeat;' . $ln_char;
						$after_value .= $tab_char . 'background-position: bottom center;' . $ln_char;
						break;

					case 'bottom-right':
						$after_value .= $tab_char . 'background-repeat: no-repeat;' . $ln_char;
						$after_value .= $tab_char . 'background-position: bottom right;' . $ln_char;
						break;

				}
				$value = 'url(' . $value['img'] . ')';
			}

		}

		// prepare value for "color" type
		if ( isset( $block['type'] ) && $block['type'] == 'color' ) {
			if ( preg_match( '/%%value([-|+]\d*)%%/', $block['value'], $change ) ) {
				Better_Framework::factory( 'color' );
				$value = preg_replace( '/(%%value[-|+]\d*%%)/', BF_Color::change_color( $value, intval( $change[1] ) ), $block['value'] );
			} elseif ( preg_match( '/%%value-opacity-(.*)%%/', $block['value'], $opacity ) ) {
				Better_Framework::factory( 'color' );
				$value = preg_replace( '/(%%value-opacity-.*%%)/', BF_Color::hex_to_rgba( $value, $opacity[1] ), $block['value'] );
			}
		}

		// prepare value for "border" type
		if ( isset( $block['type'] ) && $block['type'] == 'border' ) {

			if ( isset( $value['all'] ) ) {

				$result['code'] .= $tab_char . 'border:';

				if ( isset( $value['all']['width'] ) ) {
					$result['code'] .= $value['all']['width'] . 'px ';
				}
				if ( isset( $value['all']['style'] ) ) {
					$result['code'] .= $value['all']['style'] . ' ';
				}
				if ( isset( $value['all']['color'] ) ) {
					$result['code'] .= $value['all']['color'] . ' ';
				}

				$result['code'] .= ';' . $ln_char;

			} else {

				if ( isset( $value['top'] ) ) {

					$result['code'] .= $tab_char . 'border-top:';

					if ( isset( $value['top']['width'] ) ) {
						$result['code'] .= $value['top']['width'] . 'px ';
					}
					if ( isset( $value['top']['style'] ) ) {
						$result .= $value['top']['style'] . ' ';
					}
					if ( isset( $value['top']['color'] ) ) {
						$result['code'] .= $value['top']['color'] . ' ';
					}

					$result['code'] .= ';' . $ln_char;

				}

				if ( isset( $value['right'] ) ) {

					$result['code'] .= $tab_char . 'border-right:';

					if ( isset( $value['right']['width'] ) ) {
						$result['code'] .= $value['right']['width'] . 'px ';
					}
					if ( isset( $value['right']['style'] ) ) {
						$result['code'] .= $value['right']['style'] . ' ';
					}
					if ( isset( $value['right']['color'] ) ) {
						$result['code'] .= $value['right']['color'] . ' ';
					}

					$result['code'] .= ';' . $ln_char;

				}
				if ( isset( $value['bottom'] ) ) {

					$result['code'] .= $tab_char . 'border-bottom:';

					if ( isset( $value['bottom']['width'] ) ) {
						$result['code'] .= $value['bottom']['width'] . 'px ';
					}
					if ( isset( $value['bottom']['style'] ) ) {
						$result['code'] .= $value['bottom']['style'] . ' ';
					}
					if ( isset( $value['bottom']['color'] ) ) {
						$result['code'] .= $value['bottom']['color'] . ' ';
					}

					$result['code'] .= ';' . $ln_char;

				}

				if ( isset( $value['left'] ) ) {

					$result['code'] .= $tab_char . 'border-left:';

					if ( isset( $value['left']['width'] ) ) {
						$result['code'] .= $value['left']['width'] . 'px ';
					}
					if ( isset( $value['left']['style'] ) ) {
						$result['code'] .= $value['left']['style'] . ' ';
					}
					if ( isset( $value['left']['color'] ) ) {
						$result['code'] .= $value['left']['color'] . ' ';
					}

					$result['code'] .= ';' . $ln_char;

				}

			}

		}

		// Prepare Properties
		if ( isset( $block['prop'] ) ) {

			foreach ( (array) $block['prop'] as $key => $val ) {

				// Customized value template for property
				if ( strpos( $val, '%%value%%' ) !== false ) {

					$result['code'] .= $tab_char . $key . ':';
					$result['code'] .= str_replace( '%%value%%', $value, $val ) . ';' . $ln_char;

				} // Simply set value to property
				else {

					if ( ! is_int( $key ) ) {

						$result['code'] .= $tab_char . $key . ':' . $val . ';' . $ln_char;

					} elseif ( ! is_array( $value ) ) {

						$result['code'] .= $tab_char . $val . ':' . $value . ';' . $ln_char;

					}

				}
			}

		}

		// add after value
		if ( isset( $after_value ) && $after_value != '' ) {
			$result['code'] .= $after_value;
		}

		// Remove last ';'
		$result['code'] = rtrim( $result['code'], ';' );

		if ( isset( $block['selector'] ) ) {
			$result['code'] .= "}" . $ln_char;
		}

		// After css code. For example used for adding media queries!.
		if ( isset( $block['after'] ) && is_string( $value ) ) {
			$result['code'] .= str_replace( '%%value%%', $value, $block['after'] ) . $ln_char;
		}

		return $result;
	}
}

if ( ! function_exists( 'bf_starts_with' ) ) {
	/**
	 * Check string start with
	 *
	 * @param $haystack
	 * @param $needle
	 *
	 * @return bool
	 */
	function bf_starts_with( $haystack, $needle ) {

		return $needle === '' || strrpos( $haystack, $needle, - strlen( $haystack ) ) !== false;
	}
}

if ( ! function_exists( 'bf_ends_with' ) ) {

	/**
	 * Check string end with
	 *
	 * @param $haystack
	 * @param $needle
	 *
	 * @return bool
	 */
	function bf_ends_with( $haystack, $needle ) {

		return $needle === '' || ( ( $temp = strlen( $haystack ) - strlen( $needle ) ) >= 0 && strpos( $haystack, $needle, $temp ) !== false );
	}
}

if ( ! function_exists( 'bf_found_closest_number' ) ) {

	/**
	 * Find closest number in the array
	 *
	 * @param array  $array  Ascending sorted array
	 * @param int    $number number you are looking for
	 * @param string $round  up|down  round fractions up/down
	 *
	 * TODO: optimized it!
	 *
	 * @since 3.0.1
	 * @return void|int index of array on success
	 */
	function bf_found_closest_number( $array, $number, $round = 'up' ) {

		$pivot       = array_rand( $array );
		$status      = 0; // 1: increasing, 2: decreasing
		$found_pivot = null;


		while( isset( $array[ $pivot ] ) ) {

			if ( $array[ $pivot ] === $number ) {
				return $array[ $pivot ];
			}

			if ( $array[ $pivot ] > $number ) {

				if ( $status === 1 ) {
					$found_pivot = $pivot;
					break;
				}

				$pivot --;
				$status = 2;

			} else {

				$pivot ++;

				if ( $status === 2 ) {
					$found_pivot = $pivot;
					break;
				}

				$status = 1;
			}
		}

		if ( is_null( $found_pivot ) ) {

			$first = $array[ key( $array ) ];
			if ( $first > $number ) {

				if ( $round === 'up' ) {
					return $first;
				}

			} else {

				if ( $round === 'down' ) {

					return end( $array );
				}
			}
		}

		if ( ! is_null( $found_pivot ) ) {

			if ( $round === 'up' ) {
				return $array[ $found_pivot ];
			}

			return $array[ $found_pivot - 1 ];
		}
	}
}


if ( ! function_exists( 'bf_is_user_logged_in' ) ) {
	/**
	 * Performance optimized function to check current user login status
	 *
	 * @return bool
	 */
	function bf_is_user_logged_in() {

		static $logged_in;

		if ( is_null( $logged_in ) ) {
			$logged_in = is_user_logged_in();
		}

		return $logged_in;
	}
}


if ( ! function_exists( 'bf_is_amp' ) ) {
	/**
	 * Detects active AMP page & plugin
	 *
	 * @return bool
	 */
	function bf_is_amp() {

		static $is_amp;

		if ( ! is_null( $is_amp ) ) {
			return $is_amp;
		}

		// BetterAMP plugin
		if ( function_exists( 'is_better_amp' ) && is_better_amp() ) {
			$is_amp = 'better';
		} // Official AMP Plugin
		elseif ( function_exists( 'is_amp_endpoint' ) && is_amp_endpoint() ) {
			$is_amp = 'amp';
		} else {
			$is_amp = false;
		}

		return $is_amp;
	}
}


if ( ! function_exists( 'bf_is_fia' ) ) {
	/**
	 * Detects active Facebook Instant Article plugin
	 *
	 * @return bool
	 */
	function bf_is_fia() {

		static $state;

		if ( ! is_null( $state ) ) {
			return $state;
		}

		$state = defined( 'IA_PLUGIN_VERSION' ) && function_exists( 'is_transforming_instant_article' ) && is_transforming_instant_article();

		return $state;
	}
}

if ( ! function_exists( 'bf_the_content_by_id' ) ) {
	/**
	 * Prints content of post by the ID.
	 * It handles extra actions like custom CSS prints of blocks and page.
	 *
	 * @param null  $post_id
	 * @param array $args
	 *
	 * @return mixed|string|void
	 */
	function bf_the_content_by_id( $post_id = null, $args = array() ) {

		if ( ! $post_id ) {
			return;
		}

		$post_object = get_post( $post_id );
		$args        = bf_merge_args( $args, array(
			'echo'         => true,
			'context'      => '',
			'add_vs_style' => false,
		) );

		if ( ! $post_object ) {
			return;
		} else {
			$content = apply_filters( 'the_content', $post_object->post_content, $args['context'] );
			$content = do_shortcode( $content );
		}

		//
		// Add custom css of VC page
		//

		if ( apply_filters( 'better-framework/the-content/append-styles', $args['add_vs_style'], $post_object, $args ) ) {
			//
			// Post custom CSS
			//
			$post_custom_css = get_post_meta( $post_id, '_wpb_post_custom_css', true );
			if ( ! empty( $post_custom_css ) ) {
				$post_custom_css = strip_tags( $post_custom_css );
				$content         .= '<style type="text/css" data-type="vc_custom-css">';
				$content         .= $post_custom_css;
				$content         .= '</style>';
			}


			//
			// Post shortcodes CSS
			//
			$shortcodes_custom_css = get_post_meta( $post_id, '_wpb_shortcodes_custom_css', true );
			if ( ! empty( $shortcodes_custom_css ) ) {
				$shortcodes_custom_css = strip_tags( $shortcodes_custom_css );
				$content               .= '<style type="text/css" data-type="vc_shortcodes-custom-css">';
				$content               .= $shortcodes_custom_css;
				$content               .= '</style>';
			}
		}

		if ( $args['echo'] ) {
			echo $content;
		} else {
			return $content;
		}

	}
}

if ( ! function_exists( 'bf_bp_get_current_core_component' ) ) {

	/**
	 * Return current BuddyPress component ID
	 *
	 * @since 3.5.4
	 * @return string
	 */
	function bf_bp_get_current_core_component() {

		if ( ! function_exists( 'bp_core_get_packaged_component_ids' ) ||
		     ! function_exists( 'bp_is_current_component' )
		) {
			return '';
		}

		foreach ( bp_core_get_packaged_component_ids() as $active_component ) {

			if ( bp_is_current_component( $active_component ) ) {

				return $active_component;
			}
		}

		return '';
	}
}

if ( ! function_exists( 'bf_bp_get_component_page_id' ) ) {

	/**
	 * Get page ID of given BuddyPress component
	 *
	 * @param string      $component . optional. default:current component
	 *
	 * @global BuddyPress $bp        Main BuddyPress Class.
	 *
	 * @since 3.5.4
	 * @return int
	 */
	function bf_bp_get_component_page_id( $component = 'auto' ) {

		global $bp;

		if ( ! $bp || ! isset( $bp->pages ) ) {
			return 0;
		}

		if ( 'auto' === $component ) {
			$component = bf_bp_get_current_core_component();
		}

		if ( $component && isset( $bp->pages->$component->id ) ) {
			return $bp->pages->$component->id;
		}

		return 0;
	}
}

if ( ! function_exists( 'bf_file_system_instance' ) ) {

	/**
	 * Get WP FileSystem Object
	 *
	 * @global WP_Filesystem_Base $wp_filesystem WordPress Filesystem Class
	 *
	 * @since 3.9.1
	 * @return WP_Filesystem_Base
	 */
	function bf_file_system_instance() {

		global $wp_filesystem;

		if ( ! $wp_filesystem instanceof WP_Filesystem_Base ) {

			if ( ! function_exists( 'WP_Filesystem' ) ) {
				require_once ABSPATH . '/wp-admin/includes/file.php';
			}

			$credentials['hostname'] = defined( 'FTP_HOST' ) ? FTP_HOST : '';
			$credentials['username'] = defined( 'FTP_USER' ) ? FTP_USER : '';
			$credentials['password'] = defined( 'FTP_PASS' ) ? FTP_PASS : '';

			WP_Filesystem( $credentials, WP_CONTENT_DIR, false );
		}

		return $wp_filesystem;
	}
}

if ( ! function_exists( 'bf_is_block_render_request' ) ) {

	/**
	 * @return bool
	 */
	function bf_is_block_render_request() {

		return (bool) stristr( $_SERVER['REQUEST_URI'], '/block-renderer/better-studio/' );
	}
}


/**
 * Safe count function
 *
 * @since 3.9.3
 * @return integer
 */
function bf_count( $variable ) {

	// PHP > 7.1
	if ( function_exists( 'is_countable' ) && is_countable( $variable ) ) {
		return count( $variable );
	}

	// PHP < 7.2
	if ( is_array( $variable ) ) {
		return count( $variable );
	}

	return 0;
}

<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Used for adding fields for all WordPress widgets
 */
class BF_Widgets_General_Fields {


	/**
	 * Contain active general fields
	 *
	 * @var array
	 */
	var $fields = array();


	/**
	 * Contain current fields options
	 *
	 * @var array
	 */
	private $options = array();


	/**
	 * Contains list of all valid general field ID
	 *
	 * @var array
	 */
	static $valid_general_fields = array(

		// title Fields
		'bf-widget-bg-color',
		'bf-widget-title-color',
		'bf-widget-title-bg-color',
		'bs-text-color-scheme',
		'bf-widget-title-icon',
		'bf-widget-title-link',
		'bf-widget-title-style',

		// Responsive Fields
		'bf-widget-show-desktop',
		'bf-widget-show-tablet',
		'bf-widget-show-mobile',

		// Responsive Fields
		'bf-widget-custom-class',
		'bf-widget-custom-id',

	);


	/**
	 * Contains default value of general fields
	 *
	 * @var array
	 */
	static $default_values = array();


	function __construct() {

		// Load and prepare options only in backend for better performance
		if ( is_admin() ) {

			// Loads all active fields
			$this->fields = apply_filters( 'better-framework/widgets/options/general', $this->fields );

			// Prepare fields for generator
			$this->prepare_options();

			// Add input fields(priority 10, 3 parameters)
			add_action( 'in_widget_form', array( $this, 'in_widget_form' ), 5, 3 );

			// Callback function for options update (priority 5, 3 parameters)
			add_filter( 'widget_update_callback', array( $this, 'in_widget_form_update' ), 99, 2 );

		} else {

			add_filter( 'dynamic_sidebar_params', array( $this, 'dynamic_sidebar_params' ), 99, 2 );

		}

	}


	/**
	 * Check for when a field is general field
	 *
	 * @param $field
	 *
	 * @return bool
	 */
	public static function is_valid_field( $field ) {

		return in_array( $field, self::$valid_general_fields );

	}


	/**
	 * Returns list of all valid general fields
	 *
	 * @return array
	 */
	public static function get_general_fields() {

		return self::$valid_general_fields;
	}


	/**
	 * Get default value for general fields
	 *
	 * @param $field
	 *
	 * @return bool
	 */
	public static function get_default_value( $field ) {

		// Return default value from cache
		if ( isset( self::$default_values[ $field ] ) ) {
			return self::$default_values[ $field ];
		}

		$_default = '';

		switch ( $field ) {

			case 'bf-widget-show-desktop':
			case 'bf-widget-show-tablet':
			case 'bf-widget-show-mobile':
				$_default = 'show';

		}


		// Get field default value from filters
		self::$default_values[ $field ] = apply_filters( "better-framework/widgets/options/general/{$field}/default", $_default );

		return self::$default_values[ $field ];

	}


	/**
	 * Save active fields values
	 *
	 * @param $instance
	 * @param $new_instance
	 *
	 * @return mixed
	 */
	function in_widget_form_update( $instance, $new_instance ) {

		// Create default fields

		foreach ( $this->options as $option ) {
			if ( ! empty( $option['id'] ) && isset( $option['std'] ) ) {
				$def[ $option['id'] ] = $option['std'];
			}
		}

		// Save all valid general fields
		foreach ( $this->get_general_fields() as $field ) {
			if ( isset( $new_instance[ $field ] ) ) {
				if ( $new_instance[ $field ] != $def[ $field ] ) {
					$instance[ $field ] = $new_instance[ $field ];
				} else {
					unset( $new_instance[ $field ] );
					unset( $instance[ $field ] );
				}
			}
		}

		return $instance;
	}


	/**
	 * load options and prepare to admin form generation for active fields
	 */
	function prepare_options() {

		$color_fields['group-1'] = array(
			'name'  => __( 'Color Options', 'better-studio' ),
			'type'  => 'group',
			'id'    => 'group-1',
			// Keep Widget Group State After Widget Settings Saved
			'state' => isset( $_POST['_group_status']['group-1'] ) ? $_POST['_group_status']['group-1'] : 'close',
		);

		$title_fields['group-2'] = array(
			'name'  => __( 'Title Options', 'better-studio' ),
			'type'  => 'group',
			'id'    => 'group-2',
			// Keep Widget Group State After Widget Settings Saved
			'state' => isset( $_POST['_group_status']['group-2'] ) ? $_POST['_group_status']['group-2'] : 'close',
		);

		$responsive_fields['group-3'] = array(
			'name'  => __( 'Responsive Options', 'better-studio' ),
			'type'  => 'group',
			'id'    => 'group-3',
			// Keep Widget Group State After Widget Settings Saved
			'state' => isset( $_POST['_group_status']['group-3'] ) ? $_POST['_group_status']['group-3'] : 'close',
		);

		$advanced_fields['group-4'] = array(
			'name'  => __( 'Advanced Options', 'better-studio' ),
			'type'  => 'group',
			'id'    => 'group-4',
			// Keep Widget Group State After Widget Settings Saved
			'state' => isset( $_POST['_group_status']['group-4'] ) ? $_POST['_group_status']['group-4'] : 'close',
		);


		// Iterate all fields to find active fields
		foreach ( (array) $this->fields as $field_id => $field ) {

			// detect advanced fields category
			if ( self::is_valid_field( $field ) ) {

				// Color Fields
				$raw_field = $this->register_color_option( $field );

				if ( $raw_field != false ) {
					$color_fields[] = $raw_field;
					continue;
				}

				// Advanced Fields
				$raw_field = $this->register_title_option( $field );

				if ( $raw_field != false ) {
					$title_fields[] = $raw_field;
					continue;
				}

				// Responsive Fields
				$raw_field = $this->register_responsive_option( $field );

				if ( $raw_field != false ) {
					$responsive_fields[] = $raw_field;
					continue;
				}

				// Responsive Fields
				$raw_field = $this->register_advanced_option( $field );

				if ( $raw_field != false ) {
					$advanced_fields[] = $raw_field;
					continue;
				}

			}

		}

		// Add advanced fields to main fields
		if ( bf_count( $title_fields ) > 1 ) {
			// Fix group title for 1 field
			if ( bf_count( $title_fields ) == 2 ) {
				$title_fields['group-2']['name'] = $title_fields[0]['name'];
				$title_fields[0]['name']         = '';
			}

			$this->options = array_merge( $this->options, $title_fields );
		}

		// Add color fields to main fields
		if ( bf_count( $color_fields ) > 1 ) {
			// Fix group title for 1 field
			if ( bf_count( $color_fields ) == 2 ) {
				$color_fields['group-1']['name'] = $color_fields[0]['name'];
				$color_fields[0]['name']         = '';
			}

			$this->options = array_merge( $this->options, $color_fields );
		}

		// Add responsive fields to main fields
		if ( bf_count( $responsive_fields ) > 1 ) {
			// Fix group title for 1 field
			if ( bf_count( $responsive_fields ) == 2 ) {
				$responsive_fields['group-3']['name'] = $responsive_fields[0]['name'];
				$responsive_fields[0]['name']         = '';
			}

			$this->options = array_merge( $this->options, $responsive_fields );
		}

		// Add advanced fields to main fields
		if ( bf_count( $advanced_fields ) > 1 ) {
			// Fix group title for 1 field
			if ( bf_count( $advanced_fields ) == 2 ) {
				$advanced_fields['group-3']['name'] = $advanced_fields[0]['name'];
				$advanced_fields[0]['name']         = '';
			}

			$this->options = array_merge( $this->options, $advanced_fields );
		}

	}


	/**
	 * Init a general field generator options
	 *
	 * @param $field
	 *
	 * @return array|bool
	 */
	private function register_color_option( $field ) {

		switch ( $field ) {

			case 'bf-widget-title-color':
				return array(
					'name' => __( 'Widget Title Text Color', 'better-studio' ),
					'id'   => $field,
					'type' => 'color',
					'std'  => $this->get_default_value( $field ),
				);
				break;

			case 'bf-widget-title-bg-color':
				return array(
					'name' => __( 'Widget Title Background Color', 'better-studio' ),
					'id'   => $field,
					'type' => 'color',
					'std'  => $this->get_default_value( $field ),
				);
				break;

			case 'bf-widget-bg-color':
				return array(
					'name' => __( 'Widget Background Color', 'better-studio' ),
					'id'   => $field,
					'type' => 'color',
					'std'  => $this->get_default_value( $field ),
				);
				break;

			case 'bs-text-color-scheme':
				return array(
					'name'    => __( 'Widget Text Color Scheme', 'better-studio' ),
					'id'      => $field,
					'type'    => 'select',
					'std'     => $this->get_default_value( $field ),
					'options' => array(
						''      => __( '-- Default --', 'better-studio' ),
						'light' => __( 'White Color Texts', 'better-studio' ),
					),
				);
				break;

		}

		return false;
	}


	/**
	 * Init a general field generator options
	 *
	 * @param $field
	 *
	 * @return array|bool
	 */
	private function register_title_option( $field ) {

		switch ( $field ) {

			case 'bf-widget-title-icon':
				return array(
					'name' => __( 'Widget Title Icon', 'better-studio' ),
					'id'   => $field,
					'type' => 'icon_select',
					'std'  => $this->get_default_value( $field ),
				);
				break;

			case 'bf-widget-title-link':
				return array(
					'name' => __( 'Widget Title Link', 'better-studio' ),
					'id'   => $field,
					'type' => 'text',
					'std'  => $this->get_default_value( $field ),
					'ltr'  => true,
				);
				break;

			case 'bf-widget-title-style':
				return array(
					'name'             => __( 'Widget Title Style', 'better-studio' ),
					'id'               => $field,
					'type'             => 'select_popup',
					'std'              => 'default',
					'deferred-options' => array(
						'callback' => $this->get_default_value( $field ),
						'args'     => array(
							true
						),
					),
					'column_class'     => 'one-column',
				);
				break;

		}

		return false;
	}


	/**
	 * Init a general field generator options
	 *
	 * @param $field
	 *
	 * @return array|bool
	 */
	private function register_responsive_option( $field ) {

		switch ( $field ) {

			case 'bf-widget-show-desktop':
				return array(
					'name'    => __( 'Show On Desktop', 'better-studio' ),
					'id'      => $field,
					'type'    => 'select',
					'std'     => $this->get_default_value( $field ),
					'options' => array(
						'show' => __( 'Show', 'better-studio' ),
						'hide' => __( 'Hide', 'better-studio' ),
					),
				);
				break;

			case 'bf-widget-show-tablet':
				return array(
					'name'    => __( 'Show On Tablet', 'better-studio' ),
					'id'      => $field,
					'type'    => 'select',
					'std'     => $this->get_default_value( $field ),
					'options' => array(
						'show' => __( 'Show', 'better-studio' ),
						'hide' => __( 'Hide', 'better-studio' ),
					),
				);
				break;

			case 'bf-widget-show-mobile':
				return array(
					'name'    => __( 'Show On Mobile', 'better-studio' ),
					'id'      => $field,
					'type'    => 'select',
					'std'     => $this->get_default_value( $field ),
					'options' => array(
						'show' => __( 'Show', 'better-studio' ),
						'hide' => __( 'Hide', 'better-studio' ),
					),
				);
				break;

		}

		return false;
	}


	/**
	 * Init a advanced fields
	 *
	 * @param $field
	 *
	 * @return array|bool
	 */
	private function register_advanced_option( $field ) {

		switch ( $field ) {

			case 'bf-widget-custom-class':
				return array(
					'name' => __( 'Custom CSS Class', 'better-studio' ),
					'id'   => $field,
					'type' => 'text',
					'std'  => $this->get_default_value( $field ),
				);
				break;

			case 'bf-widget-custom-id':
				return array(
					'name' => __( 'Custom ID', 'better-studio' ),
					'id'   => $field,
					'type' => 'text',
					'std'  => $this->get_default_value( $field ),
				);
				break;

		}

		return false;
	}


	/**
	 * @param $widget WP_Widget
	 */
	function prepare_fields( $widget ) {

		for ( $i = 0; $i < bf_count( $this->options ); $i ++ ) {

			if ( isset( $this->options[ $i ]['attr_id'] ) ) { //  Backward compatibility
				$this->options[ $i ]['id'] = $this->options[ $i ]['attr_id'];
			}

			// do not do anything on fields that haven't ID, ex: group fields
			if ( ! isset( $this->options[ $i ]['id'] ) ) {
				continue;
			}

			$this->options[ $i ]['input_name'] = $widget->get_field_name( $this->options[ $i ]['id'] );

			if ( $this->options[ $i ]['type'] == 'repeater' ) {

				for ( $j = 0; $j < bf_count( $this->options[ $i ]['options'] ); $j ++ ) {

					$this->options[ $i ]['options'][ $j ]['input_name'] = $this->options[ $i ]['input_name'] . '[%d][' . $this->options[ $i ]['options'][ $j ]['id'] . ']';

				}

			} elseif ( $this->options[ $i ]['type'] == 'select' && ! empty( $this->options[ $i ]['multiple'] ) && $this->options[ $i ]['multiple'] ) {
				$this->options[ $i ]['input_name'] .= '[]';
			}

		}

	}


	/**
	 * Add input fields to widget form
	 *
	 * @param $t
	 * @param $return
	 * @param $instance
	 */
	function in_widget_form( $t, $return, $instance ) {

		Better_Framework::factory( 'widgets-field-generator', false, true );

		$this->prepare_fields( $t );

		// Return if there is no general field
		if ( bf_count( $this->options ) <= 0 ) {
			return;
		}

		// Prepare generator config file
		$options = array(
			'fields' => $this->options
		);

		// Create generator instance
		$generator = new BF_Widgets_Field_Generator( $options, $instance );

		echo $generator->get_fields(); // escaped before inside generator

	}


	/**
	 * Callback: Used to change sidebar params to add general fields
	 *
	 * Filter: dynamic_sidebar_params
	 *
	 * @param $params
	 *
	 * @return mixed
	 */
	public function dynamic_sidebar_params( $params ) {

		global $wp_registered_widgets;

		$id = $params[0]['widget_id']; // Current widget ID

		if ( isset( $wp_registered_widgets[ $id ]['callback'][0] ) && is_object( $wp_registered_widgets[ $id ]['callback'][0] ) ) {

			$custom_class = array();

			// Get settings for all widgets of this type
			$settings = $wp_registered_widgets[ $id ]['callback'][0]->get_settings();

			// Get settings for this instance of the widget
			$setting_key = substr( $id, strrpos( $id, '-' ) + 1 );
			$instance    = isset( $settings[ $setting_key ] ) ? $settings[ $setting_key ] : array();

			// Add custom link to widget title
			if ( ! empty( $instance['bf-widget-title-link'] ) ) {
				$params[0]['before_title'] .= "<a href='{$instance['bf-widget-title-link']}'>";
				$params[0]['after_title']  = "</a>" . $params[0]['after_title'];
			}

			// Append custom css class
			if ( ! empty( $instance['bf-widget-custom-class'] ) ) {
				$custom_class[] = sanitize_html_class( $instance['bf-widget-custom-class'] );
			}

			// Add icon before widget title
			if ( ! empty( $instance['bf-widget-title-icon'] ) ) {

				if ( is_array( $instance['bf-widget-title-icon'] ) && $instance['bf-widget-title-icon']['icon'] != '' ) {
					$params[0]['before_title'] .= bf_get_icon_tag( $instance['bf-widget-title-icon'] ) . ' ';
					$custom_class[]            = 'h-i'; // Have Icon
				} elseif ( is_string( $instance['bf-widget-title-icon'] ) ) {
					$params[0]['before_title'] .= bf_get_icon_tag( $instance['bf-widget-title-icon'] ) . ' ';
					$custom_class[]            = 'h-i'; // Have Icon
				} else {
					$custom_class[] = 'h-ni'; // Have Not Icon
				}

			} else {
				$custom_class[] = 'h-ni'; // Have Not Icon
			}

			// Add class for bg color
			if ( ! empty( $instance['bf-widget-bg-color'] ) ) {
				$custom_class[] = 'w-bg'; // Wdiegt BG Color
				$custom_class[] = 'w-bg-' . sanitize_html_class( $instance['bf-widget-bg-color'] );
			}

			// Add class for title color
			if ( ! empty( $instance['bf-widget-title-color'] ) ) {
				$custom_class[] = 'h-c'; // Heading Color
				$custom_class[] = 'h-c-' . sanitize_html_class( $instance['bf-widget-title-color'] );
			}

			// Add class for title bg color
			if ( ! empty( $instance['bf-widget-title-bg-color'] ) ) {
				$custom_class[] = 'h-bg'; // Heading BG
				$custom_class[] = 'h-bg-' . sanitize_html_class( $instance['bf-widget-title-bg-color'] );
			}

			// Show on desktop
			if ( ! empty( $instance['bf-widget-show-desktop'] ) ) {
				if ( $instance['bf-widget-show-desktop'] == 'hide' ) {
					$custom_class[] = 'bs-hidden-lg';
					$custom_class[] = 'bs-hidden-md';
				}
			}

			// Show on tablet
			if ( ! empty( $instance['bf-widget-show-tablet'] ) ) {
				if ( $instance['bf-widget-show-tablet'] == 'hide' ) {
					$custom_class[] = 'bs-hidden-sm';
				}
			}

			// Show on mobile
			if ( ! empty( $instance['bf-widget-show-mobile'] ) ) {
				if ( $instance['bf-widget-show-mobile'] == 'hide' ) {
					$custom_class[] = 'bs-hidden-xs';
				}
			}

			// add title classes
			if ( ! empty( $instance['title'] ) ) {
				$custom_class[] = 'w-t'; // Have Title
			} else {
				$custom_class[] = 'w-nt'; // Have No Title
			}

			// Prepare custom classes
			$class_to_add = 'class=" ' . implode( ' ', $custom_class ) . ' '; // Make sure you leave a space at the end

			// Add classes
			$params[0]['before_widget'] = str_replace(
				'class="',
				$class_to_add,
				$params[0]['before_widget']
			);


			// Change id to custom ID
			if ( ! empty( $instance['bf-widget-custom-id'] ) ) {

				$params[0]['before_widget'] = str_replace(
					' id="' . $params[0]['widget_id'] . '"',
					' id="' . sanitize_html_class( $instance['bf-widget-custom-id'] ) . '"',
					$params[0]['before_widget']
				);
			}
		}

		return $params;
	}
}<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Base class for widgets
 */
class BF_Widget extends WP_Widget {


	/**
	 * Widget Position in wp-admin/widgets.php
	 *
	 * @var int
	 */
	var $position = 30;

	/**
	 * $default values for widget fields
	 *
	 * @var array
	 */
	var $defaults = array();


	/**
	 * Flag to load default only one time
	 *
	 * @var bool
	 */
	var $defaults_loaded = false;


	/**
	 * Contains shortcode id of widget
	 *
	 * @var string
	 */
	var $base_widget_id;


	/**
	 * Contain all fields of widget
	 *
	 * @var array
	 */
	var $fields = array();


	/**
	 * Show widget title
	 *
	 * @var bool
	 */
	var $with_title = true;


	/**
	 * Register widget with WordPress.
	 *
	 * @param string $shortcode_id
	 * @param string $title
	 * @param array  $desc
	 * @param bool   $widget_id
	 */
	function __construct( $shortcode_id = '', $title = '', $desc = array(), $widget_id = false ) {

		if ( empty( $shortcode_id ) ) {
			return;
		}


		$this->base_widget_id = $shortcode_id;

		if ( $widget_id != false ) {
			parent::__construct(
				$widget_id,
				$title,
				$desc
			);
		} else {
			parent::__construct(
				$shortcode_id,
				$title,
				$desc
			);
		}

	}


	/**
	 * Loads widget -> shortcode default attrs
	 */
	public function load_defaults() {

		if ( $this->defaults_loaded ) {
			return;
		}

		$this->defaults_loaded = true;
		$this->defaults        = BF_Shortcodes_Manager::factory( $this->base_widget_id, array(), true )->defaults;
	}


	/**
	 * Loads fields
	 */
	public function load_fields() {
	}


	/**
	 * Prepare fields for field generator
	 */
	function prepare_fields() {

		for ( $i = 0; $i < bf_count( $this->fields ); $i ++ ) {

			if ( isset( $this->fields[ $i ]['attr_id'] ) ) { //  Backward compatibility
				$this->fields[ $i ]['id'] = $this->fields[ $i ]['attr_id'];
			}
			// do not do anything on fields that haven't ID, ex: group fields
			if ( ! isset( $this->fields[ $i ]['id'] ) ) {
				continue;
			}

			$this->fields[ $i ]['input_name'] = $this->get_field_name( $this->fields[ $i ]['id'] );

			// TODO: check this
			// $this->fields[ $i ]['id'] = $this->get_field_id( $this->fields[ $i ]['id'] );


			if ( $this->fields[ $i ]['type'] == 'repeater' ) {

				foreach ( $this->fields[ $i ]['options'] as $_id => $_item ) {

					$this->fields[ $i ]['options'][ $_id ]['input_name'] = $this->fields[ $i ]['input_name'] . '[%d][' . $_item['id'] . ']';
				}

			} elseif ( $this->fields[ $i ]['type'] == 'select' && ! empty( $this->fields[ $i ]['multiple'] ) && $this->fields[ $i ]['multiple'] ) {
				$this->fields[ $i ]['input_name'] .= '[]';
			}
		}
	}


	/**
	 * Merge two arrays to one, if $atts key not defined or is empty then $default value will be set.
	 *
	 * @param $default
	 * @param $atts
	 *
	 * @return mixed
	 */
	function parse_args( $default, $atts ) {

		foreach ( (array) $default as $key => $value ) {

			// empty fields in $atts is ok!
			if ( ! isset( $atts[ $key ] ) ) {
				$atts[ $key ] = $value;
			}

		}

		$atts['shortcode-id'] = $this->base_widget_id; // adds shortcode id to atts for using it inside filters

		return $atts;
	}


	/**
	 * Front-end display of widget.
	 *
	 * @see BetterWidget::widget()
	 * @see WP_Widget::widget()
	 *
	 * @param array $args     Widget arguments.
	 * @param array $instance Saved values from database.
	 */
	public function widget( $args, $instance ) {

		$this->load_defaults();
		$instance = $this->parse_args( $this->defaults, $instance );

		echo $args['before_widget'];  // escaped before inside WP

		$title = apply_filters( 'widget_title', empty( $instance['title'] ) ? '' : $instance['title'], $instance, $this->base_widget_id );
		if ( ! empty( $title ) && $this->with_title ) {
			echo $args['before_title'] . $title . $args['after_title']; // escaped before inside WP
		}

		echo BF_Shortcodes_Manager::factory( $this->base_widget_id )->handle_widget( $instance ); // escaped before inside WP

		echo $args['after_widget']; // escaped before inside WP
	}


	/**
	 * Sanitize widget form values as they are saved.
	 *
	 * @see WP_Widget::update()
	 *
	 * @param array $new_instance Values just sent to be saved.
	 * @param array $old_instance Previously saved values from database.
	 *
	 * @return array Updated safe values to be saved.
	 */
	public function update( $new_instance, $old_instance ) {

		$this->load_defaults();

		return $this->parse_args( $this->defaults, $new_instance );
	}


	/**
	 * Back-end widget form.
	 *
	 * @see WP_Widget::form()
	 *
	 * @param array $instance Previously saved values from database.
	 *
	 * @return string|void
	 */
	public function form( $instance ) {

		$this->load_defaults();
		$instance = $this->parse_args( $this->defaults, $instance );

		Better_Framework::factory( 'widgets-field-generator', false, true );

		// prepare fields for generator
		$this->load_fields();
		$this->prepare_fields();
		$options = array(
			'fields' => $this->fields
		);

		/**
		 * Keep Widget Group State After Widget Settings Saved
		 */
		if ( ! empty( $_POST['_group_status'] ) ) {
			foreach ( $options['fields'] as $idx => $field ) {
				if ( $field['type'] === 'group' && ! empty( $field['id'] ) ) {
					$id = &$field['id'];

					if ( ! empty( $_POST['_group_status'][ $id ] ) ) {
						$options['fields'][ $idx ]['state'] = $_POST['_group_status'][ $id ];
					}
				}
			}
		}

		$generator = new BF_Widgets_Field_Generator( $options, $instance );

		echo $generator->get_fields(); // escaped before
	}


	public function get_fields() {

		return $this->fields;
	}
}
<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Class BF_Widgets_Field_Generator
 */
class BF_Widgets_Field_Generator extends BF_Admin_Fields {


	/**
	 * Constructor Function
	 *
	 * @param array $items  Panel All Options
	 * @param array $values Panel ID
	 *
	 * @since  1.0
	 * @access public
	 * @return \BF_Widgets_Field_Generator
	 */
	public function __construct( array $items, $values = array() ) {

		$default_options = array(
			'templates_dir' => BF_PATH . 'widget/templates/',
		);
		$items           = array_merge( $default_options, $items );

		foreach ( $items['fields'] as $idx => $field ) {

			if ( isset( $field['id'] ) ) {
				$items['fields'][ $idx ]['id'] = $field['id'];
			}
		}

		// Parent Constructor
		parent::__construct( $items );

		$this->items  = $items;
		$this->values = $values;
	}


	/**
	 * Display HTML output of one field
	 *
	 * @param $field
	 *
	 * @return string
	 */
	public function get_field( $field ) {

		$field['value'] = isset( $this->values[ $field['id'] ] ) ? $this->values[ $field['id'] ] : null;
		if ( is_null( $field['value'] ) && isset( $field['std'] ) && $field['type'] != 'repeater' ) {
			$field['value'] = $field['std'];
		}

		if ( ! in_array( $field['type'], $this->supported_fields ) ) {
			return '';
		}

		if ( $field['type'] == 'repeater' ) {
			$field['widget_field'] = true;
		}

		// filter field
		if ( isset( $field['filter-field'] ) && $field['filter-field-value'] ) {

			// filter field value
			$filter_field_value = isset( $this->values[ $field['filter-field'] ] ) ? $this->values[ $field['filter-field'] ] : null;
			if ( is_null( $filter_field_value ) ) {

				foreach ( $this->items['fields'] as $_field ) {

					if ( $_field == $field['filter-field'] ) {

						if ( isset( $_field['std'] ) && $_field['type'] != 'repeater' ) {

							$filter_field_value = $_field['std'];

						}

					}

				}

			}

			if ( $field['filter-field-value'] !== $filter_field_value ) {

				$field['section-css']['display'] = "none";

			}

		}

		return $this->section(
			call_user_func(
				array( $this, $field['type'] ),
				$field
			),
			$field
		);

	}


	/**
	 * Display HTML output of widget fields array
	 *
	 * @since  1.0
	 * @access public
	 * @return string
	 */
	public function get_fields() {

		$output = '';

		// Flag for detecting Groups
		$group_counter = 0;

		foreach ( $this->items['fields'] as $field ) {

			if ( $field['type'] == 'group_close' ) {

				// close tag for latest group in tab
				if ( $group_counter != 0 ) {
					$group_counter = 0;
					$output        .= $this->get_fields_group_close( $field );
				}
				continue;
			}

			if ( $field['type'] == 'group' ) {

				// close tag for latest group in tab
				if ( $group_counter != 0 ) {
					$group_counter = 0;
					$output        .= $this->get_fields_group_close( $field );
				}

				if ( isset( $field['container-class'] ) ) {
					$field['container-class'] .= ' bf-widgets';
				} else {
					$field['container-class'] = 'bf-widgets';
				}

				$output .= $this->get_fields_group_start( $field );

				$group_counter ++;

			} else {

				$output .= $this->get_field( $field );

			}

		}

		// close tag for latest group
		if ( $group_counter != 0 ) {
			$output .= $this->get_fields_group_close();
		}

		return $output;
	}

}
<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Manager for base and public functionality related to Widgets and dynamic sidebars
 */
class BF_Widgets_Manager {

	/**
	 * Contain current showed dynamic sidebar location id
	 *
	 * @var string
	 */
	public static $current_sidebar = '';


	/**
	 * Contain top-bar sidebars locations
	 *
	 * @var array
	 */
	public static $top_bar_sidebars = array();


	/**
	 * Contain footer sidebars locations
	 *
	 * @var array
	 */
	public static $footer_sidebars = array();


	function __construct() {

		$this->load_special_sidebars();

		$this->load_widgets_general_fields();

		add_action( 'dynamic_sidebar_before', array( 'BF_Widgets_Manager', 'dynamic_sidebar_before' ) );
		add_action( 'dynamic_sidebar_after', array( 'BF_Widgets_Manager', 'dynamic_sidebar_after' ) );

		add_filter( 'widget_title', array( $this, 'widget_title_filter' ), 99 );
		add_filter( 'in_widget_form', array( $this, 'append_position_field' ), 20, 4 );
	}


	/**
	 * This filter used for delete widgets title on special sidebar locations
	 *
	 * @param $title
	 *
	 * @return string
	 */
	function widget_title_filter( $title ) {

		if ( self::is_special_sidebar() ) {
			$title = '';
		}

		return $title;
	}


	/**
	 * Filter special sidebars
	 */
	function load_special_sidebars() {

		self::$top_bar_sidebars = apply_filters( 'better-framework/sidebars/locations/top-bar', array() );

		self::$footer_sidebars = apply_filters( 'better-framework/sidebars/locations/footer-bar', array() );

	}


	/**
	 * Init general fields for all WordPress widgets
	 */
	function load_widgets_general_fields() {

		require_once BF_PATH . 'widget/class-bf-widgets-general-fields.php';

		new BF_Widgets_General_Fields();

	}


	public function append_position_field( $instance ) {

		if ( property_exists( $instance, 'position' ) ) {
			$position = $instance->position;
		} else {
			$position = apply_filters( 'better-framework/widget/default-position', 30, $instance );
		}

		$position = apply_filters( 'better-framework/widget/position', $position, $instance );

		printf( '<input type="hidden"  value="%d" class="bf-widget-position">', $position );
	}


	/**
	 * Fires before widgets are rendered in a dynamic sidebar.
	 *
	 * @param $index
	 */
	public static function dynamic_sidebar_before( $index ) {

		self::$current_sidebar = $index;

	}


	/**
	 * Fires after widgets are rendered in a dynamic sidebar.
	 *
	 * @param $index
	 */
	public static function dynamic_sidebar_after( $index ) {

		self::$current_sidebar = '';

	}


	/**
	 * Used For retrieving current sidebar
	 *
	 */
	public static function get_current_sidebar() {

		return self::$current_sidebar;

	}


	/**
	 * Load widget for shortcode
	 *
	 * @param string $id
	 * @param array  $options
	 */
	public static function register_widget_for_shortcode( $id = '', $options = array() ) {

		// custom class for widget. 3rd party shortcode widget that is outside of BF
		if ( isset( $options['widget_class'] ) && class_exists( $options['widget_class'] ) && is_subclass_of( $options['widget_class'], 'WP_Widget' ) ) {

			$class = $options['widget_class'];

			register_widget( $class );

		} else {

			$class = bf_convert_string_to_class_name( $id, 'BF_', '_Widget' );

			if ( ! class_exists( $class ) ) {

				if ( file_exists( BF_PATH . 'widget/widgets/class-bf-' . $id . '-widget.php' ) ) {

					require_once BF_PATH . 'widget/widgets/class-bf-' . $id . '-widget.php';

					register_widget( $class );

				}

			}
		}

	}


	/**
	 * Determine current showing sidebar is a top bar sidebar!
	 */
	public static function is_top_bar_sidebar() {

		return in_array( self::$current_sidebar, self::$top_bar_sidebars );

	}


	/**
	 * Determine current showing sidebar is a footer sidebar!
	 */
	public static function is_footer_sidebar() {

		return in_array( self::$current_sidebar, self::$footer_sidebars );

	}


	/**
	 * Determine current showing sidebar is a special sidebar!
	 */
	public static function is_special_sidebar() {

		if ( self::is_top_bar_sidebar() || self::is_footer_sidebar() ) {
			return true;
		}

		return false;

	}

}<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


$classes = $this->get_classes( $options );
$iri     = isset( $options['repeater_item'] ) && $options['repeater_item'] == true; // Is this section for a repeater item

$section_classes   = $classes['section'] . ' bf-widget-field-section';
$container_classes = $classes['container'];

$heading_classes  = $classes['heading'] . ' bf-heading';
$controls_classes = $classes['controls'] . ' bf-control not-prepared';
$explain_classes  = $classes['explain'] . ' bf-desc';

if ( $iri ) {

	$section_classes  .= ' ' . $classes['repeater-section'];
	$heading_classes  .= ' ' . $classes['repeater-heading'];
	$controls_classes .= ' ' . $classes['repeater-controls'];
	$explain_classes  .= ' ' . $classes['repeater-explain'];

} else {

	$section_classes  .= ' ' . $classes['nonrepeater-section'];
	$heading_classes  .= ' ' . $classes['nonrepeater-heading'];
	$controls_classes .= ' ' . $classes['nonrepeater-controls'];
	$explain_classes  .= ' ' . $classes['nonrepeater-explain'];

}

$section_classes  .= ' ' . $classes['section-class-by-filed-type'];
$heading_classes  .= ' ' . $classes['heading-class-by-filed-type'];
$controls_classes .= ' ' . $classes['controls-class-by-filed-type'];
$explain_classes  .= ' ' . $classes['explain-class-by-filed-type'];

$section_css_attr = $this->get_section_css_attr( $options );
$section_attr     = $this->get_section_filter_attr( $options );

?>
<div
		class="<?php echo esc_attr( $container_classes ); ?> bf-section-container bf-widgets bf-clearfix" <?php echo $section_css_attr; // escaped before ?> <?php echo $section_attr; // escaped before ?>>
	<div class="<?php echo esc_attr( $section_classes ); ?> bf-clearfix"
	     data-id="<?php echo esc_attr( $options['id'] ); ?>">

		<div class="<?php echo esc_attr( $heading_classes ); ?> bf-clearfix">
			<h4><label><?php echo esc_html( $options['name'] ); ?></label></h4>
		</div>

		<div class="<?php echo esc_attr( $controls_classes ); ?> bf-clearfix">
			<?php echo $input; // escaped before ?>
		</div>

		<?php if ( ! empty( $options['desc'] ) ) { ?>
			<div
					class="<?php echo esc_attr( $explain_classes ); ?> bf-clearfix"><?php echo wp_kses( $options['desc'], bf_trans_allowed_html() ); ?></div>
		<?php } ?>

	</div>
</div><?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

?>
<div class="bf-section-container bf-clearfix">
	<div class="bf-section-hr bf-clearfix">
		<?php echo $input; // escaped before ?>
	</div>
</div><?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


$classes = $this->get_classes( $options );
$iri     = isset( $options['repeater_item'] ) && $options['repeater_item'] == true; // Is this section for a repeater item

$section_classes = $classes['section'] . ' bf-widget-field-section';

$heading_classes  = $classes['heading'] . ' bf-heading';
$controls_classes = $classes['controls'] . ' bf-control not-prepared';
$explain_classes  = $classes['explain'] . ' bf-desc';

if ( $iri ) {

	$section_classes  .= ' ' . $classes['repeater-section'];
	$heading_classes  .= ' ' . $classes['repeater-heading'];
	$controls_classes .= ' ' . $classes['repeater-controls'];
	$explain_classes  .= ' ' . $classes['repeater-explain'];

} else {

	$section_classes  .= ' ' . $classes['nonrepeater-section'];
	$heading_classes  .= ' ' . $classes['nonrepeater-heading'];
	$controls_classes .= ' ' . $classes['nonrepeater-controls'];
	$explain_classes  .= ' ' . $classes['nonrepeater-explain'];

}

$section_classes  .= ' ' . $classes['section-class-by-filed-type'];
$heading_classes  .= ' ' . $classes['heading-class-by-filed-type'];
$controls_classes .= ' ' . $classes['controls-class-by-filed-type'];
$explain_classes  .= ' ' . $classes['explain-class-by-filed-type'];


if ( ! isset( $options['info-type'] ) ) {
	$options['info-type'] = 'info';
}

if ( ! isset( $options['state'] ) ) {
	$options['state'] = 'open';
}

?>
<div class="bf-section-container bf-widgets bf-clearfix">
	<div
			class="bf-section-info <?php echo esc_attr( $options['info-type'] ); ?> <?php echo esc_attr( $options['state'] ); ?> bf-clearfix">
		<div class="bf-section-info-title bf-clearfix">
			<h3><?php

				switch ( $options['info-type'] ) {

					case 'help':
						echo '<i class="fa fa-support"></i> ';
						break;

					case 'info':
						echo '<i class="fa fa-info"></i> ';
						break;

					case 'warning':
						echo '<i class="fa fa-warning"></i> ';
						break;

					case 'danger':
						echo '<i class="fa fa-exclamation"></i> ';
						break;

					default:
						echo '<i class="fa fa-info"></i> ';
						break;


				}

				echo esc_html( $options['name'] ); ?></h3>
		</div>
		<div class="<?php echo esc_attr( $controls_classes ); ?>  bf-clearfix">
			<?php echo $input; // escaped before ?>
		</div>
	</div>
</div><?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


$classes = $this->get_classes( $options );
$iri     = isset( $options['repeater_item'] ) && $options['repeater_item'] == true; // Is this section for a repeater item

$section_classes = $classes['section'] . ' bf-widget-field-section';

$heading_classes  = $classes['heading'] . ' bf-heading';
$controls_classes = $classes['controls'] . ' bf-control not-prepared';
$explain_classes  = $classes['explain'] . ' bf-desc';

if ( $iri ) {

	$section_classes  .= ' ' . $classes['repeater-section'];
	$heading_classes  .= ' ' . $classes['repeater-heading'];
	$controls_classes .= ' ' . $classes['repeater-controls'];
	$explain_classes  .= ' ' . $classes['repeater-explain'];

} else {

	$section_classes  .= ' ' . $classes['nonrepeater-section'];
	$heading_classes  .= ' ' . $classes['nonrepeater-heading'];
	$controls_classes .= ' ' . $classes['nonrepeater-controls'];
	$explain_classes  .= ' ' . $classes['nonrepeater-explain'];

}

$section_classes  .= ' ' . $classes['section-class-by-filed-type'];
$heading_classes  .= ' ' . $classes['heading-class-by-filed-type'];
$controls_classes .= ' ' . $classes['controls-class-by-filed-type'];
$explain_classes  .= ' ' . $classes['explain-class-by-filed-type'];


?>
<div class="bf-section-container bf-widgets bf-clearfix">
	<div class="<?php echo esc_attr( $section_classes ); ?> bf-clearfix"
	     data-id="<?php echo esc_attr( $options['id'] ); ?>">

		<div class="<?php echo esc_attr( $heading_classes ); ?> bf-clearfix">
			<h4><label> <?php echo $input; // escaped before ?><?php echo esc_attr( $options['name'] ); ?></label></h4>
		</div>

		<?php if ( ! empty( $options['desc'] ) ) { ?>
			<div
					class="<?php echo esc_attr( $explain_classes ); ?> bf-clearfix"><?php echo wp_kses( $options['desc'], bf_trans_allowed_html() ); ?></div>
		<?php } ?>

	</div>
</div><?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

// Default selected
$current = array(
	'key'    => '',
	'title'  => __( 'Chose an Icon', 'better-studio' ),
	'width'  => '',
	'height' => '',
	'type'   => '',
);


if ( isset( $options['value'] ) ) {

	if ( is_array( $options['value'] ) ) {

		if ( in_array( $options['value']['type'], array( 'custom-icon', 'custom' ) ) ) {
			$current['key']    = isset( $options['value']['icon'] ) ? $options['value']['icon'] : '';
			$current['title']  = bf_get_icon_tag( isset( $options['value'] ) ? $options['value'] : '' ) . ' ' . __( 'Custom icon', 'better-studio' );
			$current['width']  = isset( $options['value']['width'] ) ? $options['value']['width'] : '';
			$current['height'] = isset( $options['value']['height'] ) ? $options['value']['height'] : '';
			$current['type']   = 'custom-icon';
		} else {
			Better_Framework::factory( 'icon-factory' );

			$fontawesome = BF_Icons_Factory::getInstance( 'fontawesome' );

			if ( isset( $fontawesome->icons[ $options['value']['icon'] ] ) ) {
				$current['key']    = $options['value']['icon'];
				$current['title']  = bf_get_icon_tag( $options['value'] ) . $fontawesome->icons[ $options['value']['icon'] ]['label'];
				$current['width']  = $options['value']['width'];
				$current['height'] = $options['value']['height'];
				$current['type']   = 'fontawesome';
			}
		}

	} elseif ( ! empty( $options['value'] ) ) {

		Better_Framework::factory( 'icon-factory' );

		$fontawesome = BF_Icons_Factory::getInstance( 'fontawesome' );

		$icon_label = '';
		if ( substr( $options['value'], 0, 3 ) == 'fa-' ) {
			$icon_label      = bf_get_icon_tag( $options['value'] ) . ' ' . $fontawesome->icons[ $options['value'] ]['label'];
			$current['type'] = 'fontawesome';
		} else {
			$icon_label      = bf_get_icon_tag( $options['value'] );
			$current['type'] = 'custom-icon';
		}

		$current['key']    = $options['value'];
		$current['title']  = $icon_label;
		$current['width']  = '';
		$current['height'] = '';

	}

}

$icon_handler = 'bf-icon-modal-handler-' . mt_rand();


?>
	<div class="bf-icon-modal-handler" id="<?php echo esc_attr( $icon_handler ); ?>">

		<div class="select-options">
			<span class="selected-option"><?php echo wp_kses( $current['title'], bf_trans_allowed_html() ); ?></span>
		</div>

		<input type="hidden" class="mce-field wpb-textinput title textfield icon-input"
		       data-label=""
		       name="<?php echo esc_attr( $options['input_name'] ); ?>"
		       value="<?php echo esc_attr( $current['key'] ); ?>"/>

	</div><!-- modal handler container -->
<?php

bf_enqueue_modal( 'icon' );
<?php

$options['clone-name-format'] = '$4[$5][$6]';

include BF_PATH . 'core/field-generator/fields/repeater.php';
<?php
<?php


/**
 * TinyMCE Views field generator
 */
class BF_Tinymce_View_Field_Generator extends BF_Admin_Fields {

	/**
	 * @var array
	 */
	public $shortcode_content_fields = array();


	/**
	 * Constructor Method
	 *
	 * @param array $items  Panel All Options
	 * @param int   $id     Panel ID
	 * @param array $values Panel Saved Values
	 *
	 * @since  1.0
	 * @access public
	 */
	public function __construct( array &$items, &$id, &$values = array() ) {

		// Parent Constructor
		parent::__construct( array(
			'templates_dir' => BF_PATH . 'tinymce/templates/'
		) );

		$this->items  = $items;
		$this->id     = $id;
		$this->values = $values;
	}


	public function output() {

		$this->callback( true );
	}


	/**
	 * Field Generator
	 */
	public function callback() {

		$has_tab = false;

		// Add Class For Post Format Filter
		$container = Better_Framework::html()->add( 'div' )->class( 'tinymce-addon-fields' );

		$tab_counter   = 0;
		$group_counter = 0;

		$fields_std = $this->get_stds();

		$container->text( '<div class="tabs-wrapper">' . $this->get_tabs() . '</div>' );

		foreach ( $this->get_fields() as $field ) {

			if ( ! empty( $field['type'] ) && $field['type'] === 'id-holder' ) {
				continue;
			}

			if ( ! isset( $field['input_class'] ) ) {
				$field['input_class'] = '';
			}

			$field['input_class'] .= ' mce-field';
			$field['input_name']  = $this->input_name( $field );

			$field_id = isset( $field['id'] ) ? $field['id'] : false;

			if ( $field['type'] === 'info' ) {
				if ( isset( $field['std'] ) ) {
					$field['value'] = $field['std'];
				} else {
					$field['value'] = '';
				}
			} else {
				$field['value'] = isset( $field['id'] ) && isset( $this->values[ $field['id'] ] ) ? $this->values[ $field['id'] ] : null;
			}

			if ( is_null( $field['value'] ) && isset( $fields_std[ $field_id ] ) ) {
				$field['value'] = $fields_std[ $field_id ];
			}

			if ( $field['type'] == 'repeater' ) {
				$field['clone-name-format'] = 'bf-metabox-option[$3][$4][$5][$6]';
				$field['metabox-id']        = $this->id;
				$field['metabox-field']     = true;
			}

			if ( $field['type'] == 'tab' || $field['type'] == 'subtab' ) {

				// close tag for latest group in tab
				if ( $group_counter != 0 ) {
					$group_counter = 0;
					$container->text( $this->get_fields_group_close( $field ) );
				}

				$is_subtab = $field['type'] == 'subtab';

				if ( $tab_counter != 0 ) {
					$container->text( '</div><!-- /Section -->' );
				}

				if ( $is_subtab ) {
					$container->text( "\n\n<!-- Section -->\n<div class='group subtab-group' id='bf-tmv-{$field["id"]}'>\n" );
				} else {
					$container->text( "\n\n<!-- Section -->\n<div class='group' id='bf-tmv-{$field["id"]}'>\n" );
				}
				$has_tab = true;
				$tab_counter ++;
				continue;
			}

			if ( $field['type'] == 'group_close' ) {

				// close tag for latest group in tab
				if ( $group_counter != 0 ) {
					$group_counter = 0;
					$container->text( $this->get_fields_group_close( $field ) );
				}
				continue;
			}


			if ( $field['type'] == 'group' ) {

				// close tag for latest group in tab
				if ( $group_counter != 0 ) {
					$group_counter = 0;
					$container->text( $this->get_fields_group_close( $field ) );
				}

				$container->text( $this->get_fields_group_start( $field ) );

				$group_counter ++;
			}


			if ( ! in_array( $field['type'], $this->supported_fields ) ) {
				continue;
			}

			// Filter Each Field For Post Formats!
			if ( isset( $field['post_format'] ) ) {

				if ( is_array( $field['post_format'] ) ) {
					$field_post_formats = implode( ',', $field['post_format'] );
				} else {
					$field_post_formats = $field['post_format'];
				}
				$container->text( "<div class='bf-field-post-format-filter' data-bf_pf_filter='{$field_post_formats}'>" );
			}

			$container->text(
				$this->section(
					call_user_func(
						array( $this, $field['type'] ),
						$field
					),
					$field
				)
			);

			// End Post Format Filter Wrapper
			if ( isset( $field['post_format'] ) ) {

				$container->text( "</div>" );
			}
		}

		// close tag for latest group in tab
		if ( $group_counter != 0 ) {
			$container->text( $this->get_fields_group_close( $field ) );
		}

		// last sub tab closing
		if ( $has_tab ) {
			$container->text( "</div><!-- /Section -->" );
		}

		echo $container->display();
	} // callback


	/**
	 * Used for creating input name
	 *
	 * @param $options
	 *
	 * @return string
	 */
	public function input_name( &$options ) {

		if ( isset( $options['type'] ) && $options['type'] === 'repeater' ) {
			return '%2$s[%3$d][%4$s]';
		}

		return isset( $options['id'] ) ? $options['id'] : '';
	}


	/**
	 * Get shortcode fields std values
	 *
	 * @return array
	 */
	public function get_stds() {

		if ( $shortcode = BF_Shortcodes_Manager::factory( $this->id ) ) {
			return $shortcode->defaults;
		}

		return array();
	}


	public function generate_repeater_field( $tinymce, $field, $defaults, $name_format, $number ) {

		if ( ! isset( $field['input_class'] ) ) {
			$field['input_class'] = '';
		}
		$field['input_class'] .= ' mce-field';

		if ( ! empty( $field['shortcode_content'] ) ) {
			$this->shortcode_content_fields[ $tinymce['id'] ] = $field['id'];
		}

		return parent::generate_repeater_field( $tinymce, $field, $defaults, $name_format, $number );
	}


	public function generate_repeater_field_script( $tinymce, $field, $defaults ) {

		if ( ! isset( $field['input_class'] ) ) {
			$field['input_class'] = '';
		}
		$field['input_class'] .= ' mce-field';

		return parent::generate_repeater_field_script( $tinymce, $field, $defaults );
	}


	public function __call( $name, $arguments ) {

		$file = BF_PATH . 'tinymce/fields/' . $name . '.php';

		// Check if requested field (method) does exist!
		if ( ! file_exists( $file ) ) {
			return parent::__call( $name, $arguments );
		}


		$options = $arguments[0];

		// Capture output
		ob_start();
		require $file;

		$data = ob_get_clean();

		return $data;
	}
}

F1le Man4ger