PK      *\6c  c    class-vc-page.phpnu W+A        <?php
if ( ! defined( 'ABSPATH' ) ) {
	die( '-1' );
}

class Vc_Page implements Vc_Render {
	protected $slug;
	protected $title;
	protected $templatePath;

	/**
	 * @return string
	 *
	 */
	public function getSlug() {
		return $this->slug;
	}

	/**
	 * @param mixed $slug
	 *
	 * @return $this;
	 */
	public function setSlug( $slug ) {
		$this->slug = (string) $slug;

		return $this;
	}

	/**
	 * @return mixed
	 */
	public function getTitle() {
		return $this->title;
	}

	/**
	 * @param string $title
	 *
	 * @return $this
	 */
	public function setTitle( $title ) {
		$this->title = (string) $title;

		return $this;
	}

	/**
	 * @return mixed
	 */
	public function getTemplatePath() {
		return $this->templatePath;
	}

	/**
	 * @param mixed $templatePath
	 *
	 * @return $this
	 */
	public function setTemplatePath( $templatePath ) {
		$this->templatePath = $templatePath;

		return $this;
	}

	public function render() {
		ob_start();
		vc_include_template( $this->getTemplatePath(), array(
			'page' => $this,
		) );

		echo apply_filters( 'vc_settings-page-render-' . $this->getSlug(), ob_get_clean(), $this );
	}
}
PK      *\E    '  access/class-vc-current-user-access.phpnu W+A        <?php
if ( ! defined( 'ABSPATH' ) ) {
	die( '-1' );
}

require_once vc_path_dir( 'CORE_DIR', 'access/class-vc-role-access.php' );

/**
 * Class Vc_User_Access
 */
class Vc_Current_User_Access extends Vc_Role_Access {
	/**
	 * @param $part
	 *
	 * @return Vc_Current_User_Access_Controller;
	 */
	public function part( $part ) {
		if ( ! isset( $this->parts[ $part ] ) ) {
			require_once vc_path_dir( 'CORE_DIR', 'access/class-vc-current-user-access-controller.php' );
			/** @var $user_access_controller Vc_Current_User_Access_Controller */
			$user_access_controller = $this->parts[ $part ] = new Vc_Current_User_Access_Controller( $part );
		}
		/** @var $user_access_controller Vc_Current_User_Access_Controller */
		$user_access_controller = $this->parts[ $part ];
		// we also check for user "logged_in" status
		$is_user_logged_in = function_exists( 'is_user_logged_in' ) && is_user_logged_in();
		$user_access_controller->setValidAccess( $is_user_logged_in && $this->getValidAccess() ); // send current status to upper level
		$this->setValidAccess( true ); // reset

		return $user_access_controller;
	}

	public function wpMulti( $method, $valid, $argsList ) {
		if ( $this->getValidAccess() ) {
			$access = ! $valid;
			foreach ( $argsList as &$args ) {
				if ( ! is_array( $args ) ) {
					$args = array( $args );
				}
				array_unshift( $args, 'current_user_can' );
				$this->setValidAccess( true );
				call_user_func_array( array(
					&$this,
					$method,
				), $args );
				if ( $valid === $this->getValidAccess() ) {
					$access = $valid;
					break;
				}
			}
			$this->setValidAccess( $access );
		}

		return $this;
	}

	/**
	 * Check Wordpress capability. Should be valid one cap at least.
	 *
	 * @return Vc_Current_User_Access
	 */
	public function wpAny() {
		if ( $this->getValidAccess() ) {
			$args = func_get_args();
			$this->wpMulti( 'check', true, $args );
		}

		return $this;
	}

	/**
	 * Check Wordpress capability. Should be valid all caps.
	 *
	 * @return Vc_Current_User_Access
	 */
	public function wpAll() {
		if ( $this->getValidAccess() ) {
			$args = func_get_args();
			$this->wpMulti( 'check', false, $args );
		}

		return $this;
	}
}
PK      *\Q)  )  2  access/class-vc-current-user-access-controller.phpnu W+A        <?php
if ( ! defined( 'ABSPATH' ) ) {
	die( '-1' );
}

require_once vc_path_dir( 'CORE_DIR', 'access/class-vc-role-access-controller.php' );

class Vc_Current_User_Access_Controller extends Vc_Role_Access_Controller {
	/**
	 * Get capability for current user
	 *
	 * @param $rule
	 *
	 * @return bool
	 */
	public function getCapRule( $rule ) {
		$role_rule = $this->getStateKey() . '/' . $rule;

		return current_user_can( $role_rule );
	}

	/**
	 * Add capability to role.
	 *
	 * @param $rule
	 * @param bool $value
	 */
	public function setCapRule( $rule, $value = true ) {
		$role_rule = $this->getStateKey() . '/' . $rule;

		wp_get_current_user()->add_cap( $role_rule, $value );
	}

	public function getRole() {
		if ( ! $this->roleName && function_exists( 'wp_get_current_user' ) ) {
			$user = wp_get_current_user();
			$user_roles = array_intersect( array_values( (array) $user->roles ), array_keys( (array) get_editable_roles() ) );
			$this->roleName = reset( $user_roles );
			$this->role = get_role( $this->roleName );
		}

		return $this->role;
	}
}
PK      *\u$+      access/class-vc-role-access.phpnu W+A        <?php
if ( ! defined( 'ABSPATH' ) ) {
	die( '-1' );
}

require_once vc_path_dir( 'CORE_DIR', 'access/abstract-class-vc-access.php' );

/**
 * Class Vc_Role_Access
 */
class Vc_Role_Access extends Vc_Access {
	/**
	 * @var bool
	 */
	protected $roleName = false;
	/**
	 * @var array
	 */
	protected $parts = array();

	/**
	 *
	 */
	public function __construct() {
		require_once( ABSPATH . 'wp-admin/includes/user.php' );
	}

	/**
	 * @param $part
	 * @return \Vc_Role_Access_Controller
	 * @throws \Exception
	 */
	public function part( $part ) {
		$role_name = $this->getRoleName();
		if ( ! $role_name ) {
			throw new Exception( 'roleName for vc_role_access is not set, please use ->who(roleName) method to set!' );
		}
		$key = $part . '_' . $role_name;
		if ( ! isset( $this->parts[ $key ] ) ) {
			require_once vc_path_dir( 'CORE_DIR', 'access/class-vc-role-access-controller.php' );
			/** @var $role_access_controller Vc_Role_Access_Controller */
			$role_access_controller = $this->parts[ $key ] = new Vc_Role_Access_Controller( $part );
			$role_access_controller->setRoleName( $this->getRoleName() );
		}
		/** @var $role_access_controller Vc_Role_Access_Controller */
		$role_access_controller = $this->parts[ $key ];
		$role_access_controller->setValidAccess( $this->getValidAccess() ); // send current status to upper level
		$this->setValidAccess( true ); // reset

		return $role_access_controller;
	}

	/**
	 * Set role to get access to data.
	 *
	 * @param $roleName
	 * @return $this
	 * @internal param $role
	 *
	 */
	public function who( $roleName ) {
		$this->roleName = $roleName;

		return $this;
	}

	/**
	 * @return null|string
	 */
	public function getRoleName() {
		return $this->roleName;
	}
}
PK      *\x    #  access/abstract-class-vc-access.phpnu W+A        <?php
if ( ! defined( 'ABSPATH' ) ) {
	die( '-1' );
}

/**
 * Class Vc_Access
 *
 * @package WPBakeryVisualComposer
 * @since 4.8
 */
abstract class Vc_Access {
	/**
	 * @var bool
	 */
	protected $validAccess = true;

	public function getValidAccess() {
		return $this->validAccess;
	}

	/**
	 * @param mixed $validAccess
	 *
	 * @return $this
	 */
	public function setValidAccess( $validAccess ) {
		$this->validAccess = $validAccess;

		return $this;
	}

	/**
	 * Check multi access settings by method inside class object.
	 *
	 * @param $method
	 * @param $valid
	 * @param $argsList
	 *
	 * @return $this
	 */
	public function checkMulti( $method, $valid, $argsList ) {
		if ( $this->getValidAccess() ) {
			$access = ! $valid;
			foreach ( $argsList as $args ) {
				if ( ! is_array( $args ) ) {
					$args = array( $args );
				}
				$this->setValidAccess( true );
				call_user_func_array( array( &$this, $method ), $args );
				if ( $valid === $this->getValidAccess() ) {
					$access = $valid;
					break;
				}
			}
			$this->setValidAccess( $access );
		}

		return $this;
	}

	/**
	 * Get current validation state and reset it to true. ( should be never called twice )
	 * @return bool
	 */
	public function get() {
		$result = $this->getValidAccess();
		$this->setValidAccess( true );

		return $result;
	}

	/**
	 * Call die() function with message if access is invalid.
	 *
	 * @param string $message
	 * @return $this
	 * @throws \Exception
	 */
	public function validateDie( $message = '' ) {
		$result = $this->getValidAccess();
		$this->setValidAccess( true );
		if ( ! $result ) {
			if ( defined( 'VC_DIE_EXCEPTION' ) && VC_DIE_EXCEPTION ) {
				throw new Exception( $message );
			} else {
				die( $message );
			}
		}

		return $this;
	}


	/**
	 * @param $func
	 *
	 * @return $this
	 */
	public function check( $func ) {
		if ( $this->getValidAccess() ) {
			$args = func_get_args();
			$args = array_slice( $args, 1 );
			if ( ! empty( $func ) ) {
				$this->setValidAccess( call_user_func_array( $func, $args ) );
			}
		}

		return $this;
	}

	/**
	 * Any of provided rules should be valid.
	 * Usage: checkAny(
	 *      'vc_verify_admin_nonce',
	 *      array( 'current_user_can', 'edit_post', 12 ),
	 *      array( 'current_user_can', 'edit_posts' ),
	 * )
	 * @return $this
	 */
	public function checkAny() {
		if ( $this->getValidAccess() ) {
			$args = func_get_args();
			$this->checkMulti( 'check', true, $args );
		}

		return $this;
	}

	/**
	 * All provided rules should be valid.
	 * Usage: checkAll(
	 *      'vc_verify_admin_nonce',
	 *      array( 'current_user_can', 'edit_post', 12 ),
	 *      array( 'current_user_can', 'edit_posts' ),
	 * )
	 * @return $this
	 */
	public function checkAll() {
		if ( $this->getValidAccess() ) {
			$args = func_get_args();
			$this->checkMulti( 'check', false, $args );
		}

		return $this;
	}

	/**
	 * @param string $nonce
	 *
	 * @return Vc_Current_User_Access
	 */
	public function checkAdminNonce( $nonce = '' ) {
		return $this->check( 'vc_verify_admin_nonce', $nonce );
	}

	/**
	 * @param string $nonce
	 *
	 * @return Vc_Current_User_Access
	 */
	public function checkPublicNonce( $nonce = '' ) {
		return $this->check( 'vc_verify_public_nonce', $nonce );
	}
}
PK      *\9J  J  *  access/class-vc-role-access-controller.phpnu W+A        <?php
if ( ! defined( 'ABSPATH' ) ) {
	die( '-1' );
}

require_once vc_path_dir( 'CORE_DIR', 'access/abstract-class-vc-access.php' );

/**
 * Class Vc_Role_Access_Controller
 *
 * @since 4.8
 */
class Vc_Role_Access_Controller extends Vc_Access {
	protected static $part_name_prefix = 'vc_access_rules_';
	protected $part = false;
	protected $roleName = false;
	protected $role = false;
	protected $validAccess = true;
	protected $mergedCaps = array(
		'vc_row_inner_all' => 'vc_row_all',
		'vc_column_all' => 'vc_row_all',
		'vc_column_inner_all' => 'vc_row_all',
		'vc_row_inner_edit' => 'vc_row_edit',
		'vc_column_edit' => 'vc_row_edit',
		'vc_column_inner_edit' => 'vc_row_edit',
	);

	function __construct( $part ) {
		$this->part = $part;
	}

	/**
	 * Set role name.
	 *
	 * @param $role_name
	 */
	public function setRoleName( $role_name ) {
		$this->roleName = $role_name;
	}

	/**
	 * Get part for role.
	 * @return bool
	 */
	public function getPart() {
		return $this->part;
	}

	/**
	 * Get state of the Vc access rules part.
	 *
	 * @return mixed;
	 */
	public function getState() {
		$role = $this->getRole();
		$state = null;
		if ( $role && isset( $role->capabilities, $role->capabilities[ $this->getStateKey() ] ) ) {
			$state = $role->capabilities[ $this->getStateKey() ];
		}

		return apply_filters( 'vc_role_access_with_' . $this->getPart() . '_get_state', $state, $this->getRole() );
	}

	/**
	 * Set state for full part.
	 *
	 * State can have 3 values:
	 * true - all allowed under this part;
	 * false - all disabled under this part;
	 * string|'custom' - custom settings. It means that need to check exact capability.
	 *
	 * @param bool $value
	 *
	 * @return $this
	 */
	public function setState( $value = true ) {
		$this->getRole() && $this->getRole()->add_cap( $this->getStateKey(), $value );

		return $this;
	}

	/**
	 * Can user do what he doo.
	 * Any rule has three types of state: true, false, string.
	 *
	 * @param string $rule
	 * @param bool|true $check_state
	 *
	 * @return $this
	 */
	public function can( $rule = '', $check_state = true ) {
		if ( null === $this->getRole() ) {
			$this->setValidAccess( is_super_admin() );
		} elseif ( $this->getValidAccess() ) {
			// YES it is hard coded :)
			if ( 'administrator' === $this->getRole()->name && 'settings' === $this->getPart() && ( 'vc-roles-tab' === $rule || 'vc-updater-tab' === $rule ) ) {
				$this->setValidAccess( true );

				return $this;
			}
			$rule = $this->updateMergedCaps( $rule );

			if ( true === $check_state ) {
				$state = $this->getState();
				$return = false !== $state;
				if ( null === $state ) {
					$return = true;
				} elseif ( is_bool( $state ) ) {
					$return = $state;
				} elseif ( '' !== $rule ) {
					$return = $this->getCapRule( $rule );
				}
			} else {
				$return = $this->getCapRule( $rule );
			}
			$return = apply_filters( 'vc_role_access_with_' . $this->getPart() . '_can', $return, $this->getRole(), $rule );
			$return = apply_filters( 'vc_role_access_with_' . $this->getPart() . '_can_' . $rule, $return, $this->getRole() );
			$this->setValidAccess( $return );
		}

		return $this;
	}

	/**
	 * Can user do what he doo.
	 * Any rule has three types of state: true,false, string.
	 */
	public function canAny() {
		if ( $this->getValidAccess() ) {
			$args = func_get_args();
			$this->checkMulti( 'can', true, $args );
		}

		return $this;
	}

	/**
	 * Can user do what he doo.
	 * Any rule has three types of state: true,false, string.
	 */
	public function canAll() {
		if ( $this->getValidAccess() ) {
			$args = func_get_args();
			$this->checkMulti( 'can', false, $args );
		}

		return $this;
	}

	/**
	 * Get capability for role
	 *
	 * @param $rule
	 *
	 * @return bool
	 */
	public function getCapRule( $rule ) {
		$rule = $this->getStateKey() . '/' . $rule;

		return $this->getRole() ? $this->getRole()->has_cap( $rule ) : false;
	}

	/**
	 * Add capability to role.
	 *
	 * @param $rule
	 * @param bool $value
	 */
	public function setCapRule( $rule, $value = true ) {
		$role_rule = $this->getStateKey() . '/' . $rule;
		$this->getRole() && $this->getRole()->add_cap( $role_rule, $value );
	}

	/**
	 * Get all capability for this part.
	 */
	public function getAllCaps() {
		$role = $this->getRole();
		$caps = array();
		if ( $role ) {
			$role = apply_filters( 'vc_role_access_all_caps_role', $role );
			if ( isset( $role->capabilities ) && is_array( $role->capabilities ) ) {
				foreach ( $role->capabilities as $key => $value ) {
					if ( preg_match( '/^' . $this->getStateKey() . '\//', $key ) ) {
						$rule = preg_replace( '/^' . $this->getStateKey() . '\//', '', $key );
						$caps[ $rule ] = $value;
					}
				}
			}
		}

		return $caps;
	}

	/**
	 * @return null|\WP_Role
	 * @throws Exception
	 */
	public function getRole() {
		if ( ! $this->role ) {
			if ( ! $this->getRoleName() ) {
				throw new Exception( 'roleName for role_manager is not set, please use ->who(roleName) method to set!' );
			}
			$this->role = get_role( $this->getRoleName() );
		}

		return $this->role;
	}

	/**
	 * @return null|string
	 */
	public function getRoleName() {
		return $this->roleName;
	}

	public function getStateKey() {
		return self::$part_name_prefix . $this->getPart();
	}

	public function checkState( $data ) {
		if ( $this->getValidAccess() ) {
			$this->setValidAccess( $this->getState() === $data );
		}

		return $this;
	}

	public function checkStateAny() {
		if ( $this->getValidAccess() ) {
			$args = func_get_args();
			$this->checkMulti( 'checkState', true, $args );
		}

		return $this;
	}

	/**
	 * Return access value.
	 * @return string
	 */
	public function __toString() {
		return (string) $this->get();
	}

	public function updateMergedCaps( $rule ) {
		if ( isset( $this->mergedCaps[ $rule ] ) ) {
			return $this->mergedCaps[ $rule ];
		}

		return $rule;
	}

	/**
	 * @return array
	 */
	public function getMergedCaps() {
		return $this->mergedCaps;
	}
}
PK      *\IZ&M  M    class-wpb-map.phpnu W+A        <?php
if ( ! defined( 'ABSPATH' ) ) {
	die( '-1' );
}

/**
 * WPBakery Visual Composer Main manager.
 *
 * @package WPBakeryVisualComposer
 * @since   4.2
 */
class WPBMap {

	/**
	 * @var array
	 */
	protected static $sc = array();

	/**
	 * @var bool
	 */
	protected static $sorted_sc = false;

	/**
	 * @var array|false
	 */
	protected static $categories = false;

	/**
	 * @var bool
	 */
	protected static $user_sc = false;

	/**
	 * @var bool
	 */
	protected static $user_sorted_sc = false;

	/**
	 * @var bool
	 */
	protected static $user_categories = false;

	/**
	 * @var Vc_Settings $settings
	 */
	protected static $settings;

	/**
	 * @var
	 */
	protected static $user_role;

	/**
	 * @var
	 */
	protected static $tags_regexp;

	/**
	 * @var bool
	 */
	protected static $is_init = false;

	/**
	 * @var bool
	 */
	protected static $init_elements = array();

	/**
	 * Set init status fro WPMap.
	 *
	 * if $is_init is FALSE, then all activity like add, update and delete for shortcodes attributes will be hold in
	 * the list of activity and will be executed after initialization.
	 *
	 * @see Vc_Mapper::iniy.
	 * @static
	 *
	 * @param bool $value
	 */
	public static function setInit( $value = true ) {
		self::$is_init = $value;
	}

	/**
	 * Gets user role and access rules for current user.
	 *
	 * @static
	 * @return mixed
	 */
	protected static function getSettings() {
		global $current_user;

		// @todo fix_roles? what is this and why it is inside class-wpb-map?
		if ( null !== self::$settings ) {
			if ( function_exists( 'wp_get_current_user' ) ) {
				wp_get_current_user();
				/** @var Vc_Settings $settings - get use group access rules */
				if ( ! empty( $current_user->roles ) ) {
					self::$user_role = $current_user->roles[0];
				} else {
					self::$user_role = 'author';
				}
			} else {
				self::$user_role = 'author';
			}
			self::$settings = vc_settings()->get( 'groups_access_rules' );
		}

		return self::$settings;
	}

	/**
	 * Check is shortcode with a tag mapped to VC.
	 *
	 * @static
	 *
	 * @param $tag - shortcode tag.
	 *
	 * @return bool
	 */
	public static function exists( $tag ) {
		return (boolean) isset( self::$sc[ $tag ] );
	}

	/**
	 * Map shortcode to VC.
	 *
	 * This method maps shortcode to VC.
	 * You need to shortcode's tag and settings to map correctly.
	 * Default shortcodes are mapped in config/map.php file.
	 * The best way is to call this method with "init" action callback function of WP.
	 *
	 * vc_filter: vc_mapper_tag - to change shortcode tag, arguments 2 ( $tag, $attributes )
	 * vc_filter: vc_mapper_attributes - to change shortcode attributes (like params array), arguments 2 ( $attributes,
	 * $tag ) vc_filter: vc_mapper_attribute - to change singe shortcode param data, arguments 2 ( $attribute, $tag )
	 * vc_filter: vc_mapper_attribute_{PARAM_TYPE} - to change singe shortcode param data by param type, arguments 2 (
	 * $attribute, $tag )
	 *
	 * @static
	 *
	 * @param $tag
	 * @param $attributes
	 *
	 * @return bool
	 */
	public static function map( $tag, $attributes ) {
		if ( ! self::$is_init ) {
			if ( empty( $attributes['name'] ) ) {
				trigger_error( sprintf( __( 'Wrong name for shortcode:%s. Name required', 'js_composer' ), $tag ) );
			} elseif ( empty( $attributes['base'] ) ) {
				trigger_error( sprintf( __( 'Wrong base for shortcode:%s. Base required', 'js_composer' ), $tag ) );
			} else {
				vc_mapper()->addActivity( 'mapper', 'map', array(
					'tag' => $tag,
					'attributes' => $attributes,
				) );

				return true;
			}

			return false;
		}
		if ( empty( $attributes['name'] ) ) {
			trigger_error( sprintf( __( 'Wrong name for shortcode:%s. Name required', 'js_composer' ), $tag ) );
		} elseif ( empty( $attributes['base'] ) ) {
			trigger_error( sprintf( __( 'Wrong base for shortcode:%s. Base required', 'js_composer' ), $tag ) );
		} else {
			self::$sc[ $tag ] = $attributes;

			return true;
		}

		return false;
	}

	/**
	 * Lazy method to map shortcode to VC.
	 *
	 * This method maps shortcode to VC.
	 * You can shortcode settings as you do in self::map method. Bu also you
	 * can pass function name or file, which will be used to add settings for
	 * element. But this will be done only when element data is really required.
	 *
	 * @static
	 * @since 4.9
	 *
	 * @param $tag
	 * @param $settings_file
	 * @param $settings_function
	 * @param $attributes
	 *
	 * @return bool
	 */
	public static function leanMap( $tag, $settings_function = null, $settings_file = null, $attributes = array() ) {
		self::$sc[ $tag ] = $attributes;
		self::$sc[ $tag ]['base'] = $tag;
		if ( is_string( $settings_file ) ) {
			self::$sc[ $tag ]['__vc_settings_file'] = $settings_file;
		}
		if ( ! is_null( $settings_function ) ) {
			self::$sc[ $tag ]['__vc_settings_function'] = $settings_function;
		}

		return true;
	}

	/**
	 * Generates list of shortcodes taking into account the access rules for shortcodes from VC Settings page.
	 *
	 * This method parses the list of mapped shortcodes and creates categories list for users.
	 *
	 * @static
	 *
	 * @param bool $force - force data generation even data already generated.
	 */
	protected static function generateUserData( $force = false ) {
		if ( ! $force && false !== self::$user_sc && false !== self::$user_categories ) {
			return;
		}

		//$settings = self::getSettings();
		self::$user_sc = self::$user_categories = self::$user_sorted_sc = array();
		$deprecated = 'deprecated';
		$add_deprecated = false;
		if ( is_array( self::$sc ) && ! empty( self::$sc ) ) {
			foreach ( array_keys( self::$sc ) as $name ) {
				self::setElementSettings( $name );
				if ( ! isset( self::$sc[ $name ] ) ) {
					continue;
				}
				$values = self::$sc[ $name ];
				if ( vc_user_access_check_shortcode_all( $name ) ) {
					if ( ! isset( $values['content_element'] ) || true === $values['content_element'] ) {
						$categories = isset( $values['category'] ) ? $values['category'] : '_other_category_';
						$values['_category_ids'] = array();
						if ( isset( $values['deprecated'] ) && false !== $values['deprecated'] ) {
							$add_deprecated = true;
							$values['_category_ids'][] = 'deprecated';
						} else {
							if ( is_array( $categories ) && ! empty( $categories ) ) {
								foreach ( $categories as $c ) {
									if ( false === array_search( $c, self::$user_categories ) ) {
										self::$user_categories[] = $c;
									}
									$values['_category_ids'][] = md5( $c );
								}
							} else {
								if ( false === array_search( $categories, self::$user_categories ) ) {
									self::$user_categories[] = $categories;
								}
								$values['_category_ids'][] = md5( $categories );
							}
						}
					}

					self::$user_sc[ $name ] = $values;
					self::$user_sorted_sc[] = $values;
				}
			}
		}
		if ( $add_deprecated ) {
			self::$user_categories[] = $deprecated;
		}

		$sort = new Vc_Sort( self::$user_sorted_sc );
		self::$user_sorted_sc = $sort->sortByKey();
	}

	/**
	 * Generates list of shortcodes.
	 *
	 * This method parses the list of mapped shortcodes and creates categories list.
	 *
	 * @static_other_category_
	 *
	 * @param bool $force - force data generation even data already generated.
	 */
	protected static function generateData( $force = false ) {
		if ( ! $force && false !== self::$categories ) {
			return;
		}
		foreach ( self::$sc as $tag => $settings ) {
			self::setElementSettings( $tag );
		}
		self::$categories = self::collectCategories( self::$sc );
		$sort = new Vc_Sort( array_values( self::$sc ) );
		self::$sorted_sc = $sort->sortByKey();
	}

	/**
	 * Get mapped shortcode settings.
	 *
	 * @static
	 * @return array
	 */
	public static function getShortCodes() {
		return self::$sc;
	}

	/**
	 * Get mapped shortcode settings.
	 *
	 * @static
	 * @return array
	 */
	public static function getAllShortCodes() {
		self::generateData();

		return self::$sc;
	}

	/**
	 * Get mapped shortcode settings.
	 *
	 * @static
	 * @return array
	 */
	public static function getSortedAllShortCodes() {
		self::generateData();

		return self::$sorted_sc;
	}

	/**
	 * Get sorted list of mapped shortcode settings for current user.
	 *
	 * Sorting depends on the weight attribute and mapping order.
	 *
	 * @static
	 * @return array
	 */
	public static function getSortedUserShortCodes() {
		self::generateUserData();

		return self::$user_sorted_sc;
	}

	/**
	 * Get list of mapped shortcode settings for current user.
	 * @static
	 * @return array - associated array of shortcodes settings with tag as the key.
	 */
	public static function getUserShortCodes() {
		self::generateUserData();

		return self::$user_sc;
	}

	/**
	 * Get mapped shortcode settings by tag.
	 *
	 * @static
	 *
	 * @param $tag - shortcode tag.
	 *
	 * @return array|null null @since 4.4.3
	 */
	public static function getShortCode( $tag ) {
		if ( isset( self::$sc[ $tag ] ) && is_array( self::$sc[ $tag ] ) ) {
			self::setElementSettings( $tag );
			$shortcode = self::$sc[ $tag ];
		} else {
			$shortcode = null;
		}

		return $shortcode;
	}

	/**
	 * Get mapped shortcode settings by tag.
	 *
	 * @since 4.5.2
	 * @static
	 *
	 * @param $tag - shortcode tag.
	 *
	 * @return array|null
	 */
	public static function getUserShortCode( $tag ) {
		self::generateUserData();
		if ( isset( self::$user_sc[ $tag ] ) && is_array( self::$user_sc[ $tag ] ) ) {
			$shortcode = self::$user_sc[ $tag ];
			if ( ! empty( $shortcode['params'] ) ) {
				$params = $shortcode['params'];
				$shortcode['params'] = array();
				foreach ( $params as $attribute ) {
					$attribute = apply_filters( 'vc_mapper_attribute', $attribute, $tag );
					$attribute = apply_filters( 'vc_mapper_attribute_' . $attribute['type'], $attribute, $tag );
					$shortcode['params'][] = $attribute;
				}
				$sort = new Vc_Sort( $shortcode['params'] );
				$shortcode['params'] = $sort->sortByKey();
			}

			return $shortcode;
		}

		return null;
	}

	/**
	 * Get all categories for mapped shortcodes.
	 *
	 * @static
	 * @return array
	 */
	public static function getCategories() {
		self::generateData();

		return self::$categories;
	}

	/**
	 * Get all categories for current user.
	 *
	 * Category is added to the list when at least one shortcode of this category is allowed for current user
	 * by Vc access rules.
	 *
	 * @static
	 * @return array
	 */
	public static function getUserCategories() {
		self::generateUserData();

		return self::$user_categories;
	}

	/**
	 * Drop shortcode param.
	 *
	 * @static
	 *
	 * @param $name
	 * @param $attribute_name
	 *
	 * @return bool
	 */
	public static function dropParam( $name, $attribute_name ) {
		if ( ! isset( self::$init_elements[ $name ] ) ) {
			vc_mapper()->addElementActivity( $name, 'drop_param', array(
				'name' => $name,
				'attribute_name' => $attribute_name,
			) );

			return true;
		}
		if ( isset( self::$sc[ $name ], self::$sc[ $name ]['params'] ) && is_array( self::$sc[ $name ]['params'] ) ) {
			foreach ( self::$sc[ $name ]['params'] as $index => $param ) {
				if ( $param['param_name'] == $attribute_name ) {
					unset( self::$sc[ $name ]['params'][ $index ] );
					self::$sc[ $name ]['params'] = array_merge( self::$sc[ $name ]['params'] ); // fix indexes
					return true;
				}
			}
		}

		return true;
	}

	/**
	 * Returns param settings for mapped shortcodes.
	 *
	 * @static
	 *
	 * @param $tag
	 * @param $param_name
	 *
	 * @return bool| array
	 */
	public static function getParam( $tag, $param_name ) {
		if ( ! isset( self::$sc[ $tag ] ) ) {
			return trigger_error( sprintf( __( 'Wrong name for shortcode:%s. Name required', 'js_composer' ), $tag ) );
		}

		if ( isset( self::$sc[ $tag ]['__vc_settings_function'] ) || isset( self::$sc[ $tag ]['__vc_settings_file'] ) ) {
			self::setElementSettings( $tag );
		}

		if ( ! isset( self::$sc[ $tag ]['params'] ) ) {
			return false;
		}

		foreach ( self::$sc[ $tag ]['params'] as $index => $param ) {
			if ( $param['param_name'] == $param_name ) {
				return self::$sc[ $tag ]['params'][ $index ];
			}
		}

		return false;
	}

	/**
	 * Add new param to shortcode params list.
	 *
	 * @static
	 *
	 * @param $name
	 * @param array $attribute
	 *
	 * @return bool - true if added, false if scheduled/rejected
	 */
	public static function addParam( $name, $attribute = array() ) {
		if ( ! isset( self::$init_elements[ $name ] ) ) {
			vc_mapper()->addElementActivity( $name, 'add_param', array(
				'name' => $name,
				'attribute' => $attribute,
			) );

			return false;
		}
		if ( ! isset( self::$sc[ $name ] ) ) {
			trigger_error( sprintf( __( 'Wrong name for shortcode:%s. Name required', 'js_composer' ), $name ) );
		} elseif ( ! isset( $attribute['param_name'] ) ) {
			trigger_error( sprintf( __( "Wrong attribute for '%s' shortcode. Attribute 'param_name' required", 'js_composer' ), $name ) );
		} else {

			$replaced = false;

			foreach ( self::$sc[ $name ]['params'] as $index => $param ) {
				if ( $param['param_name'] == $attribute['param_name'] ) {
					$replaced = true;
					self::$sc[ $name ]['params'][ $index ] = $attribute;
					break;
				}
			}
			if ( false === $replaced ) {
				self::$sc[ $name ]['params'][] = $attribute;
			}

			$sort = new Vc_Sort( self::$sc[ $name ]['params'] );
			self::$sc[ $name ]['params'] = $sort->sortByKey();

			return true;
		}

		return false;
	}

	/**
	 * Change param attributes of mapped shortcode.
	 *
	 * @static
	 *
	 * @param $name
	 * @param array $attribute
	 *
	 * @return bool
	 */
	public static function mutateParam( $name, $attribute = array() ) {
		if ( ! isset( self::$init_elements[ $name ] ) ) {
			vc_mapper()->addElementActivity( $name, 'mutate_param', array(
				'name' => $name,
				'attribute' => $attribute,
			) );

			return false;
		}
		if ( ! isset( self::$sc[ $name ] ) ) {
			return trigger_error( sprintf( __( 'Wrong name for shortcode:%s. Name required', 'js_composer' ), $name ) );
		} elseif ( ! isset( $attribute['param_name'] ) ) {
			trigger_error( sprintf( __( "Wrong attribute for '%s' shortcode. Attribute 'param_name' required", 'js_composer' ), $name ) );
		} else {

			$replaced = false;

			foreach ( self::$sc[ $name ]['params'] as $index => $param ) {
				if ( $param['param_name'] == $attribute['param_name'] ) {
					$replaced = true;
					self::$sc[ $name ]['params'][ $index ] = array_merge( $param, $attribute );
					break;
				}
			}

			if ( false === $replaced ) {
				self::$sc[ $name ]['params'][] = $attribute;
			}
			$sort = new Vc_Sort( self::$sc[ $name ]['params'] );
			self::$sc[ $name ]['params'] = $sort->sortByKey();
		}

		return true;
	}

	/**
	 * Removes shortcode from mapping list.
	 *
	 * @static
	 *
	 * @param $name
	 *
	 * @return bool
	 */
	public static function dropShortcode( $name ) {
		if ( ! isset( self::$init_elements[ $name ] ) ) {
			vc_mapper()->addElementActivity( $name, 'drop_shortcode', array(
				'name' => $name,
			) );

			return false;
		}
		unset( self::$sc[ $name ] );
		visual_composer()->removeShortCode( $name );

		return true;
	}

	public static function dropAllShortcodes() {
		if ( ! self::$is_init ) {
			vc_mapper()->addActivity( '*', 'drop_all_shortcodes', array() );

			return false;
		}
		foreach ( self::$sc as $name => $data ) {
			visual_composer()->removeShortCode( $name );
		}
		self::$sc = array();
		self::$user_sc = self::$user_categories = self::$user_sorted_sc = false;

		return true;
	}

	/**
	 * Modify shortcode's mapped settings.
	 * You can modify only one option of the group options.
	 * Call this method with $settings_name param as associated array to mass modifications.
	 *
	 * @static
	 *
	 * @param $name - shortcode' name.
	 * @param $setting_name - option key name or the array of options.
	 * @param $value - value of settings if $setting_name is option key.
	 *
	 * @return array|bool
	 */
	public static function modify( $name, $setting_name, $value = '' ) {
		if ( ! isset( self::$init_elements[ $name ] ) ) {
			vc_mapper()->addElementActivity( $name, 'modify', array(
				'name' => $name,
				'setting_name' => $setting_name,
				'value' => $value,
			) );

			return false;
		}
		if ( ! isset( self::$sc[ $name ] ) ) {
			return trigger_error( sprintf( __( 'Wrong name for shortcode:%s. Name required', 'js_composer' ), $name ) );
		} elseif ( 'base' === $setting_name ) {
			return trigger_error( sprintf( __( "Wrong setting_name for shortcode:%s. Base can't be modified.", 'js_composer' ), $name ) );
		}
		if ( is_array( $setting_name ) ) {
			foreach ( $setting_name as $key => $value ) {
				self::modify( $name, $key, $value );
			}
		} else {
			if ( is_array( $value ) ) {
				$value = array_merge( $value ); // fix indexes
			}
			self::$sc[ $name ][ $setting_name ] = $value;
			visual_composer()->updateShortcodeSetting( $name, $setting_name, $value );
		}

		return self::$sc;
	}

	/**
	 * Returns "|" separated list of mapped shortcode tags.
	 *
	 * @static
	 * @return string
	 */
	public static function getTagsRegexp() {
		if ( empty( self::$tags_regexp ) ) {
			self::$tags_regexp = implode( '|', array_keys( self::$sc ) );
		}

		return self::$tags_regexp;
	}

	/**
	 * Sorting method for WPBMap::generateUserData method. Called by uasort php function.
	 * @deprecated - use Vc_Sort::sortByKey since 4.4
	 * @static
	 *
	 * @param $a
	 * @param $b
	 *
	 * @return int
	 */
	public static function sort( $a, $b ) {
		// _deprecated_function( 'WPBMap::sort', '4.4 (will be removed in 4.10)', 'Vc_Sort class, :sortByKey' );
		$a_weight = isset( $a['weight'] ) ? (int) $a['weight'] : 0;
		$b_weight = isset( $b['weight'] ) ? (int) $b['weight'] : 0;
		if ( $a_weight == $b_weight ) {
			$cmpa = array_search( $a, (array) self::$user_sorted_sc );
			$cmpb = array_search( $b, (array) self::$user_sorted_sc );

			return ( $cmpa > $cmpb ) ? 1 : - 1;
		}

		return ( $a_weight < $b_weight ) ? 1 : - 1;
	}

	public static function collectCategories( &$shortcodes ) {
		$categories_list = array();
		$deprecated = 'deprecated';
		$add_deprecated = false;
		if ( is_array( $shortcodes ) && ! empty( $shortcodes ) ) {
			foreach ( $shortcodes as $name => $values ) {
				$values['_category_ids'] = array();
				if ( isset( $values['deprecated'] ) && false !== $values['deprecated'] ) {
					$add_deprecated = true;
					$values['_category_ids'][] = 'deprecated';
				} elseif ( isset( $values['category'] ) ) {
					$categories = $values['category'];
					if ( is_array( $categories ) && ! empty( $categories ) ) {
						foreach ( $categories as $c ) {
							if ( false === array_search( $c, $categories_list ) ) {
								$categories[] = $c;
							}
							$values['_category_ids'][] = md5( $c );
						}
					} else {
						if ( false === array_search( $categories, $categories_list ) ) {
							$categories_list[] = $categories;
						}
						$values['_category_ids'][] = md5( $categories );
					}
				}
				$shortcodes[ $name ] = $values;
			}
		}
		if ( $add_deprecated ) {
			$categories_list[] = $deprecated;
		}

		return $categories_list;
	}

	/**
	 * Process files/functions for lean mapping settings
	 *
	 * @since 4.9
	 *
	 * @param $tag
	 *
	 * @return bool
	 */
	public static function setElementSettings( $tag ) {
		if ( ! isset( self::$sc[ $tag ] ) ) {
			return false;
		}
		$settings = self::$sc[ $tag ];
		if ( isset( $settings['__vc_settings_function'] ) ) {
			self::$sc[ $tag ] = call_user_func( $settings['__vc_settings_function'], $tag );
		} elseif ( isset( $settings['__vc_settings_file'] ) ) {
			self::$sc[ $tag ] = include $settings['__vc_settings_file'];
		}
		self::$sc[ $tag ]['base'] = $tag;
		self::$init_elements[ $tag ] = true;
		vc_mapper()->callElementActivities( $tag );

		return true;
	}

	/**
	 * Add elements as shortcodes
	 *
	 * @since 4.9
	 */
	public static function addAllMappedShortcodes() {
		foreach ( self::$sc as $tag => $settings ) {
			if ( ! shortcode_exists( $tag ) ) {
				add_shortcode( $tag, 'vc_do_shortcode' );
			}
		}
	}
}
PK      *\4      class-vc-sort.phpnu W+A        <?php
if ( ! defined( 'ABSPATH' ) ) {
	die( '-1' );
}

/**
 * Sort array values by key, default key is 'weight'
 * Used in uasort() function.
 * For fix equal weight problem used $this->data array_search
 *
 * @since 4.4
 */

/**
 * Class Vc_Sort
 * @since 4.4
 */
class Vc_Sort {
	/**
	 * @since 4.4
	 * @var array $data - sorting data
	 */
	protected $data = array();
	/**
	 * @since 4.4
	 * @var string $key - key for search
	 */
	protected $key = 'weight';

	/**
	 * @since 4.4
	 *
	 * @param $data - array to sort
	 */
	public function __construct( $data ) {
		$this->data = $data;
	}

	/**
	 * Used to change/set data to sort
	 *
	 * @since 4.5
	 *
	 * @param $data
	 */
	public function setData( $data ) {
		$this->data = $data;
	}

	/**
	 * Sort $this->data by user key, used in class-vc-mapper.
	 * If keys are equals it SAVES a position in array (index).
	 *
	 * @since 4.4
	 *
	 * @param string $key
	 *
	 * @return array - sorted array
	 */
	public function sortByKey( $key = 'weight' ) {
		$this->key = $key;
		uasort( $this->data, array( &$this, '_key' ) );

		return array_merge( $this->data ); // reset array keys to 0..N
	}

	/**
	 * Sorting by key callable for usort function
	 * @since 4.4
	 *
	 * @param $a - compare value
	 * @param $b - compare value
	 *
	 * @return int
	 */
	private function _key( $a, $b ) {
		$a_weight = isset( $a[ $this->key ] ) ? (int) $a[ $this->key ] : 0;
		$b_weight = isset( $b[ $this->key ] ) ? (int) $b[ $this->key ] : 0;
		// To save real-ordering
		if ( $a_weight == $b_weight ) {
			$cmp_a = array_search( $a, $this->data );
			$cmp_b = array_search( $b, $this->data );

			return $cmp_a - $cmp_b;
		}

		return $b_weight - $a_weight;
	}

	/**
	 * @since 4.4
	 *
	 * @return array - sorting data
	 */
	public function getData() {
		return $this->data;
	}
}
PK      *\03      interfaces.phpnu W+A        <?php
if ( ! defined( 'ABSPATH' ) ) {
	die( '-1' );
}

/**
 * @since 4.3
 * Interface for editors
 */
interface Vc_Editor_Interface {
	/**
	 * @since 4.3
	 * @return mixed
	 */
	public function renderEditor();
}

/**
 * @since 4.3
 * Default render interface
 */
interface Vc_Render {
	/**
	 * @since 4.3
	 * @return mixed
	 */
	public function render();
}

/**
 * @since 4.3
 * Interface for third-party plugins classes loader.
 */
interface Vc_Vendor_Interface {
	/**
	 * @since 4.3
	 * @return mixed
	 */
	public function load();
}
PK      *\wB        class-vc-pages-group.phpnu W+A        <?php
if ( ! defined( 'ABSPATH' ) ) {
	die( '-1' );
}

/**
 * Class Vs_Pages_Group Show the groups of the pages likes pages with tabs.
 *
 * @since 4.5
 */
class Vc_Pages_Group extends Vc_Page {
	protected $activePage;
	protected $pages;
	protected $templatePath;

	/**
	 * @return mixed
	 */
	public function getActivePage() {
		return $this->activePage;
	}

	/**
	 * @param Vc_Page $activePage
	 *
	 * @return $this
	 */
	public function setActivePage( Vc_Page $activePage ) {
		$this->activePage = $activePage;

		return $this;
	}

	/**
	 * @return mixed
	 */
	public function getPages() {
		return $this->pages;
	}

	/**
	 * @param mixed $pages
	 *
	 * @return $this
	 */
	public function setPages( $pages ) {
		$this->pages = $pages;

		return $this;
	}

	/**
	 * @return mixed
	 */
	public function getTemplatePath() {
		return $this->templatePath;
	}

	/**
	 * @param mixed $templatePath
	 *
	 * @return $this
	 */
	public function setTemplatePath( $templatePath ) {
		$this->templatePath = $templatePath;

		return $this;
	}

	/**
	 * Render html output for current page.
	 */
	public function render() {
		vc_include_template( $this->getTemplatePath(),
			array(
				'pages' => $this->getPages(),
				'active_page' => $this->activePage,
				'page' => $this,
			) );
	}
}
PK      *\/,  ,    class-vc-post-admin.phpnu W+A        <?php
if ( ! defined( 'ABSPATH' ) ) {
	die( '-1' );
}

/**
 * Ability to interact with post data.
 *
 * @since 4.4
 */
class Vc_Post_Admin {
	/**
	 * Add hooks required to save, update and manipulate post
	 */
	public function init() {
		add_action( 'save_post', array( &$this, 'save' ) );
	}

	/**
	 * Save generated shortcodes, html and visual composer status in posts meta.
	 *
	 * @access public
	 * @since 4.4
	 *
	 * @param $post_id - current post id
	 *
	 * @return void
	 */
	public function save( $post_id ) {
		if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
			return;
		}

		// @todo fix_roles maybe check also for is vc_enabled
		if ( ! vc_user_access()
			->wpAny( array( 'edit_post', $post_id ) )
			->get()
		) {
			return;
		}
		$this->setJsStatus( $post_id );
		if ( ! ( isset( $_POST['wp-preview'] ) && 'dopreview' === $_POST['wp-preview'] ) ) {

			$this->setSettings( $post_id );
		}
		/**
		 * vc_filter: vc_base_save_post_custom_css
		 * @since 4.4
		 */
		$post_custom_css = apply_filters( 'vc_base_save_post_custom_css',
			vc_post_param( 'vc_post_custom_css' ) );
		if ( null !== $post_custom_css && empty( $post_custom_css ) ) {
			delete_post_meta( $post_id, '_wpb_post_custom_css' );
		} elseif ( null !== $post_custom_css ) {
			$post_custom_css = strip_tags( $post_custom_css );
			update_post_meta( $post_id, '_wpb_post_custom_css', $post_custom_css );
		}
		visual_composer()->buildShortcodesCustomCss( $post_id );
	}

	/**
	 * Saves VC Backend editor meta box visibility status.
	 *
	 * If post param 'wpb_vc_js_status' set to true, then methods adds/updated post
	 * meta option with tag '_wpb_vc_js_status'.
	 * @since 4.4
	 *
	 * @param $post_id
	 */
	public function setJsStatus( $post_id ) {
		$value = vc_post_param( 'wpb_vc_js_status' );
		if ( null !== $value ) {
			// Add value
			if ( '' === get_post_meta( $post_id, '_wpb_vc_js_status' ) ) {
				add_post_meta( $post_id, '_wpb_vc_js_status', $value, true );
			} // Update value
			elseif ( get_post_meta( $post_id, '_wpb_vc_js_status', true ) != $value ) {
				update_post_meta( $post_id, '_wpb_vc_js_status', $value );
			} // Delete value
			elseif ( '' === $value ) {
				delete_post_meta( $post_id, '_wpb_vc_js_status', get_post_meta( $post_id, '_wpb_vc_js_status', true ) );
			}
		}
	}

	/**
	 * Saves VC interface version which is used for building post content.
	 * @since 4.4
	 * @todo check is it used everywhere and is it needed?!
	 * @param $post_id
	 */
	public function setInterfaceVersion( $post_id ) {
		if ( null !== ( $value = vc_post_param( 'wpb_vc_js_interface_version' ) ) ) {
			update_post_meta( $post_id, '_wpb_vc_js_interface_version', $value );
		}
	}

	/**
	 * Set Post Settings for VC.
	 *
	 * It is possible to add any data to post settings by adding filter with tag 'vc_hooks_vc_post_settings'.
	 * @since 4.4
	 * vc_filter: vc_hooks_vc_post_settings - hook to override post meta settings for visual composer (used in grid for
	 *     example)
	 *
	 * @param $post_id
	 */
	public function setSettings( $post_id ) {
		$settings = array();
		$settings = apply_filters( 'vc_hooks_vc_post_settings', $settings, $post_id, get_post( $post_id ) );
		if ( is_array( $settings ) && ! empty( $settings ) ) {
			update_post_meta( $post_id, '_vc_post_settings', $settings );
		} else {
			delete_post_meta( $post_id, '_vc_post_settings' );
		}
	}
}
PK      *\Bn  Bn    class-vc-base.phpnu W+A        <?php
if ( ! defined( 'ABSPATH' ) ) {
	die( '-1' );
}

/**
 * Visual Composer basic class.
 * @since 4.2
 */
class Vc_Base {
	/**
	 * Shortcode's edit form.
	 *
	 * @since  4.2
	 * @access protected
	 * @var bool|Vc_Shortcode_Edit_Form
	 */
	protected $shortcode_edit_form = false;

	/**
	 * Templates management panel.
	 * @deprecated 4.4 updated to $templates_panel_editor, use Vc_Base::setTemplatesPanelEditor
	 * @since  4.2
	 * @access protected
	 * @var bool|Vc_Templates_Editor
	 */
	protected $templates_editor = false;
	/**
	 * Templates management panel editor.
	 * @since  4.4
	 * @access protected
	 * @var bool|Vc_Templates_Panel_Editor
	 */
	protected $templates_panel_editor = false;
	/**
	 * Post object for VC in Admin.
	 *
	 * @since  4.4
	 * @access protected
	 * @var bool|Vc_Post_Admin
	 */
	protected $post_admin = false;
	/**
	 * Post object for VC.
	 *
	 * @since  4.4.3
	 * @access protected
	 * @var bool|Vc_Post_Admin
	 */
	protected $post = false;
	/**
	 * List of shortcodes map to VC.
	 *
	 * @since  4.2
	 * @access public
	 * @var array WPBakeryShortCodeFishBones
	 */
	protected $shortcodes = array();

	/**
	 * @deprecated 4.4 due to autoload logic
	 * @var Vc_Vendors_Manager $vendor_manager
	 */
	protected $vendor_manager;

	/** @var  Vc_Shared_Templates */
	public $shared_templates;

	/**
	 * Load default object like shortcode parsing.
	 *
	 * @since  4.2
	 * @access public
	 */
	public function init() {
		do_action( 'vc_before_init_base' );
		if ( is_admin() ) {
			$this->postAdmin()->init();
		}
		add_filter( 'body_class', array(
			$this,
			'bodyClass',
		) );
		add_filter( 'the_excerpt', array(
			$this,
			'excerptFilter',
		) );
		add_action( 'wp_head', array(
			$this,
			'addMetaData',
		) );
		add_action( 'wp_head', array(
			$this,
			'addIEMinimalSupport',
		) );
		if ( is_admin() ) {
			$this->initAdmin();
		} else {
			$this->initPage();
		}
		do_action( 'vc_after_init_base' );
	}

	/**
	 * Post object for interacting with Current post data.
	 * @since 4.4
	 * @return Vc_Post_Admin
	 */
	public function postAdmin() {
		if ( false === $this->post_admin ) {
			require_once vc_path_dir( 'CORE_DIR', 'class-vc-post-admin.php' );
			$this->post_admin = new Vc_Post_Admin();
		}

		return $this->post_admin;
	}

	/**
	 * Build VC for frontend pages.
	 *
	 * @since  4.2
	 * @access public
	 */
	public function initPage() {
		do_action( 'vc_build_page' );
		add_action( 'template_redirect', array(
			$this,
			'frontCss',
		) );
		add_action( 'template_redirect', array(
			'WPBMap',
			'addAllMappedShortcodes',
		) );
		add_action( 'wp_head', array(
			$this,
			'addFrontCss',
		), 1000 );
		add_action( 'wp_head', array(
			$this,
			'addNoScript',
		), 1000 );
		add_action( 'template_redirect', array(
			$this,
			'frontJsRegister',
		) );
		add_filter( 'the_content', array(
			$this,
			'fixPContent',
		), 11 );
	}

	/**
	 * Load admin required modules and elements
	 *
	 * @since  4.2
	 * @access public
	 */
	public function initAdmin() {
		do_action( 'vc_build_admin_page' );
		// Build settings for admin page;
		//$this->registerAdminJavascript();
		//$this->registerAdminCss();

		// editors actions:
		$this->editForm()->init();
		$this->templatesPanelEditor()->init();
		$this->shared_templates->init();
		// ajax params/shortcode action
		add_action( 'wp_ajax_wpb_single_image_src', array(
			$this,
			'singleImageSrc',
		) ); // @todo move it
		add_action( 'wp_ajax_wpb_gallery_html', array(
			$this,
			'galleryHTML',
		) ); // @todo move it

		// plugins list page actions links
		add_filter( 'plugin_action_links', array(
			$this,
			'pluginActionLinks',
		), 10, 2 );
	}

	/**
	 * Setter for edit form.
	 * @since 4.2
	 *
	 * @param Vc_Shortcode_Edit_Form $form
	 */
	public function setEditForm( Vc_Shortcode_Edit_Form $form ) {
		$this->shortcode_edit_form = $form;
	}

	/**
	 * Get Shortcodes Edit form object.
	 *
	 * @see    Vc_Shortcode_Edit_Form::__construct
	 * @since  4.2
	 * @access public
	 * @return Vc_Shortcode_Edit_Form
	 */
	public function editForm() {
		return $this->shortcode_edit_form;
	}

	/**
	 * Setter for Templates editor.
	 * @deprecated 4.4 updated to panel editor see Vc_Templates_Panel_Editor::__construct
	 * @use setTemplatesPanelEditor
	 * @since 4.2
	 *
	 * @param Vc_Templates_Editor $editor
	 */
	public function setTemplatesEditor( Vc_Templates_Editor $editor ) {
		_deprecated_function( 'Vc_Base::setTemplatesEditor', '4.4 (will be removed in 5.1)', 'Vc_Base::setTemplatesPanelEditor' );
		$this->templates_editor = $editor;
	}

	/**
	 * Setter for Templates editor.
	 * @since 4.4
	 *
	 * @param Vc_Templates_Panel_Editor $editor
	 */
	public function setTemplatesPanelEditor( Vc_Templates_Panel_Editor $editor ) {
		$this->templates_panel_editor = $editor;
	}

	/**
	 * Get templates manager.
	 * @deprecated updated to panel editor see Vc_Templates_Panel_Editor::__construct
	 * @see    Vc_Templates_Editor::__construct
	 * @since  4.2
	 * @access public
	 * @return bool|Vc_Templates_Editor
	 */
	public function templatesEditor() {
		_deprecated_function( 'Vc_Base::templatesEditor', '4.4 (will be removed in 5.1)', 'Vc_Base::templatesPanelEditor' );

		return $this->templates_editor;
	}

	/**
	 * Get templates manager.
	 * @see    Vc_Templates_Panel_Editor::__construct
	 * @since  4.4
	 * @access public
	 * @return bool|Vc_Templates_Panel_Editor
	 */
	public function templatesPanelEditor() {
		return $this->templates_panel_editor;
	}

	/**
	 * Save method for edit_post action.
	 * @deprecated 4.9
	 * @since  4.2
	 * @access public
	 *
	 * @param null $post_id
	 */
	public function save( $post_id = null ) {
		_deprecated_function( '\Vc_Base::save', '4.9 (will be removed in 5.1)', '\Vc_Post_Admin::save' );
	}

	/**
	 * Add new shortcode to Visual composer.
	 *
	 * @see    WPBMap::map
	 * @since  4.2
	 * @access public
	 * @deprecated 4.9
	 *
	 * @param array $shortcode - array of options.
	 */
	public function addShortCode( array $shortcode ) {
		_deprecated_function( '\Vc_Base::addShortcode', '4.9 (will be removed in 5.1)', 'vc_map' );
		if ( ! isset( $this->shortcodes[ $shortcode['base'] ] ) ) {
			require_once vc_path_dir( 'SHORTCODES_DIR', 'shortcodes.php' );
			$this->shortcodes[ $shortcode['base'] ] = new WPBakeryShortCodeFishBones( $shortcode );
		}

	}

	/**
	 * Get shortcode class instance.
	 *
	 * @see    WPBakeryShortCodeFishBones
	 * @since  4.2
	 * @access public
	 *
	 * @param string $tag
	 *
	 * @return Vc_Shortcodes_Manager|null
	 */
	public function getShortCode( $tag ) {
		return Vc_Shortcodes_Manager::getInstance()->setTag( $tag );
	}

	/**
	 * Remove shortcode from shortcodes list of VC.
	 *
	 * @since  4.2
	 * @access public
	 *
	 * @param $tag - shortcode tag
	 */
	public function removeShortCode( $tag ) {
		remove_shortcode( $tag );
	}

	/**
	 * @todo move it
	 * @since 4.2
	 */
	public function singleImageSrc() {
		// @todo again, this method should be moved (comment added on 4.8)
		vc_user_access()->checkAdminNonce()->validateDie()->wpAny( 'edit_posts', 'edit_pages' )->validateDie();

		$image_id = (int) vc_post_param( 'content' );
		$params = vc_post_param( 'params' );
		$post_id = vc_post_param( 'post_id' );
		$img_size = vc_post_param( 'size' );
		$img = '';

		if ( ! empty( $params['source'] ) ) {
			$source = $params['source'];
		} else {
			$source = 'media_library';
		}

		switch ( $source ) {
			case 'media_library':
			case 'featured_image':

				if ( 'featured_image' === $source ) {
					if ( $post_id && has_post_thumbnail( $post_id ) ) {
						$img_id = get_post_thumbnail_id( $post_id );
					} else {
						$img_id = 0;
					}
				} else {
					$img_id = preg_replace( '/[^\d]/', '', $image_id );
				}

				if ( ! $img_size ) {
					$img_size = 'thumbnail';
				}

				if ( $img_id ) {
					$img = wp_get_attachment_image_src( $img_id, $img_size );
					if ( $img ) {
						$img = $img[0];
					}
				}

				break;

			case 'external_link':
				if ( ! empty( $params['custom_src'] ) ) {
					$img = $params['custom_src'];
				}
				break;
		}

		die( $img );
	}

	/**
	 * @todo move it
	 * @since 4.2
	 */
	public function galleryHTML() {
		// @todo again, this method should be moved (comment added on 4.8)
		vc_user_access()->checkAdminNonce()->validateDie()->wpAny( 'edit_posts', 'edit_pages' )->validateDie();

		$images = vc_post_param( 'content' );
		if ( ! empty( $images ) ) {
			echo fieldAttachedImages( explode( ',', $images ) );
		}
		die();
	}

	/**
	 * Set or modify new settings for shortcode.
	 *
	 * This function widely used by WPBMap class methods to modify shortcodes mapping
	 *
	 * @since 4.3
	 *
	 * @param $tag
	 * @param $name
	 * @param $value
	 */
	public function updateShortcodeSetting( $tag, $name, $value ) {
		Vc_Shortcodes_Manager::getInstance()->getElementClass( $tag )->setSettings( $name, $value );
	}

	/**
	 * Build custom css styles for page from shortcodes attributes created by VC editors.
	 *
	 * Called by save method, which is hooked by edit_post action.
	 * Function creates meta data for post with the key '_wpb_shortcodes_custom_css'
	 * and value as css string, which will be added to the footer of the page.
	 *
	 * @since  4.2
	 * @access public
	 *
	 * @param $post_id
	 */
	public function buildShortcodesCustomCss( $post_id ) {
		$post = get_post( $post_id );
		/**
		 * vc_filter: vc_base_build_shortcodes_custom_css
		 * @since 4.4
		 */
		$css = apply_filters( 'vc_base_build_shortcodes_custom_css', $this->parseShortcodesCustomCss( $post->post_content ) );
		if ( empty( $css ) ) {
			delete_post_meta( $post_id, '_wpb_shortcodes_custom_css' );
		} else {
			update_post_meta( $post_id, '_wpb_shortcodes_custom_css', $css );
		}
	}

	/**
	 * Parse shortcodes custom css string.
	 *
	 * This function is used by self::buildShortcodesCustomCss and creates css string from shortcodes attributes
	 * like 'css_editor'.
	 *
	 * @see    WPBakeryVisualComposerCssEditor
	 * @since  4.2
	 * @access public
	 *
	 * @param $content
	 *
	 * @return string
	 */
	public function parseShortcodesCustomCss( $content ) {
		$css = '';
		if ( ! preg_match( '/\s*(\.[^\{]+)\s*\{\s*([^\}]+)\s*\}\s*/', $content ) ) {
			return $css;
		}
		WPBMap::addAllMappedShortcodes();
		preg_match_all( '/' . get_shortcode_regex() . '/', $content, $shortcodes );
		foreach ( $shortcodes[2] as $index => $tag ) {
			$shortcode = WPBMap::getShortCode( $tag );
			$attr_array = shortcode_parse_atts( trim( $shortcodes[3][ $index ] ) );
			if ( isset( $shortcode['params'] ) && ! empty( $shortcode['params'] ) ) {
				foreach ( $shortcode['params'] as $param ) {
					if ( isset( $param['type'] ) && 'css_editor' === $param['type'] && isset( $attr_array[ $param['param_name'] ] ) ) {
						$css .= $attr_array[ $param['param_name'] ];
					}
				}
			}
		}
		foreach ( $shortcodes[5] as $shortcode_content ) {
			$css .= $this->parseShortcodesCustomCss( $shortcode_content );
		}

		return $css;
	}

	/**
	 * Hooked class method by wp_head WP action to output post custom css.
	 *
	 * Method gets post meta value for page by key '_wpb_post_custom_css' and if it is not empty
	 * outputs css string wrapped into style tag.
	 *
	 * @since  4.2
	 * @access public
	 *
	 * @param int $id
	 */
	public function addPageCustomCss( $id = null ) {
		if ( ! is_singular() ) {
			return;
		}
		if ( ! $id ) {
			$id = get_the_ID();
		}
		if ( $id ) {
			$post_custom_css = get_post_meta( $id, '_wpb_post_custom_css', true );
			if ( ! empty( $post_custom_css ) ) {
				$post_custom_css = strip_tags( $post_custom_css );
				echo '<style type="text/css" data-type="vc_custom-css">';
				echo $post_custom_css;
				echo '</style>';
			}
		}
	}

	/**
	 * Hooked class method by wp_footer WP action to output shortcodes css editor settings from page meta data.
	 *
	 * Method gets post meta value for page by key '_wpb_shortcodes_custom_css' and if it is not empty
	 * outputs css string wrapped into style tag.
	 *
	 * @since  4.2
	 * @access public
	 *
	 * @param int $id
	 *
	 */
	public function addShortcodesCustomCss( $id = null ) {
		if ( ! is_singular() ) {
			return;
		}
		if ( ! $id ) {
			$id = get_the_ID();
		}

		if ( $id ) {
			$shortcodes_custom_css = get_post_meta( $id, '_wpb_shortcodes_custom_css', true );
			if ( ! empty( $shortcodes_custom_css ) ) {
				$shortcodes_custom_css = strip_tags( $shortcodes_custom_css );
				echo '<style type="text/css" data-type="vc_shortcodes-custom-css">';
				echo $shortcodes_custom_css;
				echo '</style>';
			}
		}
	}

	/**
	 * Add css styles for current page and elements design options added w\ editor.
	 */
	public function addFrontCss() {
		$this->addPageCustomCss();
		$this->addShortcodesCustomCss();
	}

	public function addNoScript() {
		echo '<noscript>';
		echo '<style type="text/css">';
		echo ' .wpb_animate_when_almost_visible { opacity: 1; }';
		echo '</style>';
		echo '</noscript>';
	}

	/**
	 * Register front css styles.
	 *
	 * Calls wp_register_style for required css libraries files.
	 *
	 * @since  3.1
	 * @access public
	 */
	public function frontCss() {
		wp_register_style( 'flexslider', vc_asset_url( 'lib/bower/flexslider/flexslider.min.css' ), array(), WPB_VC_VERSION );
		wp_register_style( 'nivo-slider-css', vc_asset_url( 'lib/bower/nivoslider/nivo-slider.min.css' ), array(), WPB_VC_VERSION );
		wp_register_style( 'nivo-slider-theme', vc_asset_url( 'lib/bower/nivoslider/themes/default/default.min.css' ), array( 'nivo-slider-css' ), WPB_VC_VERSION );
		wp_register_style( 'prettyphoto', vc_asset_url( 'lib/prettyphoto/css/prettyPhoto.min.css' ), array(), WPB_VC_VERSION );
		wp_register_style( 'isotope-css', vc_asset_url( 'css/lib/isotope.min.css' ), array(), WPB_VC_VERSION );
		wp_register_style( 'font-awesome', vc_asset_url( 'lib/bower/font-awesome/css/font-awesome.min.css' ), array(), WPB_VC_VERSION );
		wp_register_style( 'animate-css', vc_asset_url( 'lib/bower/animate-css/animate.min.css' ), array(), WPB_VC_VERSION, false );

		$front_css_file = vc_asset_url( 'css/js_composer.min.css' );
		$upload_dir = wp_upload_dir();
		$vc_upload_dir = vc_upload_dir();
		if ( '1' === vc_settings()->get( 'use_custom' ) && is_file( $upload_dir['basedir'] . '/' . $vc_upload_dir . '/js_composer_front_custom.css' ) ) {
			$front_css_file = $upload_dir['baseurl'] . '/' . $vc_upload_dir . '/js_composer_front_custom.css';
			$front_css_file = vc_str_remove_protocol( $front_css_file );
		}
		wp_register_style( 'js_composer_front', $front_css_file, array(), WPB_VC_VERSION );

		$custom_css_path = $upload_dir['basedir'] . '/' . $vc_upload_dir . '/custom.css';
		if ( is_file( $upload_dir['basedir'] . '/' . $vc_upload_dir . '/custom.css' ) && filesize( $custom_css_path ) > 0 ) {
			$custom_css_url = $upload_dir['baseurl'] . '/' . $vc_upload_dir . '/custom.css';
			$custom_css_url = vc_str_remove_protocol( $custom_css_url );
			wp_register_style( 'js_composer_custom_css', $custom_css_url, array(), WPB_VC_VERSION );
		}
		add_action( 'wp_enqueue_scripts', array(
			$this,
			'enqueueStyle',
		) );

		/**
		 * @since 4.4
		 */
		do_action( 'vc_base_register_front_css' );
	}

	/**
	 * Enqueue base css class for VC elements and enqueue custom css if exists.
	 */
	public function enqueueStyle() {
		$post = get_post();
		if ( $post && preg_match( '/vc_row/', $post->post_content ) ) {
			wp_enqueue_style( 'js_composer_front' );
		}
		wp_enqueue_style( 'js_composer_custom_css' );
	}

	/**
	 * Register front javascript libs.
	 *
	 * Calls wp_register_script for required css libraries files.
	 *
	 * @since  3.1
	 * @access public
	 */
	public function frontJsRegister() {
		wp_register_script( 'prettyphoto', vc_asset_url( 'lib/prettyphoto/js/jquery.prettyPhoto.min.js' ), array( 'jquery' ), WPB_VC_VERSION, true );
		wp_register_script( 'waypoints', vc_asset_url( 'lib/waypoints/waypoints.min.js' ), array( 'jquery' ), WPB_VC_VERSION, true );

		// @deprecated used in old tabs
		wp_register_script( 'jquery_ui_tabs_rotate', vc_asset_url( 'lib/bower/jquery-ui-tabs-rotate/jquery-ui-tabs-rotate.min.js' ), array(
			'jquery',
			'jquery-ui-tabs',
		), WPB_VC_VERSION, true );

		// used in vc_gallery, old grid
		wp_register_script( 'isotope', vc_asset_url( 'lib/bower/isotope/dist/isotope.pkgd.min.js' ), array( 'jquery' ), WPB_VC_VERSION, true );

		wp_register_script( 'twbs-pagination', vc_asset_url( 'lib/bower/twbs-pagination/jquery.twbsPagination.min.js' ), array( 'jquery' ), WPB_VC_VERSION, true );
		wp_register_script( 'nivo-slider', vc_asset_url( 'lib/bower/nivoslider/jquery.nivo.slider.pack.js' ), array( 'jquery' ), WPB_VC_VERSION, true );
		wp_register_script( 'flexslider', vc_asset_url( 'lib/bower/flexslider/jquery.flexslider-min.js' ), array( 'jquery' ), WPB_VC_VERSION, true );
		wp_register_script( 'wpb_composer_front_js', vc_asset_url( 'js/dist/js_composer_front.min.js' ), array( 'jquery' ), WPB_VC_VERSION, true );

		/**
		 * @since 4.4
		 */
		do_action( 'vc_base_register_front_js' );
	}

	/**
	 * Register admin javascript libs.
	 *
	 * Calls wp_register_script for required css libraries files for Admin dashboard.
	 *
	 * @since  3.1
	 * vc_filter: vc_i18n_locale_composer_js_view, since 4.4 - override localization for js
	 * @access public
	 */
	public function registerAdminJavascript() {
		/**
		 * @since 4.4
		 */
		do_action( 'vc_base_register_admin_js' );

	}

	/**
	 * Register admin css styles.
	 *
	 * Calls wp_register_style for required css libraries files for admin dashboard.
	 *
	 * @since  3.1
	 * @access public
	 */
	public function registerAdminCss() {
		/**
		 * @since 4.4
		 */
		do_action( 'vc_base_register_admin_css' );
	}

	/**
	 * Add Settings link in plugin's page
	 * @since 4.2
	 *
	 * @param $links
	 * @param $file
	 *
	 * @return array
	 */
	public function pluginActionLinks( $links, $file ) {
		if ( plugin_basename( vc_path_dir( 'APP_DIR', '/js_composer.php' ) ) == $file ) {
			$title = __( 'Visual Composer Settings', 'js_composer' );
			$html = esc_html__( 'Settings', 'js_composer' );
			if ( ! vc_user_access()->part( 'settings' )->can( 'vc-general-tab' )->get() ) {
				$title = __( 'About Visual Composer', 'js_composer' );
				$html = esc_html__( 'About', 'js_composer' );
			}
			$link = '<a title="' . esc_attr( $title ) . '" href="' . esc_url( $this->getSettingsPageLink() ) . '">' . $html . '</a>';
			array_unshift( $links, $link ); // Add to top
		}

		return $links;
	}

	/**
	 * Get settings page link
	 * @since 4.2
	 * @return string url to settings page
	 */
	public function getSettingsPageLink() {
		$page = 'vc-general';
		if ( ! vc_user_access()->part( 'settings' )->can( 'vc-general-tab' )->get() ) {
			$page = 'vc-welcome';
		}

		return add_query_arg( array( 'page' => $page ), admin_url( 'admin.php' ) );
	}

	/**
	 * Hooked class method by wp_head WP action.
	 * @since  4.2
	 * @access public
	 */
	public function addMetaData() {
		echo '<meta name="generator" content="Powered by Visual Composer - drag and drop page builder for WordPress."/>' . "\n";
	}

	/**
	 * Also add fix for IE8 bootstrap styles from WPExplorer
	 * @since  4.9
	 * @access public
	 */
	public function addIEMinimalSupport() {
		echo '<!--[if lte IE 9]><link rel="stylesheet" type="text/css" href="' . vc_asset_url( 'css/vc_lte_ie9.min.css' ) . '" media="screen"><![endif]-->';
	}

	/**
	 * Method adds css class to body tag.
	 *
	 * Hooked class method by body_class WP filter. Method adds custom css class to body tag of the page to help
	 * identify and build design specially for VC shortcodes.
	 *
	 * @since  4.2
	 * @access public
	 *
	 * @param $classes
	 *
	 * @return array
	 */
	public function bodyClass( $classes ) {
		return js_composer_body_class( $classes );
	}

	/**
	 * Builds excerpt for post from content.
	 *
	 * Hooked class method by the_excerpt WP filter. When user creates content with VC all content is always wrapped by
	 * shortcodes. This methods calls do_shortcode for post's content and then creates a new excerpt.
	 *
	 * @since  4.2
	 * @access public
	 *
	 * @param $output
	 *
	 * @return string
	 */
	public function excerptFilter( $output ) {
		global $post;
		if ( empty( $output ) && ! empty( $post->post_content ) ) {
			$text = strip_tags( do_shortcode( $post->post_content ) );
			$excerpt_length = apply_filters( 'excerpt_length', 55 );
			$excerpt_more = apply_filters( 'excerpt_more', ' ' . '[...]' );
			$text = wp_trim_words( $text, $excerpt_length, $excerpt_more );

			return $text;
		}

		return $output;
	}

	/**
	 * Remove unwanted wraping with p for content.
	 *
	 * Hooked by 'the_content' filter.
	 * @since 4.2
	 *
	 * @param null $content
	 *
	 * @return string|null
	 */
	public function fixPContent( $content = null ) {
		if ( $content ) {
			$s = array(
				'/' . preg_quote( '</div>', '/' ) . '[\s\n\f]*' . preg_quote( '</p>', '/' ) . '/i',
				'/' . preg_quote( '<p>', '/' ) . '[\s\n\f]*' . preg_quote( '<div ', '/' ) . '/i',
				'/' . preg_quote( '<p>', '/' ) . '[\s\n\f]*' . preg_quote( '<section ', '/' ) . '/i',
				'/' . preg_quote( '</section>', '/' ) . '[\s\n\f]*' . preg_quote( '</p>', '/' ) . '/i',
			);
			$r = array(
				'</div>',
				'<div ',
				'<section ',
				'</section>',
			);
			$content = preg_replace( $s, $r, $content );

			return $content;
		}

		return null;
	}

	/**
	 * @todo remove this (comment added on 4.8) also remove helpers
	 * Set manger for custom third-party plugins.
	 * @deprecated due to autoload logic 4.4
	 * @since 4.3
	 *
	 * @param Vc_Vendors_Manager $vendor_manager
	 */
	public function setVendorsManager( Vc_Vendors_Manager $vendor_manager ) {
		_deprecated_function( 'Vc_Base::setVendorsManager', '4.4 (will be removed in 5.1)', 'autoload logic' );

		$this->vendor_manager = $vendor_manager;
	}

	/**
	 * @todo remove this (comment added on 4.8) also remove helpers
	 * Get vendors manager.
	 * @deprecated due to autoload logic from 4.4
	 * @since 4.3
	 * @return bool|Vc_Vendors_Manager
	 */
	public function vendorsManager() {
		_deprecated_function( 'Vc_Base::vendorsManager', '4.4 (will be removed in 5.1)', 'autoload logic' );

		return $this->vendor_manager;
	}

	/**
	 * Get array of string for locale.
	 *
	 * @since 4.7
	 *
	 * @return array
	 */
	public function getEditorsLocale() {
		return array(
			'add_remove_picture' => __( 'Add/remove picture', 'js_composer' ),
			'finish_adding_text' => __( 'Finish Adding Images', 'js_composer' ),
			'add_image' => __( 'Add Image', 'js_composer' ),
			'add_images' => __( 'Add Images', 'js_composer' ),
			'settings' => __( 'Settings', 'js_composer' ),
			'main_button_title' => __( 'Visual Composer', 'js_composer' ),
			'main_button_title_backend_editor' => __( 'BACKEND EDITOR', 'js_composer' ),
			'main_button_title_frontend_editor' => __( 'FRONTEND EDITOR', 'js_composer' ),
			'main_button_title_revert' => __( 'CLASSIC MODE', 'js_composer' ),
			'please_enter_templates_name' => __( 'Enter template name you want to save.', 'js_composer' ),
			'confirm_deleting_template' => __( 'Confirm deleting "{template_name}" template, press Cancel to leave. This action cannot be undone.', 'js_composer' ),
			'press_ok_to_delete_section' => __( 'Press OK to delete section, Cancel to leave', 'js_composer' ),
			'drag_drop_me_in_column' => __( 'Drag and drop me in the column', 'js_composer' ),
			'press_ok_to_delete_tab' => __( 'Press OK to delete "{tab_name}" tab, Cancel to leave', 'js_composer' ),
			'slide' => __( 'Slide', 'js_composer' ),
			'tab' => __( 'Tab', 'js_composer' ),
			'section' => __( 'Section', 'js_composer' ),
			'please_enter_new_tab_title' => __( 'Please enter new tab title', 'js_composer' ),
			'press_ok_delete_section' => __( 'Press OK to delete "{tab_name}" section, Cancel to leave', 'js_composer' ),
			'section_default_title' => __( 'Section', 'js_composer' ),
			'please_enter_section_title' => __( 'Please enter new section title', 'js_composer' ),
			'error_please_try_again' => __( 'Error. Please try again.', 'js_composer' ),
			'if_close_data_lost' => __( 'If you close this window all shortcode settings will be lost. Close this window?', 'js_composer' ),
			'header_select_element_type' => __( 'Select element type', 'js_composer' ),
			'header_media_gallery' => __( 'Media gallery', 'js_composer' ),
			'header_element_settings' => __( 'Element settings', 'js_composer' ),
			'add_tab' => __( 'Add tab', 'js_composer' ),
			'are_you_sure_convert_to_new_version' => __( 'Are you sure you want to convert to new version?', 'js_composer' ),
			'loading' => __( 'Loading...', 'js_composer' ),
			// Media editor
			'set_image' => __( 'Set Image', 'js_composer' ),
			'are_you_sure_reset_css_classes' => __( 'Are you sure that you want to remove all your data?', 'js_composer' ),
			'loop_frame_title' => __( 'Loop settings', 'js_composer' ),
			'enter_custom_layout' => __( 'Custom row layout', 'js_composer' ),
			'wrong_cells_layout' => __( 'Wrong row layout format! Example: 1/2 + 1/2 or span6 + span6.', 'js_composer' ),
			'row_background_color' => __( 'Row background color', 'js_composer' ),
			'row_background_image' => __( 'Row background image', 'js_composer' ),
			'column_background_color' => __( 'Column background color', 'js_composer' ),
			'column_background_image' => __( 'Column background image', 'js_composer' ),
			'guides_on' => __( 'Guides ON', 'js_composer' ),
			'guides_off' => __( 'Guides OFF', 'js_composer' ),
			'template_save' => __( 'New template successfully saved.', 'js_composer' ),
			'template_added' => __( 'Template added to the page.', 'js_composer' ),
			'template_added_with_id' => __( 'Template added to the page. Template has ID attributes, make sure that they are not used more than once on the same page.', 'js_composer' ),
			'template_removed' => __( 'Template successfully removed.', 'js_composer' ),
			'template_is_empty' => __( 'Template is empty: There is no content to be saved as a template.', 'js_composer' ),
			'template_save_error' => __( 'Error while saving template.', 'js_composer' ),
			'css_updated' => __( 'Page settings updated!', 'js_composer' ),
			'update_all' => __( 'Update all', 'js_composer' ),
			'confirm_to_leave' => __( 'The changes you made will be lost if you navigate away from this page.', 'js_composer' ),
			'inline_element_saved' => __( '%s saved!', 'js_composer' ),
			'inline_element_deleted' => __( '%s deleted!', 'js_composer' ),
			'inline_element_cloned' => __( '%s cloned. <a href="#" class="vc_edit-cloned" data-model-id="%s">Edit now?</a>', 'js_composer' ),
			'gfonts_loading_google_font_failed' => __( 'Loading Google Font failed', 'js_composer' ),
			'gfonts_loading_google_font' => __( 'Loading Font...', 'js_composer' ),
			'gfonts_unable_to_load_google_fonts' => __( 'Unable to load Google Fonts', 'js_composer' ),
			'no_title_parenthesis' => sprintf( '(%s)', __( 'no title', 'js_composer' ) ),
			'error_while_saving_image_filtered' => __( 'Error while applying filter to the image. Check your server and memory settings.', 'js_composer' ),
			'ui_saved' => sprintf( '<i class="vc-composer-icon vc-c-icon-check"></i> %s', __( 'Saved!', 'js_composer' ) ),
			'ui_danger' => sprintf( '<i class="vc-composer-icon vc-c-icon-close"></i> %s', __( 'Failed to Save!', 'js_composer' ) ),
			'delete_preset_confirmation' => __( 'You are about to delete this preset. This action can not be undone.', 'js_composer' ),
			'ui_template_downloaded' => __( 'Downloaded', 'js_composer' ),
			'ui_template_update' => __( 'Update', 'js_composer' ),
			'ui_templates_failed_to_download' => __( 'Failed to download template', 'js_composer' ),
		);
	}

}

/**
 * @todo remove this (comment added on 4.8) also remove helpers
 * VC backward capability.
 * @deprecated @since 4.3
 */
class WPBakeryVisualComposer extends Vc_Base {

	/**
	 * @deprecated since 4.3
	 */
	function __construct() {
		_deprecated_function( 'WPBakeryVisualComposer class', '4.3 (will be removed in 5.1)', 'Vc_Base class' );
	}

	/**
	 * @param $template
	 *
	 * @deprecated 4.3
	 * @return string
	 */
	public static function getUserTemplate( $template ) {
		_deprecated_function( 'WPBakeryVisualComposer getUserTemplate', '4.3 (will be removed in 5.1)', 'Vc_Base getShortcodesTemplateDir' );

		return vc_manager()->getShortcodesTemplateDir( $template );
	}
}
PK      *\zsYG   G     class-vc-shared-library.phpnu W+A        <?php
if ( ! defined( 'ABSPATH' ) ) {
	die( '-1' );
}

/*** Visual Composer Content elements refresh ***/
class VcSharedLibrary {
	// Here we will store plugin wise (shared) settings. Colors, Locations, Sizes, etc...
	/**
	 * @var array
	 */
	private static $colors = array(
		'Blue' => 'blue',
		'Turquoise' => 'turquoise',
		'Pink' => 'pink',
		'Violet' => 'violet',
		'Peacoc' => 'peacoc',
		'Chino' => 'chino',
		'Mulled Wine' => 'mulled_wine',
		'Vista Blue' => 'vista_blue',
		'Black' => 'black',
		'Grey' => 'grey',
		'Orange' => 'orange',
		'Sky' => 'sky',
		'Green' => 'green',
		'Juicy pink' => 'juicy_pink',
		'Sandy brown' => 'sandy_brown',
		'Purple' => 'purple',
		'White' => 'white',
	);

	/**
	 * @var array
	 */
	public static $icons = array(
		'Glass' => 'glass',
		'Music' => 'music',
		'Search' => 'search',
	);

	/**
	 * @var array
	 */
	public static $sizes = array(
		'Mini' => 'xs',
		'Small' => 'sm',
		'Normal' => 'md',
		'Large' => 'lg',
	);

	/**
	 * @var array
	 */
	public static $button_styles = array(
		'Rounded' => 'rounded',
		'Square' => 'square',
		'Round' => 'round',
		'Outlined' => 'outlined',
		'3D' => '3d',
		'Square Outlined' => 'square_outlined',
	);

	/**
	 * @var array
	 */
	public static $message_box_styles = array(
		'Standard' => 'standard',
		'Solid' => 'solid',
		'Solid icon' => 'solid-icon',
		'Outline' => 'outline',
		'3D' => '3d',
	);

	/**
	 * Toggle styles
	 * @var array
	 */
	public static $toggle_styles = array(
		'Default' => 'default',
		'Simple' => 'simple',
		'Round' => 'round',
		'Round Outline' => 'round_outline',
		'Rounded' => 'rounded',
		'Rounded Outline' => 'rounded_outline',
		'Square' => 'square',
		'Square Outline' => 'square_outline',
		'Arrow' => 'arrow',
		'Text Only' => 'text_only',
	);

	/**
	 * Animation styles
	 * @var array
	 */
	public static $animation_styles = array(
		'Bounce' => 'easeOutBounce',
		'Elastic' => 'easeOutElastic',
		'Back' => 'easeOutBack',
		'Cubic' => 'easeinOutCubic',
		'Quint' => 'easeinOutQuint',
		'Quart' => 'easeOutQuart',
		'Quad' => 'easeinQuad',
		'Sine' => 'easeOutSine',
	);

	/**
	 * @var array
	 */
	public static $cta_styles = array(
		'Rounded' => 'rounded',
		'Square' => 'square',
		'Round' => 'round',
		'Outlined' => 'outlined',
		'Square Outlined' => 'square_outlined',
	);

	/**
	 * @var array
	 */
	public static $txt_align = array(
		'Left' => 'left',
		'Right' => 'right',
		'Center' => 'center',
		'Justify' => 'justify',
	);

	/**
	 * @var array
	 */
	public static $el_widths = array(
		'100%' => '',
		'90%' => '90',
		'80%' => '80',
		'70%' => '70',
		'60%' => '60',
		'50%' => '50',
		'40%' => '40',
		'30%' => '30',
		'20%' => '20',
		'10%' => '10',
	);

	/**
	 * @var array
	 */
	public static $sep_widths = array(
		'1px' => '',
		'2px' => '2',
		'3px' => '3',
		'4px' => '4',
		'5px' => '5',
		'6px' => '6',
		'7px' => '7',
		'8px' => '8',
		'9px' => '9',
		'10px' => '10',
	);

	/**
	 * @var array
	 */
	public static $sep_styles = array(
		'Border' => '',
		'Dashed' => 'dashed',
		'Dotted' => 'dotted',
		'Double' => 'double',
		'Shadow' => 'shadow',
	);

	/**
	 * @var array
	 */
	public static $box_styles = array(
		'Default' => '',
		'Rounded' => 'vc_box_rounded',
		'Border' => 'vc_box_border',
		'Outline' => 'vc_box_outline',
		'Shadow' => 'vc_box_shadow',
		'Bordered shadow' => 'vc_box_shadow_border',
		'3D Shadow' => 'vc_box_shadow_3d',
	);

	/**
	 * Round box styles
	 *
	 * @var array
	 */
	public static $round_box_styles = array(
		'Round' => 'vc_box_circle',
		'Round Border' => 'vc_box_border_circle',
		'Round Outline' => 'vc_box_outline_circle',
		'Round Shadow' => 'vc_box_shadow_circle',
		'Round Border Shadow' => 'vc_box_shadow_border_circle',
	);

	/**
	 * Circle box styles
	 *
	 * @var array
	 */
	public static $circle_box_styles = array(
		'Circle' => 'vc_box_circle_2',
		'Circle Border' => 'vc_box_border_circle_2',
		'Circle Outline' => 'vc_box_outline_circle_2',
		'Circle Shadow' => 'vc_box_shadow_circle_2',
		'Circle Border Shadow' => 'vc_box_shadow_border_circle_2',
	);

	/**
	 * @return array
	 */
	public static function getColors() {
		return self::$colors;
	}

	/**
	 * @return array
	 */
	public static function getIcons() {
		return self::$icons;
	}

	/**
	 * @return array
	 */
	public static function getSizes() {
		return self::$sizes;
	}

	/**
	 * @return array
	 */
	public static function getButtonStyles() {
		return self::$button_styles;
	}

	/**
	 * @return array
	 */
	public static function getMessageBoxStyles() {
		return self::$message_box_styles;
	}

	/**
	 * @return array
	 */
	public static function getToggleStyles() {
		return self::$toggle_styles;
	}

	/**
	 * @return array
	 */
	public static function getAnimationStyles() {
		return self::$animation_styles;
	}

	/**
	 * @return array
	 */
	public static function getCtaStyles() {
		return self::$cta_styles;
	}

	/**
	 * @return array
	 */
	public static function getTextAlign() {
		return self::$txt_align;
	}

	/**
	 * @return array
	 */
	public static function getBorderWidths() {
		return self::$sep_widths;
	}

	/**
	 * @return array
	 */
	public static function getElementWidths() {
		return self::$el_widths;
	}

	/**
	 * @return array
	 */
	public static function getSeparatorStyles() {
		return self::$sep_styles;
	}

	/**
	 * Get list of box styles
	 *
	 * Possible $groups values:
	 * - default
	 * - round
	 * - circle
	 *
	 * @param array $groups Array of groups to include. If not specified, return all
	 *
	 * @return array
	 */
	public static function getBoxStyles( $groups = array() ) {
		$list = array();
		$groups = (array) $groups;

		if ( ! $groups || in_array( 'default', $groups ) ) {
			$list += self::$box_styles;
		}

		if ( ! $groups || in_array( 'round', $groups ) ) {
			$list += self::$round_box_styles;
		}

		if ( ! $groups || in_array( 'cirlce', $groups ) ) {
			$list += self::$circle_box_styles;
		}

		return $list;
	}

	public static function getColorsDashed() {
		$colors = array(
			__( 'Blue', 'js_composer' ) => 'blue',
			__( 'Turquoise', 'js_composer' ) => 'turquoise',
			__( 'Pink', 'js_composer' ) => 'pink',
			__( 'Violet', 'js_composer' ) => 'violet',
			__( 'Peacoc', 'js_composer' ) => 'peacoc',
			__( 'Chino', 'js_composer' ) => 'chino',
			__( 'Mulled Wine', 'js_composer' ) => 'mulled-wine',
			__( 'Vista Blue', 'js_composer' ) => 'vista-blue',
			__( 'Black', 'js_composer' ) => 'black',
			__( 'Grey', 'js_composer' ) => 'grey',
			__( 'Orange', 'js_composer' ) => 'orange',
			__( 'Sky', 'js_composer' ) => 'sky',
			__( 'Green', 'js_composer' ) => 'green',
			__( 'Juicy pink', 'js_composer' ) => 'juicy-pink',
			__( 'Sandy brown', 'js_composer' ) => 'sandy-brown',
			__( 'Purple', 'js_composer' ) => 'purple',
			__( 'White', 'js_composer' ) => 'white',
		);

		return $colors;
	}
}

/**
 * @param string $asset
 *
 * @return array
 */
function getVcShared( $asset = '' ) {
	switch ( $asset ) {
		case 'colors':
			return VcSharedLibrary::getColors();
			break;

		case 'colors-dashed':
			return VcSharedLibrary::getColorsDashed();
			break;

		case 'icons':
			return VcSharedLibrary::getIcons();
			break;

		case 'sizes':
			return VcSharedLibrary::getSizes();
			break;

		case 'button styles':
		case 'alert styles':
			return VcSharedLibrary::getButtonStyles();
			break;
		case 'message_box_styles':
			return VcSharedLibrary::getMessageBoxStyles();
			break;
		case 'cta styles':
			return VcSharedLibrary::getCtaStyles();
			break;

		case 'text align':
			return VcSharedLibrary::getTextAlign();
			break;

		case 'cta widths':
		case 'separator widths':
			return VcSharedLibrary::getElementWidths();
			break;

		case 'separator styles':
			return VcSharedLibrary::getSeparatorStyles();
			break;

		case 'separator border widths':
			return VcSharedLibrary::getBorderWidths();
			break;

		case 'single image styles':
			return VcSharedLibrary::getBoxStyles();
			break;

		case 'single image external styles':
			return VcSharedLibrary::getBoxStyles( array( 'default', 'round' ) );
			break;

		case 'toggle styles':
			return VcSharedLibrary::getToggleStyles();
			break;

		case 'animation styles':
			return VcSharedLibrary::getAnimationStyles();
			break;

		default:
			# code...
			break;
	}

	return '';
}
PK      *\xmIC      class-vc-mapper.phpnu W+A        <?php
if ( ! defined( 'ABSPATH' ) ) {
	die( '-1' );
}

/**
 * WPBakery Visual Composer Main manager.
 *
 * @package WPBakeryVisualComposer
 * @since   4.2
 */

/**
 * Vc mapper new class. On maintenance
 * Allows to bind hooks for shortcodes.
 * @since 4.2
 */
class Vc_Mapper {
	/**
	 * @since 4.2
	 * Stores mapping activities list which where called before initialization
	 * @var array
	 */
	protected $init_activity = array();
	/**
	 *
	 *
	 * @since 4.9
	 *
	 * @var array
	 */
	protected $element_activities = array();

	protected $hasAccess = array();

	// @todo fix_roles and maybe remove/@deprecate this
	protected $checkForAccess = true;

	/**
	 * @since 4.2
	 */
	function __construct() {
	}

	/**
	 * Include params list objects and calls all stored activity methods.
	 *
	 * @since  4.2
	 * @access public
	 */
	public function init() {
		do_action( 'vc_mapper_init_before' );
		require_once vc_path_dir( 'PARAMS_DIR', 'load.php' );
		WPBMap::setInit();
		require_once vc_path_dir( 'CONFIG_DIR', 'lean-map.php' );
		$this->callActivities();
		do_action( 'vc_mapper_init_after' );
	}

	/**
	 * This method is called by VC objects methods if it is called before VC initialization.
	 *
	 * @see WPBMAP
	 * @since  4.2
	 * @access public
	 *
	 * @param $object - mame of class object
	 * @param $method - method name
	 * @param array $params - list of attributes for object method
	 */
	public function addActivity( $object, $method, $params = array() ) {
		$this->init_activity[] = array(
			$object,
			$method,
			$params,
		);
	}

	/**
	 * This method is called by VC objects methods if it is called before VC initialization.
	 *
	 * @see WPBMAP
	 * @since  4.9
	 * @access public
	 *
	 * @param $tag - shortcode tag of element
	 * @param $method - method name
	 * @param array $params - list of attributes for object method
	 */
	public function addElementActivity( $tag, $method, $params = array() ) {
		if ( ! isset( $this->element_activities[ $tag ] ) ) {
			$this->element_activities[ $tag ] = array();
		}
		$this->element_activities[ $tag ][] = array(
			$method,
			$params,
		);
	}

	/**
	 * Call all stored activities.
	 *
	 * Called by init method. List of activities stored by $init_activity are created by other objects called after
	 * initialization.
	 *
	 * @since  4.2
	 * @access public
	 */
	protected function callActivities() {
		do_action( 'vc_mapper_call_activities_before' );
		while ( $activity = each( $this->init_activity ) ) {
			list( $object, $method, $params ) = $activity[1];
			if ( 'mapper' === $object ) {
				switch ( $method ) {
					case 'map':
						WPBMap::map( $params['tag'], $params['attributes'] );
						break;
					case 'drop_param':
						WPBMap::dropParam( $params['name'], $params['attribute_name'] );
						break;
					case 'add_param':
						WPBMap::addParam( $params['name'], $params['attribute'] );
						break;
					case 'mutate_param':
						WPBMap::mutateParam( $params['name'], $params['attribute'] );
						break;
					case 'drop_all_shortcodes':
						WPBMap::dropAllShortcodes();
						break;
					case 'drop_shortcode':
						WPBMap::dropShortcode( $params['name'] );
						break;
					case 'modify':
						WPBMap::modify( $params['name'], $params['setting_name'], $params['value'] );
						break;
				}
			}
		}
	}

	/**
	 * Does user has access to modify/clone/delete/add shortcode
	 *
	 * @param $shortcode
	 *
	 * @todo fix_roles and maybe remove/@deprecate this
	 * @since 4.5
	 * @return bool
	 */
	public function userHasAccess( $shortcode ) {
		if ( $this->isCheckForAccess() ) {
			if ( isset( $this->hasAccess[ $shortcode ] ) ) {
				return $this->hasAccess[ $shortcode ];
			} else {
				$this->hasAccess[ $shortcode ] = vc_user_access_check_shortcode_edit( $shortcode );
			}

			return $this->hasAccess[ $shortcode ];
		}

		return true;
	}

	/**
	 * @todo fix_roles and maybe remove/@deprecate this
	 * @since 4.5
	 * @return bool
	 */
	public function isCheckForAccess() {
		return $this->checkForAccess;
	}

	/**
	 * @todo fix_roles and maybe remove/@deprecate this
	 * @since 4.5
	 *
	 * @param bool $checkForAccess
	 */
	public function setCheckForAccess( $checkForAccess ) {
		$this->checkForAccess = $checkForAccess;
	}

	public function callElementActivities( $tag ) {
		do_action( 'vc_mapper_call_activities_before' );
		if ( isset( $this->element_activities[ $tag ] ) ) {
			while ( $activity = each( $this->element_activities[ $tag ] ) ) {
				list( $method, $params ) = $activity[1];
				switch ( $method ) {
					case 'drop_param':
						WPBMap::dropParam( $params['name'], $params['attribute_name'] );
						break;
					case 'add_param':
						WPBMap::addParam( $params['name'], $params['attribute'] );
						break;
					case 'mutate_param':
						WPBMap::mutateParam( $params['name'], $params['attribute'] );
						break;
					case 'drop_shortcode':
						WPBMap::dropShortcode( $params['name'] );
						break;
					case 'modify':
						WPBMap::modify( $params['name'], $params['setting_name'], $params['value'] );
						break;
				}
			}
		}

	}
}
PK      *\?Xct  t  .  shared-templates/class-vc-shared-templates.phpnu W+A        <?php
if ( ! defined( 'ABSPATH' ) ) {
	die( '-1' );
}

require_once dirname( __FILE__ ) . '/importer/wordpress-importer.php';
require_once dirname( __FILE__ ) . '/importer/plugin.php';

/**
 * Class Vc_Shared_Templates
 */
class Vc_Shared_Templates {
	/**
	 * @var bool
	 */
	protected $initialized = false;

	/**
	 * @var string
	 */
	protected $download_link_url = 'http://support.wpbakery.com/templates/download-link';

	/**
	 *
	 */
	public function init() {
		if ( $this->initialized ) {
			return;
		}
		$this->initialized = true;

		add_filter( 'vc_templates_render_category', array(
			$this,
			'renderTemplateBlock',
		), 10 );

		add_filter( 'vc_templates_render_frontend_template', array(
			$this,
			'renderFrontendTemplate',
		), 10, 2 );

		add_filter( 'vc_templates_render_backend_template', array(
			$this,
			'renderBackendTemplate',
		), 10, 2 );
		add_filter( 'vc_templates_render_backend_template_preview', array(
			$this,
			'renderBackendTemplate',
		), 10, 2 );
		add_action( 'vc_templates_delete_templates', array(
			$this,
			'delete',
		), 10, 2 );
		/*
		 *
				add_action( 'wp_ajax_vc_frontend_load_template', array(
					$this,
					'renderFrontendTemplate',
				) );
		*/

		add_filter( 'wp_ajax_vc_shared_templates_download', array(
			$this,
			'ajaxDownloadTemplate',
		) );
		add_filter( 'vc_get_all_templates', array(
			$this,
			'addTemplatesTab',
		) );

		$this->registerPostType();
	}

	public function renderBackendTemplate( $templateId, $templateType ) {
		if ( 'shared_templates' === $templateType ) {
			$templates = get_posts( array(
				'post_type' => 'vc4_templates',
				'include' => intval( $templateId ),
				'numberposts' => 1,
			) );
			if ( ! empty( $templates ) ) {
				$template = $templates[0];

				return $template->post_content;
			}
			wp_send_json_error( array(
				'code' => 'Wrong ID or no Template found',
			) );
		}

		return $templateId;
	}

	public function renderFrontendTemplate( $templateId, $templateType ) {
		if ( 'shared_templates' === $templateType ) {
			$templates = get_posts( array(
				'post_type' => 'vc4_templates',
				'include' => intval( $templateId ),
				'numberposts' => 1,
			) );
			if ( ! empty( $templates ) ) {
				$template = $templates[0];

				vc_frontend_editor()->setTemplateContent( $template->post_content );
				vc_frontend_editor()->enqueueRequired();
				vc_include_template( 'editors/frontend_template.tpl.php', array(
					'editor' => vc_frontend_editor(),
				) );
				die();
			}
			wp_send_json_error( array(
				'code' => 'Wrong ID or no Template found #3',
			) );
		}

		return $templateId;
	}

	public function delete( $templateId, $templateType ) {
		if ( 'shared_templates' === $templateType ) {
			$templates = get_posts( array(
				'post_type' => 'vc4_templates',
				'include' => intval( $templateId ),
				'numberposts' => 1,
			) );
			if ( ! empty( $templates ) ) {
				$template = $templates[0];
				if ( wp_delete_post( $template->ID ) ) {
					wp_send_json_success();
				}
			}
			wp_send_json_error( array(
				'code' => 'Wrong ID or no Template found #2',
			) );
		}

		return $templateId;
	}

	/**
	 * Post type from templates registration in wordpress
	 */
	private function registerPostType() {
		register_post_type( 'vc4_templates', array(
			'label' => 'Vc Templates',
			'public' => false,
			'publicly_queryable' => false,
			'exclude_from_search' => false,
			'show_ui' => false,
			'show_in_menu' => false,
			'menu_position' => 10,
			'menu_icon' => 'dashicons-admin-page',
			'hierarchical' => false,
			'taxonomies' => array(),
			'has_archive' => false,
			'rewrite' => false,
			'query_var' => false,
			'show_in_nav_menus' => false,
		) );
	}

	/**
	 * Ajax request processing from templates panel
	 */
	public function ajaxDownloadTemplate() {
		/** @var Vc_Current_User_Access $access */
		$access = vc_user_access()->checkAdminNonce()->validateDie( json_encode( array(
			'success' => false,
			'message' => 'access denied',
		) ) )->part( 'templates' )->checkStateAny( true, null )->validateDie( json_encode( array(
			'success' => false,
			'message' => 'part access denied',
		) ) )->check( array(
			vc_license(),
			'isActivated',
		) );
		$access->validateDie( json_encode( array(
			'success' => false,
			'message' => 'license is not activated',
		) ) );

		$templateId = vc_request_param( 'id' );
		$requestUrl = $this->getTemplateDownloadLink( $templateId );
		$status = false;
		$file = $this->downloadTemplate( $requestUrl );
		$data = array();
		if ( $file ) {
			new Vc_WXR_Parser_Plugin();
			$importer = new Vc_WP_Import();
			ob_start();
			$importer->import( $file );
			if ( ! empty( $importer->processed_posts ) ) {
				$status = true;
				$postId = reset( $importer->processed_posts );
				$data['post_id'] = $postId;
			}
			ob_end_clean();
		}

		if ( $status ) {
			wp_send_json_success( $data );
		} else {
			wp_send_json_error();
		}
	}

	/**
	 * @param $requestUrl
	 *
	 * @return bool|string
	 */
	private function downloadTemplate( $requestUrl ) {
		$downloadUrlRequest = wp_remote_get( $requestUrl );
		if ( is_array( $downloadUrlRequest ) && 200 === $downloadUrlRequest['response']['code'] ) {
			return $this->parseRequest( $downloadUrlRequest );
		}

		return false;
	}

	/**
	 * @param $request
	 *
	 * @return bool|string
	 */
	private function parseRequest( $request ) {
		$body = json_decode( $request['body'], true );
		if ( isset( $body['status'], $body['url'] ) && 1 === $body['status'] ) {
			$downloadUrl = $body['url'];
			$downloadedTemplateFile = download_url( $downloadUrl );
			if ( is_wp_error( $downloadedTemplateFile ) || ! $downloadedTemplateFile ) {
				return false;
			}

			return $downloadedTemplateFile;
		}

		return false;
	}

	/**
	 * @param $data
	 *
	 * @return array
	 */
	public function addTemplatesTab( $data ) {
		$newCategory = array(
			'category' => 'shared_templates',
			'category_name' => __( 'Template library', 'js_composer' ),
			'category_weight' => 10,
			'templates' => $this->getTemplates(),
		);
		$data[] = $newCategory;

		return $data;
	}

	/**
	 * @param $category
	 *
	 * @return mixed
	 */
	public function renderTemplateBlock( $category ) {
		if ( 'shared_templates' === $category['category'] ) {
			$category['output'] = $this->getTemplateBlockTemplate();
		}

		return $category;
	}

	/**
	 * @return string
	 */
	private function getTemplateBlockTemplate() {
		ob_start();
		vc_include_template( 'editors/popups/shared-templates/category.tpl.php', array(
			'controller' => $this,
			'templates' => $this->getTemplates(),
		) );

		return ob_get_clean();
	}

	public function getTemplates() {
		$posts = get_posts( 'post_type=vc4_templates&numberposts=-1' );
		$templates = array();
		if ( ! empty( $posts ) ) {
			foreach ( $posts as $post ) {
				/** @var WP_Post $post */
				$id = get_post_meta( $post->ID, '_vc4_templates-id', true );
				$template = array();
				$template['title'] = $post->post_title;
				$template['version'] = get_post_meta( $post->ID, '_vc4_templates-version', true );
				$template['id'] = $id;
				$template['post_id'] = $post->ID;
				$template['name'] = $post->post_title; // For Settings
				$template['type'] = 'shared_templates'; // For Settings
				$template['unique_id'] = $id; // For Settings
				$templates[] = $template;
			}
		}

		return $templates;
	}

	/**
	 * Create url for request to download
	 * It requires a license key, product and version
	 *
	 * @param $id
	 *
	 * @return string
	 */
	private function getTemplateDownloadLink( $id ) {
		$url = esc_url( vc_license()->getSiteUrl() );
		$key = rawurlencode( vc_license()->getLicenseKey() );

		$url = $this->download_link_url . '?product=vc&url=' . $url . '&key=' . $key . '&version=' . WPB_VC_VERSION . '&id=' . esc_attr( $id );

		return $url;
	}
}
PK      *\>D{_  _  %  shared-templates/importer/parsers.phpnu W+A        <?php
if ( ! defined( 'ABSPATH' ) ) {
	die( '-1' );
}

/**
 * WordPress eXtended RSS file parser implementations
 *
 * @package WordPress
 * @subpackage Importer
 */

/**
 * WordPress Importer class for managing parsing of WXR files.
 */
class Vc_WXR_Parser {
	function parse( $file ) {
		// Attempt to use proper XML parsers first
		if ( extension_loaded( 'simplexml' ) ) {
			$parser = new Vc_WXR_Parser_SimpleXML;
			$result = $parser->parse( $file );

			// If SimpleXML succeeds or this is an invalid WXR file then return the results
			if ( ! is_wp_error( $result ) || 'SimpleXML_parse_error' != $result->get_error_code() ) {
				return $result;
			}
		} else if ( extension_loaded( 'xml' ) ) {
			$parser = new Vc_WXR_Parser_XML;
			$result = $parser->parse( $file );

			// If XMLParser succeeds or this is an invalid WXR file then return the results
			if ( ! is_wp_error( $result ) || 'XML_parse_error' != $result->get_error_code() ) {
				return $result;
			}
		}

		// We have a malformed XML file, so display the error and fallthrough to regex
		if ( isset( $result ) && defined( 'IMPORT_DEBUG' ) && IMPORT_DEBUG ) {
			echo '<pre>';
			if ( 'SimpleXML_parse_error' == $result->get_error_code() ) {
				foreach ( $result->get_error_data() as $error ) {
					echo $error->line . ':' . $error->column . ' ' . esc_html( $error->message ) . "\n";
				}
			} else if ( 'XML_parse_error' == $result->get_error_code() ) {
				$error = $result->get_error_data();
				echo $error[0] . ':' . $error[1] . ' ' . esc_html( $error[2] );
			}
			echo '</pre>';
			echo '<p><strong>' . __( 'There was an error when reading this WXR file', 'wordpress-importer' ) . '</strong><br />';
			echo __( 'Details are shown above. The importer will now try again with a different parser...', 'wordpress-importer' ) . '</p>';
		}

		// use regular expressions if nothing else available or this is bad XML
		$parser = new Vc_WXR_Parser_Regex;

		return $parser->parse( $file );
	}
}

/**
 * WXR Parser that makes use of the SimpleXML PHP extension.
 */
class Vc_WXR_Parser_SimpleXML {
	function parse( $file ) {
		$authors = $posts = $categories = $tags = $terms = array();

		$internal_errors = libxml_use_internal_errors( true );

		$dom = new DOMDocument;
		$old_value = null;
		if ( function_exists( 'libxml_disable_entity_loader' ) ) {
			$old_value = libxml_disable_entity_loader( true );
		}
		$success = $dom->loadXML( file_get_contents( $file ) );
		if ( ! is_null( $old_value ) ) {
			libxml_disable_entity_loader( $old_value );
		}

		if ( ! $success || isset( $dom->doctype ) ) {
			return new WP_Error( 'SimpleXML_parse_error', __( 'There was an error when reading this WXR file', 'wordpress-importer' ), libxml_get_errors() );
		}

		$xml = simplexml_import_dom( $dom );
		unset( $dom );

		// halt if loading produces an error
		if ( ! $xml ) {
			return new WP_Error( 'SimpleXML_parse_error', __( 'There was an error when reading this WXR file', 'wordpress-importer' ), libxml_get_errors() );
		}

		$wxr_version = $xml->xpath( '/rss/channel/wp:wxr_version' );
		if ( ! $wxr_version ) {
			return new WP_Error( 'WXR_parse_error', __( 'This does not appear to be a WXR file, missing/invalid WXR version number', 'wordpress-importer' ) );
		}

		$wxr_version = (string) trim( $wxr_version[0] );
		// confirm that we are dealing with the correct file format
		if ( ! preg_match( '/^\d+\.\d+$/', $wxr_version ) ) {
			return new WP_Error( 'WXR_parse_error', __( 'This does not appear to be a WXR file, missing/invalid WXR version number', 'wordpress-importer' ) );
		}

		$base_url = $xml->xpath( '/rss/channel/wp:base_site_url' );
		$base_url = (string) trim( $base_url[0] );

		$namespaces = $xml->getDocNamespaces();
		if ( ! isset( $namespaces['wp'] ) ) {
			$namespaces['wp'] = 'http://wordpress.org/export/1.1/';
		}
		if ( ! isset( $namespaces['excerpt'] ) ) {
			$namespaces['excerpt'] = 'http://wordpress.org/export/1.1/excerpt/';
		}

		// grab authors
		foreach ( $xml->xpath( '/rss/channel/wp:author' ) as $author_arr ) {
			$a = $author_arr->children( $namespaces['wp'] );
			$login = (string) $a->author_login;
			$authors[ $login ] = array(
				'author_id' => (int) $a->author_id,
				'author_login' => $login,
				'author_email' => (string) $a->author_email,
				'author_display_name' => (string) $a->author_display_name,
				'author_first_name' => (string) $a->author_first_name,
				'author_last_name' => (string) $a->author_last_name,
			);
		}

		// grab cats, tags and terms
		foreach ( $xml->xpath( '/rss/channel/wp:category' ) as $term_arr ) {
			$t = $term_arr->children( $namespaces['wp'] );
			$category = array(
				'term_id' => (int) $t->term_id,
				'category_nicename' => (string) $t->category_nicename,
				'category_parent' => (string) $t->category_parent,
				'cat_name' => (string) $t->cat_name,
				'category_description' => (string) $t->category_description,
			);

			foreach ( $t->termmeta as $meta ) {
				$category['termmeta'][] = array(
					'key' => (string) $meta->meta_key,
					'value' => (string) $meta->meta_value,
				);
			}

			$categories[] = $category;
		}

		foreach ( $xml->xpath( '/rss/channel/wp:tag' ) as $term_arr ) {
			$t = $term_arr->children( $namespaces['wp'] );
			$tag = array(
				'term_id' => (int) $t->term_id,
				'tag_slug' => (string) $t->tag_slug,
				'tag_name' => (string) $t->tag_name,
				'tag_description' => (string) $t->tag_description,
			);

			foreach ( $t->termmeta as $meta ) {
				$tag['termmeta'][] = array(
					'key' => (string) $meta->meta_key,
					'value' => (string) $meta->meta_value,
				);
			}

			$tags[] = $tag;
		}

		foreach ( $xml->xpath( '/rss/channel/wp:term' ) as $term_arr ) {
			$t = $term_arr->children( $namespaces['wp'] );
			$term = array(
				'term_id' => (int) $t->term_id,
				'term_taxonomy' => (string) $t->term_taxonomy,
				'slug' => (string) $t->term_slug,
				'term_parent' => (string) $t->term_parent,
				'term_name' => (string) $t->term_name,
				'term_description' => (string) $t->term_description,
			);

			foreach ( $t->termmeta as $meta ) {
				$term['termmeta'][] = array(
					'key' => (string) $meta->meta_key,
					'value' => (string) $meta->meta_value,
				);
			}

			$terms[] = $term;
		}

		// grab posts
		foreach ( $xml->channel->item as $item ) {
			$post = array(
				'post_title' => (string) $item->title,
				'guid' => (string) $item->guid,
			);

			$dc = $item->children( 'http://purl.org/dc/elements/1.1/' );
			$post['post_author'] = (string) $dc->creator;

			$content = $item->children( 'http://purl.org/rss/1.0/modules/content/' );
			$excerpt = $item->children( $namespaces['excerpt'] );
			$post['post_content'] = (string) $content->encoded;
			$post['post_excerpt'] = (string) $excerpt->encoded;

			$wp = $item->children( $namespaces['wp'] );
			$post['post_id'] = (int) $wp->post_id;
			$post['post_date'] = (string) $wp->post_date;
			$post['post_date_gmt'] = (string) $wp->post_date_gmt;
			$post['comment_status'] = (string) $wp->comment_status;
			$post['ping_status'] = (string) $wp->ping_status;
			$post['post_name'] = (string) $wp->post_name;
			$post['status'] = (string) $wp->status;
			$post['post_parent'] = (int) $wp->post_parent;
			$post['menu_order'] = (int) $wp->menu_order;
			$post['post_type'] = (string) $wp->post_type;
			$post['post_password'] = (string) $wp->post_password;
			$post['is_sticky'] = (int) $wp->is_sticky;

			if ( isset( $wp->attachment_url ) ) {
				$post['attachment_url'] = (string) $wp->attachment_url;
			}

			foreach ( $item->category as $c ) {
				$att = $c->attributes();
				if ( isset( $att['nicename'] ) ) {
					$post['terms'][] = array(
						'name' => (string) $c,
						'slug' => (string) $att['nicename'],
						'domain' => (string) $att['domain'],
					);
				}
			}

			foreach ( $wp->postmeta as $meta ) {
				$post['postmeta'][] = array(
					'key' => (string) $meta->meta_key,
					'value' => (string) $meta->meta_value,
				);
			}

			foreach ( $wp->comment as $comment ) {
				$meta = array();
				if ( isset( $comment->commentmeta ) ) {
					foreach ( $comment->commentmeta as $m ) {
						$meta[] = array(
							'key' => (string) $m->meta_key,
							'value' => (string) $m->meta_value,
						);
					}
				}

				$post['comments'][] = array(
					'comment_id' => (int) $comment->comment_id,
					'comment_author' => (string) $comment->comment_author,
					'comment_author_email' => (string) $comment->comment_author_email,
					'comment_author_IP' => (string) $comment->comment_author_IP,
					'comment_author_url' => (string) $comment->comment_author_url,
					'comment_date' => (string) $comment->comment_date,
					'comment_date_gmt' => (string) $comment->comment_date_gmt,
					'comment_content' => (string) $comment->comment_content,
					'comment_approved' => (string) $comment->comment_approved,
					'comment_type' => (string) $comment->comment_type,
					'comment_parent' => (string) $comment->comment_parent,
					'comment_user_id' => (int) $comment->comment_user_id,
					'commentmeta' => $meta,
				);
			}

			$posts[] = $post;
		}

		return array(
			'authors' => $authors,
			'posts' => $posts,
			'categories' => $categories,
			'tags' => $tags,
			'terms' => $terms,
			'base_url' => $base_url,
			'version' => $wxr_version,
		);
	}
}

/**
 * WXR Parser that makes use of the XML Parser PHP extension.
 */
class Vc_WXR_Parser_XML {
	var $wp_tags = array(
		'wp:post_id',
		'wp:post_date',
		'wp:post_date_gmt',
		'wp:comment_status',
		'wp:ping_status',
		'wp:attachment_url',
		'wp:status',
		'wp:post_name',
		'wp:post_parent',
		'wp:menu_order',
		'wp:post_type',
		'wp:post_password',
		'wp:is_sticky',
		'wp:term_id',
		'wp:category_nicename',
		'wp:category_parent',
		'wp:cat_name',
		'wp:category_description',
		'wp:tag_slug',
		'wp:tag_name',
		'wp:tag_description',
		'wp:term_taxonomy',
		'wp:term_parent',
		'wp:term_name',
		'wp:term_description',
		'wp:author_id',
		'wp:author_login',
		'wp:author_email',
		'wp:author_display_name',
		'wp:author_first_name',
		'wp:author_last_name',
	);
	var $wp_sub_tags = array(
		'wp:comment_id',
		'wp:comment_author',
		'wp:comment_author_email',
		'wp:comment_author_url',
		'wp:comment_author_IP',
		'wp:comment_date',
		'wp:comment_date_gmt',
		'wp:comment_content',
		'wp:comment_approved',
		'wp:comment_type',
		'wp:comment_parent',
		'wp:comment_user_id',
	);

	function parse( $file ) {
		$this->wxr_version = $this->in_post = $this->cdata = $this->data = $this->sub_data = $this->in_tag = $this->in_sub_tag = false;
		$this->authors = $this->posts = $this->term = $this->category = $this->tag = array();

		$xml = xml_parser_create( 'UTF-8' );
		xml_parser_set_option( $xml, XML_OPTION_SKIP_WHITE, 1 );
		xml_parser_set_option( $xml, XML_OPTION_CASE_FOLDING, 0 );
		xml_set_object( $xml, $this );
		xml_set_character_data_handler( $xml, 'cdata' );
		xml_set_element_handler( $xml, 'tag_open', 'tag_close' );

		if ( ! xml_parse( $xml, file_get_contents( $file ), true ) ) {
			$current_line = xml_get_current_line_number( $xml );
			$current_column = xml_get_current_column_number( $xml );
			$error_code = xml_get_error_code( $xml );
			$error_string = xml_error_string( $error_code );

			return new WP_Error( 'XML_parse_error', 'There was an error when reading this WXR file', array(
				$current_line,
				$current_column,
				$error_string,
			) );
		}
		xml_parser_free( $xml );

		if ( ! preg_match( '/^\d+\.\d+$/', $this->wxr_version ) ) {
			return new WP_Error( 'WXR_parse_error', __( 'This does not appear to be a WXR file, missing/invalid WXR version number', 'wordpress-importer' ) );
		}

		return array(
			'authors' => $this->authors,
			'posts' => $this->posts,
			'categories' => $this->category,
			'tags' => $this->tag,
			'terms' => $this->term,
			'base_url' => $this->base_url,
			'version' => $this->wxr_version,
		);
	}

	function tag_open( $parse, $tag, $attr ) {
		if ( in_array( $tag, $this->wp_tags ) ) {
			$this->in_tag = substr( $tag, 3 );

			return;
		}

		if ( in_array( $tag, $this->wp_sub_tags ) ) {
			$this->in_sub_tag = substr( $tag, 3 );

			return;
		}

		switch ( $tag ) {
			case 'category':
				if ( isset( $attr['domain'], $attr['nicename'] ) ) {
					$this->sub_data['domain'] = $attr['domain'];
					$this->sub_data['slug'] = $attr['nicename'];
				}
				break;
			case 'item':
				$this->in_post = true;
			case 'title':
				if ( $this->in_post ) {
					$this->in_tag = 'post_title';
				}
				break;
			case 'guid':
				$this->in_tag = 'guid';
				break;
			case 'dc:creator':
				$this->in_tag = 'post_author';
				break;
			case 'content:encoded':
				$this->in_tag = 'post_content';
				break;
			case 'excerpt:encoded':
				$this->in_tag = 'post_excerpt';
				break;

			case 'wp:term_slug':
				$this->in_tag = 'slug';
				break;
			case 'wp:meta_key':
				$this->in_sub_tag = 'key';
				break;
			case 'wp:meta_value':
				$this->in_sub_tag = 'value';
				break;
		}
	}

	function cdata( $parser, $cdata ) {
		if ( ! trim( $cdata ) ) {
			return;
		}

		if ( false !== $this->in_tag || false !== $this->in_sub_tag ) {
			$this->cdata .= $cdata;
		} else {
			$this->cdata .= trim( $cdata );
		}
	}

	function tag_close( $parser, $tag ) {
		switch ( $tag ) {
			case 'wp:comment':
				unset( $this->sub_data['key'], $this->sub_data['value'] ); // remove meta sub_data
				if ( ! empty( $this->sub_data ) ) {
					$this->data['comments'][] = $this->sub_data;
				}
				$this->sub_data = false;
				break;
			case 'wp:commentmeta':
				$this->sub_data['commentmeta'][] = array(
					'key' => $this->sub_data['key'],
					'value' => $this->sub_data['value'],
				);
				break;
			case 'category':
				if ( ! empty( $this->sub_data ) ) {
					$this->sub_data['name'] = $this->cdata;
					$this->data['terms'][] = $this->sub_data;
				}
				$this->sub_data = false;
				break;
			case 'wp:postmeta':
				if ( ! empty( $this->sub_data ) ) {
					$this->data['postmeta'][] = $this->sub_data;
				}
				$this->sub_data = false;
				break;
			case 'item':
				$this->posts[] = $this->data;
				$this->data = false;
				break;
			case 'wp:category':
			case 'wp:tag':
			case 'wp:term':
				$n = substr( $tag, 3 );
				array_push( $this->$n, $this->data );
				$this->data = false;
				break;
			case 'wp:author':
				if ( ! empty( $this->data['author_login'] ) ) {
					$this->authors[ $this->data['author_login'] ] = $this->data;
				}
				$this->data = false;
				break;
			case 'wp:base_site_url':
				$this->base_url = $this->cdata;
				break;
			case 'wp:wxr_version':
				$this->wxr_version = $this->cdata;
				break;

			default:
				if ( $this->in_sub_tag ) {
					$this->sub_data[ $this->in_sub_tag ] = ! empty( $this->cdata ) ? $this->cdata : '';
					$this->in_sub_tag = false;
				} else if ( $this->in_tag ) {
					$this->data[ $this->in_tag ] = ! empty( $this->cdata ) ? $this->cdata : '';
					$this->in_tag = false;
				}
		}

		$this->cdata = false;
	}
}

/**
 * WXR Parser that uses regular expressions. Fallback for installs without an XML parser.
 */
class Vc_WXR_Parser_Regex {
	var $authors = array();
	var $posts = array();
	var $categories = array();
	var $tags = array();
	var $terms = array();
	var $base_url = '';

	function __construct() {
		$this->has_gzip = is_callable( 'gzopen' );
	}

	function parse( $file ) {
		$wxr_version = $in_post = false;

		$fp = $this->fopen( $file, 'r' );
		if ( $fp ) {
			while ( ! $this->feof( $fp ) ) {
				$importline = rtrim( $this->fgets( $fp ) );

				if ( ! $wxr_version && preg_match( '|<wp:wxr_version>(\d+\.\d+)</wp:wxr_version>|', $importline, $version ) ) {
					$wxr_version = $version[1];
				}

				if ( false !== strpos( $importline, '<wp:base_site_url>' ) ) {
					preg_match( '|<wp:base_site_url>(.*?)</wp:base_site_url>|is', $importline, $url );
					$this->base_url = $url[1];
					continue;
				}
				if ( false !== strpos( $importline, '<wp:category>' ) ) {
					preg_match( '|<wp:category>(.*?)</wp:category>|is', $importline, $category );
					$this->categories[] = $this->process_category( $category[1] );
					continue;
				}
				if ( false !== strpos( $importline, '<wp:tag>' ) ) {
					preg_match( '|<wp:tag>(.*?)</wp:tag>|is', $importline, $tag );
					$this->tags[] = $this->process_tag( $tag[1] );
					continue;
				}
				if ( false !== strpos( $importline, '<wp:term>' ) ) {
					preg_match( '|<wp:term>(.*?)</wp:term>|is', $importline, $term );
					$this->terms[] = $this->process_term( $term[1] );
					continue;
				}
				if ( false !== strpos( $importline, '<wp:author>' ) ) {
					preg_match( '|<wp:author>(.*?)</wp:author>|is', $importline, $author );
					$a = $this->process_author( $author[1] );
					$this->authors[ $a['author_login'] ] = $a;
					continue;
				}
				if ( false !== strpos( $importline, '<item>' ) ) {
					$post = '';
					$in_post = true;
					continue;
				}
				if ( false !== strpos( $importline, '</item>' ) ) {
					$in_post = false;
					$this->posts[] = $this->process_post( $post );
					continue;
				}
				if ( $in_post ) {
					$post .= $importline . "\n";
				}
			}

			$this->fclose( $fp );
		}

		if ( ! $wxr_version ) {
			return new WP_Error( 'WXR_parse_error', __( 'This does not appear to be a WXR file, missing/invalid WXR version number', 'wordpress-importer' ) );
		}

		return array(
			'authors' => $this->authors,
			'posts' => $this->posts,
			'categories' => $this->categories,
			'tags' => $this->tags,
			'terms' => $this->terms,
			'base_url' => $this->base_url,
			'version' => $wxr_version,
		);
	}

	function get_tag( $string, $tag ) {
		preg_match( "|<$tag.*?>(.*?)</$tag>|is", $string, $return );
		if ( isset( $return[1] ) ) {
			if ( substr( $return[1], 0, 9 ) == '<![CDATA[' ) {
				if ( strpos( $return[1], ']]]]><![CDATA[>' ) !== false ) {
					preg_match_all( '|<!\[CDATA\[(.*?)\]\]>|s', $return[1], $matches );
					$return = '';
					foreach ( $matches[1] as $match ) {
						$return .= $match;
					}
				} else {
					$return = preg_replace( '|^<!\[CDATA\[(.*)\]\]>$|s', '$1', $return[1] );
				}
			} else {
				$return = $return[1];
			}
		} else {
			$return = '';
		}

		return $return;
	}

	function process_category( $c ) {
		return array(
			'term_id' => $this->get_tag( $c, 'wp:term_id' ),
			'cat_name' => $this->get_tag( $c, 'wp:cat_name' ),
			'category_nicename' => $this->get_tag( $c, 'wp:category_nicename' ),
			'category_parent' => $this->get_tag( $c, 'wp:category_parent' ),
			'category_description' => $this->get_tag( $c, 'wp:category_description' ),
		);
	}

	function process_tag( $t ) {
		return array(
			'term_id' => $this->get_tag( $t, 'wp:term_id' ),
			'tag_name' => $this->get_tag( $t, 'wp:tag_name' ),
			'tag_slug' => $this->get_tag( $t, 'wp:tag_slug' ),
			'tag_description' => $this->get_tag( $t, 'wp:tag_description' ),
		);
	}

	function process_term( $t ) {
		return array(
			'term_id' => $this->get_tag( $t, 'wp:term_id' ),
			'term_taxonomy' => $this->get_tag( $t, 'wp:term_taxonomy' ),
			'slug' => $this->get_tag( $t, 'wp:term_slug' ),
			'term_parent' => $this->get_tag( $t, 'wp:term_parent' ),
			'term_name' => $this->get_tag( $t, 'wp:term_name' ),
			'term_description' => $this->get_tag( $t, 'wp:term_description' ),
		);
	}

	function process_author( $a ) {
		return array(
			'author_id' => $this->get_tag( $a, 'wp:author_id' ),
			'author_login' => $this->get_tag( $a, 'wp:author_login' ),
			'author_email' => $this->get_tag( $a, 'wp:author_email' ),
			'author_display_name' => $this->get_tag( $a, 'wp:author_display_name' ),
			'author_first_name' => $this->get_tag( $a, 'wp:author_first_name' ),
			'author_last_name' => $this->get_tag( $a, 'wp:author_last_name' ),
		);
	}

	function process_post( $post ) {
		$post_id = $this->get_tag( $post, 'wp:post_id' );
		$post_title = $this->get_tag( $post, 'title' );
		$post_date = $this->get_tag( $post, 'wp:post_date' );
		$post_date_gmt = $this->get_tag( $post, 'wp:post_date_gmt' );
		$comment_status = $this->get_tag( $post, 'wp:comment_status' );
		$ping_status = $this->get_tag( $post, 'wp:ping_status' );
		$status = $this->get_tag( $post, 'wp:status' );
		$post_name = $this->get_tag( $post, 'wp:post_name' );
		$post_parent = $this->get_tag( $post, 'wp:post_parent' );
		$menu_order = $this->get_tag( $post, 'wp:menu_order' );
		$post_type = $this->get_tag( $post, 'wp:post_type' );
		$post_password = $this->get_tag( $post, 'wp:post_password' );
		$is_sticky = $this->get_tag( $post, 'wp:is_sticky' );
		$guid = $this->get_tag( $post, 'guid' );
		$post_author = $this->get_tag( $post, 'dc:creator' );

		$post_excerpt = $this->get_tag( $post, 'excerpt:encoded' );
		$post_excerpt = preg_replace_callback( '|<(/?[A-Z]+)|', array(
			&$this,
			'_normalize_tag',
		), $post_excerpt );
		$post_excerpt = str_replace( '<br>', '<br />', $post_excerpt );
		$post_excerpt = str_replace( '<hr>', '<hr />', $post_excerpt );

		$post_content = $this->get_tag( $post, 'content:encoded' );
		$post_content = preg_replace_callback( '|<(/?[A-Z]+)|', array(
			&$this,
			'_normalize_tag',
		), $post_content );
		$post_content = str_replace( '<br>', '<br />', $post_content );
		$post_content = str_replace( '<hr>', '<hr />', $post_content );

		$postdata = compact( 'post_id', 'post_author', 'post_date', 'post_date_gmt', 'post_content', 'post_excerpt', 'post_title', 'status', 'post_name', 'comment_status', 'ping_status', 'guid', 'post_parent', 'menu_order', 'post_type', 'post_password', 'is_sticky' );

		$attachment_url = $this->get_tag( $post, 'wp:attachment_url' );
		if ( $attachment_url ) {
			$postdata['attachment_url'] = $attachment_url;
		}

		preg_match_all( '|<category domain="([^"]+?)" nicename="([^"]+?)">(.+?)</category>|is', $post, $terms, PREG_SET_ORDER );
		foreach ( $terms as $t ) {
			$post_terms[] = array(
				'slug' => $t[2],
				'domain' => $t[1],
				'name' => str_replace( array(
					'<![CDATA[',
					']]>',
				), '', $t[3] ),
			);
		}
		if ( ! empty( $post_terms ) ) {
			$postdata['terms'] = $post_terms;
		}

		preg_match_all( '|<wp:comment>(.+?)</wp:comment>|is', $post, $comments );
		$comments = $comments[1];
		if ( $comments ) {
			foreach ( $comments as $comment ) {
				preg_match_all( '|<wp:commentmeta>(.+?)</wp:commentmeta>|is', $comment, $commentmeta );
				$commentmeta = $commentmeta[1];
				$c_meta = array();
				foreach ( $commentmeta as $m ) {
					$c_meta[] = array(
						'key' => $this->get_tag( $m, 'wp:meta_key' ),
						'value' => $this->get_tag( $m, 'wp:meta_value' ),
					);
				}

				$post_comments[] = array(
					'comment_id' => $this->get_tag( $comment, 'wp:comment_id' ),
					'comment_author' => $this->get_tag( $comment, 'wp:comment_author' ),
					'comment_author_email' => $this->get_tag( $comment, 'wp:comment_author_email' ),
					'comment_author_IP' => $this->get_tag( $comment, 'wp:comment_author_IP' ),
					'comment_author_url' => $this->get_tag( $comment, 'wp:comment_author_url' ),
					'comment_date' => $this->get_tag( $comment, 'wp:comment_date' ),
					'comment_date_gmt' => $this->get_tag( $comment, 'wp:comment_date_gmt' ),
					'comment_content' => $this->get_tag( $comment, 'wp:comment_content' ),
					'comment_approved' => $this->get_tag( $comment, 'wp:comment_approved' ),
					'comment_type' => $this->get_tag( $comment, 'wp:comment_type' ),
					'comment_parent' => $this->get_tag( $comment, 'wp:comment_parent' ),
					'comment_user_id' => $this->get_tag( $comment, 'wp:comment_user_id' ),
					'commentmeta' => $c_meta,
				);
			}
		}
		if ( ! empty( $post_comments ) ) {
			$postdata['comments'] = $post_comments;
		}

		preg_match_all( '|<wp:postmeta>(.+?)</wp:postmeta>|is', $post, $postmeta );
		$postmeta = $postmeta[1];
		if ( $postmeta ) {
			foreach ( $postmeta as $p ) {
				$post_postmeta[] = array(
					'key' => $this->get_tag( $p, 'wp:meta_key' ),
					'value' => $this->get_tag( $p, 'wp:meta_value' ),
				);
			}
		}
		if ( ! empty( $post_postmeta ) ) {
			$postdata['postmeta'] = $post_postmeta;
		}

		return $postdata;
	}

	function _normalize_tag( $matches ) {
		return '<' . strtolower( $matches[1] );
	}

	function fopen( $filename, $mode = 'r' ) {
		if ( $this->has_gzip ) {
			return gzopen( $filename, $mode );
		}

		return fopen( $filename, $mode );
	}

	function feof( $fp ) {
		if ( $this->has_gzip ) {
			return gzeof( $fp );
		}

		return feof( $fp );
	}

	function fgets( $fp, $len = 8192 ) {
		if ( $this->has_gzip ) {
			return gzgets( $fp, $len );
		}

		return fgets( $fp, $len );
	}

	function fclose( $fp ) {
		if ( $this->has_gzip ) {
			return gzclose( $fp );
		}

		return fclose( $fp );
	}
}
PK      *\::M  M  0  shared-templates/importer/wordpress-importer.phpnu W+A        <?php
if ( ! defined( 'ABSPATH' ) ) {
	die( '-1' );
}

/*
 * Modified by Visual Composer team
WordPress Importer
http://wordpress.org/extend/plugins/wordpress-importer/
Description: Import posts, pages, comments, custom fields, categories, tags and more from a WordPress export file.
Author: wordpressdotorg
Author URI: http://wordpress.org/
Version: 0.6.3 with fixes and enchancements from Visual Composer
Text Domain: wordpress-importer
License: GPL version 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*/

// Load Importer API
require_once ABSPATH . 'wp-admin/includes/import.php';

if ( ! class_exists( 'WP_Importer' ) ) {
	$class_wp_importer = ABSPATH . 'wp-admin/includes/class-wp-importer.php';
	if ( file_exists( $class_wp_importer ) ) {
		require $class_wp_importer;
	}
}

// include WXR file parsers
require_once dirname( __FILE__ ) . '/parsers.php';

/**
 * WordPress Importer class for managing the import process of a WXR file
 *
 * @package WordPress
 * @subpackage Importer
 */
if ( class_exists( 'WP_Importer' ) ) {
	class Vc_WP_Import extends WP_Importer {
		public $max_wxr_version = 1.2; // max. supported WXR version

		public $id; // WXR attachment ID

		// information to import from WXR file
		public $version;
		public $posts = array();
		public $base_url = '';

		// mappings from old information to new
		public $processed_posts = array();
		public $processed_attachments = array();
		public $post_orphans = array();

		public $fetch_attachments = true;
		public $url_remap = array();
		public $featured_images = array();

		/**
		 * The main controller for the actual import stage.
		 *
		 * @param string $file Path to the WXR file for importing
		 */
		public function import( $file ) {
			add_filter( 'vc_import_post_meta_key', array(
				$this,
				'is_valid_meta_key',
			) );
			add_filter( 'http_request_timeout', array(
				$this,
				'bump_request_timeout',
			) );

			$this->import_start( $file );

			wp_suspend_cache_invalidation( true );
			$this->process_posts();
			wp_suspend_cache_invalidation( false );

			// update incorrect/missing information in the DB
			$this->backfill_parents();
			$this->backfill_attachment_urls();
			$this->remap_featured_images();
			do_action( 'vc_import_pre_end', $this );
			$this->import_end();
		}

		/**
		 * Parses the WXR file and prepares us for the task of processing parsed data
		 *
		 * @param string $file Path to the WXR file for importing
		 */
		public function import_start( $file ) {
			if ( ! is_file( $file ) ) {
				echo '<p><strong>' . __( 'Sorry, there has been an error.', 'wordpress-importer' ) . '</strong><br />';
				echo __( 'The file does not exist, please try again.', 'wordpress-importer' ) . '</p>';
				die();
			}

			$import_data = $this->parse( $file );

			if ( is_wp_error( $import_data ) ) {
				echo '<p><strong>' . __( 'Sorry, there has been an error.', 'wordpress-importer' ) . '</strong><br />';
				/** @var \WP_Error $import_data */
				echo esc_html( $import_data->get_error_message() ) . '</p>';
				die();
			}

			$this->version = $import_data['version'];
			$this->posts = $import_data['posts'];
			$this->base_url = esc_url( $import_data['base_url'] );

			wp_defer_term_counting( true );
			wp_defer_comment_counting( true );

			do_action( 'vc_import_start' );
		}

		/**
		 * Performs post-import cleanup of files and the cache
		 */
		public function import_end() {
			wp_import_cleanup( $this->id );

			wp_cache_flush();
			foreach ( get_taxonomies() as $tax ) {
				delete_option( "{$tax}_children" );
				_get_term_hierarchy( $tax );
			}

			wp_defer_term_counting( false );
			wp_defer_comment_counting( false );

			do_action( 'vc_import_end' );

			return true;
		}

		/**
		 * Handles the WXR upload and initial parsing of the file to prepare for
		 * displaying author import options
		 *
		 * @return bool False if error uploading or invalid file, true otherwise
		 */
		public function handle_upload() {
			$file = wp_import_handle_upload();

			if ( isset( $file['error'] ) ) {
				echo '<p><strong>' . __( 'Sorry, there has been an error.', 'wordpress-importer' ) . '</strong><br />';
				echo esc_html( $file['error'] ) . '</p>';

				return false;
			} else if ( ! file_exists( $file['file'] ) ) {
				echo '<p><strong>' . __( 'Sorry, there has been an error.', 'wordpress-importer' ) . '</strong><br />';
				printf( __( 'The export file could not be found at <code>%s</code>. It is likely that this was caused by a permissions problem.', 'wordpress-importer' ), esc_html( $file['file'] ) );
				echo '</p>';

				return false;
			}

			$this->id = (int) $file['id'];
			$import_data = $this->parse( $file['file'] );
			if ( is_wp_error( $import_data ) ) {
				echo '<p><strong>' . __( 'Sorry, there has been an error.', 'wordpress-importer' ) . '</strong><br />';
				/** @var \WP_Error $import_data */
				echo esc_html( $import_data->get_error_message() ) . '</p>';

				return false;
			}

			$this->version = $import_data['version'];
			if ( $this->version > $this->max_wxr_version ) {
				echo '<div class="error"><p><strong>';
				printf( __( 'This WXR file (version %s) may not be supported by this version of the importer. Please consider updating.', 'wordpress-importer' ), esc_html( $import_data['version'] ) );
				echo '</strong></p></div>';
			}

			return true;
		}

		/**
		 * Create new posts based on import information
		 *
		 * Posts marked as having a parent which doesn't exist will become top level items.
		 * Doesn't create a new post if: the post type doesn't exist, the given post ID
		 * is already noted as imported or a post with the same title and date already exists.
		 * Note that new/updated terms, comments and meta are imported for the last of the above.
		 */
		public function process_posts() {
			$status = array();
			$this->posts = apply_filters( 'vc_import_posts', $this->posts );
			if ( is_array( $this->posts ) && ! empty( $this->posts ) ) {
				foreach ( $this->posts as $post ) {
					$post = apply_filters( 'vc_import_post_data_raw', $post );

					if ( ! post_type_exists( $post['post_type'] ) ) {
						$status[] = array(
							'success' => false,
							'code' => 'invalid_post_type',
							'post' => $post,
						);
						do_action( 'vc_import_post_exists', $post );
						continue;
					}

					if ( isset( $this->processed_posts[ $post['post_id'] ] ) && ! empty( $post['post_id'] ) ) {
						continue;
					}

					if ( 'auto-draft' == $post['status'] ) {
						continue;
					}

					$post_parent = (int) $post['post_parent'];
					if ( $post_parent ) {
						// if we already know the parent, map it to the new local ID
						if ( isset( $this->processed_posts[ $post_parent ] ) ) {
							$post_parent = $this->processed_posts[ $post_parent ];
							// otherwise record the parent for later
						} else {
							$this->post_orphans[ intval( $post['post_id'] ) ] = $post_parent;
							$post_parent = 0;
						}
					}

					// map the post author
					$author = (int) get_current_user_id();

					$postdata = array(
						// 'import_id' => $post['post_id'], // VC: Make the ID always to be new!
						'post_author' => $author,
						'post_date' => $post['post_date'],
						'post_date_gmt' => $post['post_date_gmt'],
						'post_content' => $post['post_content'],
						'post_excerpt' => $post['post_excerpt'],
						'post_title' => $post['post_title'],
						'post_status' => $post['status'],
						'post_name' => $post['post_name'],
						'comment_status' => $post['comment_status'],
						'ping_status' => $post['ping_status'],
						'guid' => $post['guid'],
						'post_parent' => $post_parent,
						'menu_order' => $post['menu_order'],
						'post_type' => $post['post_type'],
						'post_password' => $post['post_password'],
					);

					$original_post_ID = $post['post_id'];
					$postdata = apply_filters( 'vc_import_post_data_processed', $postdata, $post, $this );

					$postdata = wp_slash( $postdata );

					if ( 'attachment' == $postdata['post_type'] ) {
						$remote_url = ! empty( $post['attachment_url'] ) ? $post['attachment_url'] : $post['guid'];

						// try to use _wp_attached file for upload folder placement to ensure the same location as the export site
						// e.g. location is 2003/05/image.jpg but the attachment post_date is 2010/09, see media_handle_upload()
						$postdata['upload_date'] = $post['post_date'];
						if ( isset( $post['postmeta'] ) ) {
							foreach ( $post['postmeta'] as $meta ) {
								if ( '_wp_attached_file' == $meta['key'] ) {
									if ( preg_match( '%^[0-9]{4}/[0-9]{2}%', $meta['value'], $matches ) ) {
										$postdata['upload_date'] = $matches[0];
									}
									break;
								}
							}
						}

						$post_id = $this->process_attachment( $postdata, $remote_url, $original_post_ID );
					} else {
						$post_id = wp_insert_post( $postdata, true );
						do_action( 'vc_import_insert_post', $post_id, $original_post_ID, $postdata, $post );
						// map pre-import ID to local ID
						$this->processed_posts[ intval( $post['post_id'] ) ] = (int) $post_id;
					}

					if ( is_wp_error( $post_id ) ) {
						$status[] = array(
							'success' => false,
							'code' => 'wp_error',
							'post' => $post_id,
						);
						continue;
					}

					if ( 1 == $post['is_sticky'] ) {
						stick_post( $post_id );
					}

					if ( ! isset( $post['postmeta'] ) ) {
						$post['postmeta'] = array();
					}

					$post['postmeta'] = apply_filters( 'vc_import_post_meta', $post['postmeta'], $post_id, $post );

					// add/update post meta
					if ( ! empty( $post['postmeta'] ) ) {
						foreach ( $post['postmeta'] as $meta ) {
							$key = apply_filters( 'vc_import_post_meta_key', $meta['key'], $post_id, $post );
							$value = false;

							if ( '_edit_last' == $key ) {
								$key = false;
							}

							if ( $key ) {
								// export gets meta straight from the DB so could have a serialized string
								if ( ! $value ) {
									$value = maybe_unserialize( $meta['value'] );
								}

								add_post_meta( $post_id, $key, $value );
								do_action( 'vc_import_post_meta', $post_id, $key, $value );

								// if the post has a featured image, take note of this in case of remap
								if ( '_thumbnail_id' == $key ) {
									$this->featured_images[ $post_id ] = (int) $value;
								}
							}
						}
					}
				}
			}
			unset( $this->posts );

			return $status;
		}

		/**
		 * If fetching attachments is enabled then attempt to create a new attachment
		 *
		 * @param array $post Attachment post details from WXR
		 * @param string $url URL to fetch attachment from
		 * @param $original_post_ID
		 * @return int|\WP_Error Post ID on success, WP_Error otherwise
		 */
		public function process_attachment( $post, $url, $original_post_ID ) {
			if ( ! $this->fetch_attachments ) {
				return new WP_Error( 'attachment_processing_error', __( 'Fetching attachments is not enabled', 'wordpress-importer' ) );
			}

			// if the URL is absolute, but does not contain address, then upload it assuming base_site_url
			if ( preg_match( '|^/[\w\W]+$|', $url ) ) {
				$url = rtrim( $this->base_url, '/' ) . $url;
			}

			$upload = $this->fetch_remote_file( $url, $post );
			if ( is_wp_error( $upload ) ) {
				return $upload;
			}

			if ( $info = wp_check_filetype( $upload['file'] ) ) {
				$post['post_mime_type'] = $info['type'];
			} else {
				return new WP_Error( 'attachment_processing_error', __( 'Invalid file type', 'wordpress-importer' ) );
			}

			$post['guid'] = $upload['url'];

			// as per wp-admin/includes/upload.php
			$post_id = wp_insert_attachment( $post, $upload['file'] );
			wp_update_attachment_metadata( $post_id, wp_generate_attachment_metadata( $post_id, $upload['file'] ) );

			// remap resized image URLs, works by stripping the extension and remapping the URL stub.
			if ( preg_match( '!^image/!', $info['type'] ) ) {
				$parts = pathinfo( $url );
				$name = basename( $parts['basename'], ".{$parts['extension']}" ); // PATHINFO_FILENAME in PHP 5.2

				$parts_new = pathinfo( $upload['url'] );
				$name_new = basename( $parts_new['basename'], ".{$parts_new['extension']}" );

				$this->url_remap[ $parts['dirname'] . '/' . $name ] = $parts_new['dirname'] . '/' . $name_new;
			}
			$this->processed_attachments[ intval( $original_post_ID ) ] = (int) $post_id;

			return $post_id;
		}

		private function wp_get_http( $url, $file_path = false ) {
			@set_time_limit( 60 );

			$options = array();
			$options['redirection'] = 5;

			$options['method'] = 'GET';

			$response = wp_safe_remote_request( $url, $options );

			if ( is_wp_error( $response ) ) {
				return false;
			}

			$headers = wp_remote_retrieve_headers( $response );
			$headers['response'] = wp_remote_retrieve_response_code( $response );

			if ( false == $file_path ) {
				return $headers;
			}

			// GET request - write it to the supplied filename
			$out_fp = fopen( $file_path, 'w' );
			if ( ! $out_fp ) {
				return $headers;
			}

			fwrite( $out_fp, wp_remote_retrieve_body( $response ) );
			fclose( $out_fp );
			clearstatcache();

			return $headers;
		}

		/**
		 * Attempt to download a remote file attachment
		 *
		 * @param string $url URL of item to fetch
		 * @param array $post Attachment details
		 * @return array|WP_Error Local file location details on success, WP_Error otherwise
		 */
		public function fetch_remote_file( $url, $post ) {
			// extract the file name and extension from the url
			$file_name = basename( $url );

			// get placeholder file in the upload dir with a unique, sanitized filename
			$upload = wp_upload_bits( $file_name, 0, '', $post['upload_date'] );
			if ( $upload['error'] ) {
				return new WP_Error( 'upload_dir_error', $upload['error'] );
			}

			// fetch the remote url and write it to the placeholder file
			$headers = $this->wp_get_http( $url, $upload['file'] );

			// request failed
			if ( ! $headers ) {
				@unlink( $upload['file'] );

				return new WP_Error( 'import_file_error', __( 'Remote server did not respond', 'wordpress-importer' ) );
			}

			// make sure the fetch was successful
			if ( '200' != $headers['response'] ) {
				@unlink( $upload['file'] );

				return new WP_Error( 'import_file_error', sprintf( __( 'Remote server returned error response %1$d %2$s', 'wordpress-importer' ), esc_html( $headers['response'] ), get_status_header_desc( $headers['response'] ) ) );
			}

			$filesize = filesize( $upload['file'] );

			if ( isset( $headers['content-length'] ) && $filesize != $headers['content-length'] ) {
				@unlink( $upload['file'] );

				return new WP_Error( 'import_file_error', __( 'Remote file is incorrect size', 'wordpress-importer' ) );
			}

			if ( 0 == $filesize ) {
				@unlink( $upload['file'] );

				return new WP_Error( 'import_file_error', __( 'Zero size file downloaded', 'wordpress-importer' ) );
			}

			$max_size = (int) $this->max_attachment_size();
			if ( ! empty( $max_size ) && $filesize > $max_size ) {
				@unlink( $upload['file'] );

				return new WP_Error( 'import_file_error', sprintf( __( 'Remote file is too large, limit is %s', 'wordpress-importer' ), size_format( $max_size ) ) );
			}

			// keep track of the old and new urls so we can substitute them later
			$this->url_remap[ $url ] = $upload['url'];
			$this->url_remap[ $post['guid'] ] = $upload['url']; // r13735, really needed?
			// keep track of the destination if the remote url is redirected somewhere else
			if ( isset( $headers['x-final-location'] ) && $headers['x-final-location'] != $url ) {
				$this->url_remap[ $headers['x-final-location'] ] = $upload['url'];
			}

			return $upload;
		}

		/**
		 * Attempt to associate posts and menu items with previously missing parents
		 *
		 * An imported post's parent may not have been imported when it was first created
		 * so try again. Similarly for child menu items and menu items which were missing
		 * the object (e.g. post) they represent in the menu
		 */
		public function backfill_parents() {
			global $wpdb;

			// find parents for post orphans
			foreach ( $this->post_orphans as $child_id => $parent_id ) {
				$local_child_id = $local_parent_id = false;
				if ( isset( $this->processed_posts[ $child_id ] ) ) {
					$local_child_id = $this->processed_posts[ $child_id ];
				}
				if ( isset( $this->processed_posts[ $parent_id ] ) ) {
					$local_parent_id = $this->processed_posts[ $parent_id ];
				}

				if ( $local_child_id && $local_parent_id ) {
					$wpdb->update( $wpdb->posts, array( 'post_parent' => $local_parent_id ), array( 'ID' => $local_child_id ), '%d', '%d' );
				}
			}
		}

		/**
		 * Use stored mapping information to update old attachment URLs
		 */
		public function backfill_attachment_urls() {
			global $wpdb;
			// make sure we do the longest urls first, in case one is a substring of another
			uksort( $this->url_remap, array(
				$this,
				'cmpr_strlen',
			) );

			foreach ( $this->url_remap as $from_url => $to_url ) {
				// remap urls in post_content
				$wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->posts} SET post_content = REPLACE(post_content, %s, %s)", $from_url, $to_url ) );
				// remap enclosure urls
				$wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->postmeta} SET meta_value = REPLACE(meta_value, %s, %s) WHERE meta_key='enclosure'", $from_url, $to_url ) );
			}
		}

		/**
		 * Update _thumbnail_id meta to new, imported attachment IDs
		 */
		public function remap_featured_images() {
			// cycle through posts that have a featured image
			foreach ( $this->featured_images as $post_id => $value ) {
				if ( isset( $this->processed_posts[ $value ] ) ) {
					$new_id = $this->processed_posts[ $value ];
					// only update if there's a difference
					if ( $new_id != $value ) {
						update_post_meta( $post_id, '_thumbnail_id', $new_id );
					}
				}
			}
		}

		/**
		 * Parse a WXR file
		 *
		 * @param string $file Path to WXR file for parsing
		 * @return array Information gathered from the WXR file
		 */
		public function parse( $file ) {
			$parser = new Vc_WXR_Parser();

			return $parser->parse( $file );
		}

		/**
		 * Decide if the given meta key maps to information we will want to import
		 *
		 * @param string $key The meta key to check
		 * @return string|bool The key if we do want to import, false if not
		 */
		public function is_valid_meta_key( $key ) {
			// skip attachment metadata since we'll regenerate it from scratch
			// skip _edit_lock as not relevant for import
			if ( in_array( $key, array(
				'_wp_attached_file',
				'_wp_attachment_metadata',
				'_edit_lock',
			) ) ) {
				return false;
			}

			return $key;
		}

		/**
		 * Decide whether or not the importer is allowed to create users.
		 * Default is true, can be filtered via import_allow_create_users
		 *
		 * @return bool True if creating users is allowed
		 */
		public function allow_create_users() {
			return false;
		}

		/**
		 * Decide whether or not the importer should attempt to download attachment files.
		 * Default is true, can be filtered via import_allow_fetch_attachments. The choice
		 * made at the import options screen must also be true, false here hides that checkbox.
		 *
		 * @return bool True if downloading attachments is allowed
		 */
		public function allow_fetch_attachments() {
			return apply_filters( 'vc_import_allow_fetch_attachments', true );
		}

		/**
		 * Decide what the maximum file size for downloaded attachments is.
		 * Default is 0 (unlimited), can be filtered via import_attachment_size_limit
		 *
		 * @return int Maximum attachment file size to import
		 */
		public function max_attachment_size() {
			return apply_filters( 'vc_import_attachment_size_limit', 0 );
		}

		// return the difference in length between two strings
		public function cmpr_strlen( $a, $b ) {
			return strlen( $b ) - strlen( $a );
		}
	}

} // class_exists( 'WP_Importer' )
PK      *\Huw2  2  $  shared-templates/importer/plugin.phpnu W+A        <?php
if ( ! defined( 'ABSPATH' ) ) {
	die( '-1' );
}

class Vc_WXR_Parser_Plugin {
	public $shortcodes = array(
		'gallery' => array(
			'ids',
		),
		'vc_single_image' => array(
			'image',
		),
		'vc_gallery' => array(
			'images',
		),
		'vc_images_carousel' => array(
			'images',
		),
		'vc_media_grid' => array(
			'include',
		),
		'vc_masonry_media_grid' => array(
			'include',
		),
	);
	protected $remaps = 0;

	public function __construct() {
		$this->shortcodes = apply_filters( 'vc_shared_templates_import_shortcodes', $this->shortcodes );
		add_filter( 'vc_import_post_data_processed', array(
			$this,
			'processPostContent',
		) );

		add_action( 'vc_import_pre_end', array(
			$this,
			'remapIdsInPosts',
		) );
	}

	private $idsRemap = array();

	/**
	 * @param array $postdata
	 *
	 * @return array
	 */
	public function processPostContent( $postdata ) {
		if ( ! empty( $postdata['post_content'] ) && 'vc4_templates' === $postdata['post_type'] ) {
			$this->parseShortcodes( $postdata['post_content'] );
		}

		return $postdata;
	}

	/**
	 * @param Vc_WP_Import $importer
	 */
	public function remapIdsInPosts( $importer ) {
		$currentPost = reset( $importer->processed_posts );
		// Nothing to remap or something wrong
		if ( ! $currentPost ) {
			return;
		}
		$post = get_post( $currentPost );
		if ( empty( $post ) || ! is_object( $post ) || 'vc4_templates' !== $post->post_type ) {
			return;
		}
		// We ready to remap attributes in processed attachments
		$attachments = $importer->processed_attachments;
		$this->remaps = 0;
		$newContent = $this->processAttachments( $attachments, $post->post_content );

		if ( $this->remaps ) {
			$post->post_content = $newContent;
			wp_update_post( $post );
		}
	}

	protected function processAttachments( $attachments, $content ) {
		if ( ! empty( $this->idsRemap ) ) {
			foreach ( $this->idsRemap as $shortcode ) {
				$tag = $shortcode['tag'];
				$attributes = $this->shortcodes[ $tag ];
				$rawQuery = $shortcode['attrs_query'];
				$newQuery = $this->shortcodeAttributes( $shortcode, $attributes, $rawQuery, $attachments );

				if ( $newQuery ) {
					$content = str_replace( $rawQuery, $newQuery, $content );
					$this->remaps ++;
				}
			}
		}
		$urlRegex = '#\bhttps?://[^\s()<>]+(?:\([\w\d]+\)|(?:[^[:punct:]\s]|/))#';
		$urlMatches = array();
		preg_match_all( $urlRegex, $content, $urlMatches );
		if ( ! empty( $urlMatches[0] ) ) {
			foreach ( $urlMatches[0] as $url ) {
				$idsMatches = array();
				preg_match_all( '/id\=(?P<id>\d+)/', $url, $idsMatches );
				if ( ! empty( $idsMatches['id'] ) ) {
					$this->remaps = true;
					$vals = array_map( 'intval', $idsMatches['id'] );
					$content = $this->remapAttachmentUrls( $attachments, $content, $url, $vals );
				}
			}
		}

		return $content;
	}

	protected function remapAttachmentUrls( $attachments, $content, $url, $vals ) {
		foreach ( $vals as $oldAttachmentId ) {
			if ( isset( $attachments[ $oldAttachmentId ] ) ) {
				$newUrl = wp_get_attachment_url( $attachments[ $oldAttachmentId ] );
				$content = str_replace( $url, $newUrl . '?id=' . $attachments[ $oldAttachmentId ], $content );
			}
		}

		return $content;
	}

	protected function shortcodeAttributes( $shortcode, $attributes, $newQuery, $attachments ) {
		$replacements = 0;
		foreach ( $attributes as $attribute ) {
			// for example in vc_single_image 'image' attribute
			if ( isset( $shortcode['attrs'][ $attribute ] ) ) {
				$attributeValue = $shortcode['attrs'][ $attribute ];
				$attributeValues = explode( ',', $attributeValue );
				$newValues = $attributeValues;
				array_walk( $newValues, array(
					$this,
					'attributesWalker',
				), array(
					'attachments' => $attachments,
				) );
				$newAttributeValue = implode( ',', $newValues );
				$newQuery = str_replace( sprintf( '%s="%s"', $attribute, $attributeValue ), sprintf( '%s="%s"', $attribute, $newAttributeValue ), $newQuery );
				$replacements ++;
			}
		}
		if ( $replacements ) {
			return $newQuery;
		}

		return false;
	}

	public function attributesWalker( &$attributeValue, $key, $data ) {
		$intValue = intval( $attributeValue );
		if ( array_key_exists( $intValue, $data['attachments'] ) ) {
			$attributeValue = $data['attachments'][ $intValue ];
		}
	}

	private function parseShortcodes( $content ) {
		WPBMap::addAllMappedShortcodes();
		preg_match_all( '/' . get_shortcode_regex() . '/', trim( $content ), $found );

		if ( count( $found[2] ) === 0 ) {
			return $this->idsRemap;
		}
		foreach ( $found[2] as $index => $tag ) {
			$content = $found[5][ $index ];
			$shortcode = array(
				'tag' => $tag,
				'attrs_query' => $found[3][ $index ],
				'attrs' => shortcode_parse_atts( $found[3][ $index ] ),
			);
			if ( array_key_exists( $tag, $this->shortcodes ) ) {
				$this->idsRemap[] = $shortcode;
			}
			$this->idsRemap = $this->parseShortcodes( $content );
		}

		return $this->idsRemap;
	}
}
PK        *\6c  c                  class-vc-page.phpnu W+A        PK        *\E    '              access/class-vc-current-user-access.phpnu W+A        PK        *\Q)  )  2              access/class-vc-current-user-access-controller.phpnu W+A        PK        *\u$+                  access/class-vc-role-access.phpnu W+A        PK        *\x    #              access/abstract-class-vc-access.phpnu W+A        PK        *\9J  J  *            %&  access/class-vc-role-access-controller.phpnu W+A        PK        *\IZ&M  M              =  class-wpb-map.phpnu W+A        PK        *\4                  class-vc-sort.phpnu W+A        PK        *\03                K  interfaces.phpnu W+A        PK        *\wB                    class-vc-pages-group.phpnu W+A        PK        *\/,  ,                class-vc-post-admin.phpnu W+A        PK        *\Bn  Bn              [  class-vc-base.phpnu W+A        PK        *\zsYG   G                class-vc-shared-library.phpnu W+A        PK        *\xmIC                p7 class-vc-mapper.phpnu W+A        PK        *\?Xct  t  .            oK shared-templates/class-vc-shared-templates.phpnu W+A        PK        *\>D{_  _  %            Aj shared-templates/importer/parsers.phpnu W+A        PK        *\::M  M  0            s shared-templates/importer/wordpress-importer.phpnu W+A        PK        *\Huw2  2  $            x shared-templates/importer/plugin.phpnu W+A        PK        +   