This commit is contained in:
KhaiNguyen
2020-02-13 10:39:37 +07:00
commit 59401cb805
12867 changed files with 4646216 additions and 0 deletions

View File

@@ -0,0 +1,170 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Class Vc_Access
*
* @package WPBakeryPageBuilder
* @since 4.8
*/
abstract class Vc_Access {
/**
* @var bool
*/
protected $validAccess = true;
/**
* @return bool
*/
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( esc_html( $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_Access
*/
public function checkAdminNonce( $nonce = '' ) {
return $this->check( 'vc_verify_admin_nonce', $nonce );
}
/**
* @param string $nonce
*
* @return Vc_Access
*/
public function checkPublicNonce( $nonce = '' ) {
return $this->check( 'vc_verify_public_nonce', $nonce );
}
}

View File

@@ -0,0 +1,50 @@
<?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
*/
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 );
}
/**
* @return bool|\WP_Role|null
*/
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;
}
}

View File

@@ -0,0 +1,90 @@
<?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 Vc_Current_User_Access_Controller $user_access_controller */
$this->parts[ $part ] = new Vc_Current_User_Access_Controller( $part );
}
/** @var Vc_Current_User_Access_Controller $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;
}
/**
* @param $method
* @param $valid
* @param $argsList
* @return $this
*/
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;
}
}

View File

@@ -0,0 +1,285 @@
<?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',
);
/**
* Vc_Role_Access_Controller constructor.
* @param $part
*/
public 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;
* @throws \Exception
*/
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
* @throws \Exception
*/
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
* @throws \Exception
*/
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
* @throws \Exception
*/
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
* @throws \Exception
*/
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.
* @throws \Exception
*/
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;
}
/**
* @return string
*/
public function getStateKey() {
return self::$part_name_prefix . $this->getPart();
}
/**
* @param $data
* @return $this
* @throws \Exception
*/
public function checkState( $data ) {
if ( $this->getValidAccess() ) {
$this->setValidAccess( $this->getState() === $data );
}
return $this;
}
/**
* @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();
}
/**
* @param $rule
* @return mixed
*/
public function updateMergedCaps( $rule ) {
if ( isset( $this->mergedCaps[ $rule ] ) ) {
return $this->mergedCaps[ $rule ];
}
return $rule;
}
/**
* @return array
*/
public function getMergedCaps() {
return $this->mergedCaps;
}
}

View File

@@ -0,0 +1,74 @@
<?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 Vc_Role_Access_Controller $role_access_controller */
$this->parts[ $key ] = new Vc_Role_Access_Controller( $part );
$role_access_controller = $this->parts[ $key ];
$role_access_controller->setRoleName( $this->getRoleName() );
}
/** @var Vc_Role_Access_Controller $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;
}
}

View File

@@ -0,0 +1,749 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* WPBakery Page Builder 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 editor.
* @since 4.4
* @access protected
* @var bool|Vc_Templates_Panel_Editor
*/
protected $templates_panel_editor = false;
/**
* Presets management panel editor.
* @since 5.2
* @access protected
* @var bool|Vc_Preset_Panel_Editor
*/
protected $preset_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();
/** @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',
) );
if ( is_admin() ) {
$this->initAdmin();
} else {
$this->initPage();
}
do_action( 'vc_after_init_base' );
}
/**
* Post object for interacting with Current post data.
* @return Vc_Post_Admin
* @since 4.4
*/
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' );
// editors actions:
$this->editForm()->init();
$this->templatesPanelEditor()->init();
$this->shared_templates->init();
// plugins list page actions links
add_filter( 'plugin_action_links', array(
$this,
'pluginActionLinks',
), 10, 2 );
}
/**
* Setter for edit form.
* @param Vc_Shortcode_Edit_Form $form
* @since 4.2
*
*/
public function setEditForm( Vc_Shortcode_Edit_Form $form ) {
$this->shortcode_edit_form = $form;
}
/**
* Get Shortcodes Edit form object.
*
* @return Vc_Shortcode_Edit_Form
* @since 4.2
* @access public
* @see Vc_Shortcode_Edit_Form::__construct
*/
public function editForm() {
return $this->shortcode_edit_form;
}
/**
* Setter for Templates editor.
* @param Vc_Templates_Panel_Editor $editor
* @since 4.4
*
*/
public function setTemplatesPanelEditor( Vc_Templates_Panel_Editor $editor ) {
$this->templates_panel_editor = $editor;
}
/**
* Setter for Preset editor.
* @param Vc_Preset_Panel_Editor $editor
* @since 5.2
*
*/
public function setPresetPanelEditor( Vc_Preset_Panel_Editor $editor ) {
$this->preset_panel_editor = $editor;
}
/**
* Get templates manager.
* @return bool|Vc_Templates_Panel_Editor
* @since 4.4
* @access public
* @see Vc_Templates_Panel_Editor::__construct
*/
public function templatesPanelEditor() {
return $this->templates_panel_editor;
}
/**
* Get preset manager.
* @return bool|Vc_Preset_Panel_Editor
* @since 5.2
* @access public
* @see Vc_Preset_Panel_Editor::__construct
*/
public function presetPanelEditor() {
return $this->preset_panel_editor;
}
/**
* Get shortcode class instance.
*
* @param string $tag
*
* @return Vc_Shortcodes_Manager|null
* @see WPBakeryShortCodeFishBones
* @since 4.2
* @access public
*
*/
public function getShortCode( $tag ) {
return Vc_Shortcodes_Manager::getInstance()->setTag( $tag );
}
/**
* Remove shortcode from shortcodes list of VC.
*
* @param $tag - shortcode tag
* @since 4.2
* @access public
*
*/
public function removeShortCode( $tag ) {
remove_shortcode( $tag );
}
/**
* Set or modify new settings for shortcode.
*
* This function widely used by WPBMap class methods to modify shortcodes mapping
*
* @param $tag
* @param $name
* @param $value
* @throws \Exception
* @since 4.3
*/
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.
*
* @param $post_id
* @throws \Exception
* @since 4.2
* @access public
*/
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 ), $post_id );
if ( empty( $css ) ) {
delete_metadata( 'post', $post_id, '_wpb_shortcodes_custom_css' );
} else {
update_metadata( 'post', $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'.
*
* @param $content
*
* @return string
* @throws \Exception
* @see WPBakeryVisualComposerCssEditor
* @since 4.2
* @access public
*/
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.
*
* @param int $id
* @since 4.2
* @access public
*
*/
public function addPageCustomCss( $id = null ) {
if ( is_front_page() || is_home() ) {
$id = get_queried_object_id();
} elseif ( is_singular() ) {
if ( ! $id ) {
$id = get_the_ID();
}
}
if ( $id ) {
if ( 'true' === vc_get_param( 'preview' ) && wp_revisions_enabled( get_post( $id ) ) ) {
$latest_revision = wp_get_post_revisions( $id );
if ( ! empty( $latest_revision ) ) {
$array_values = array_values( $latest_revision );
$id = $array_values[0]->ID;
}
}
$post_custom_css = get_metadata( 'post', $id, '_wpb_post_custom_css', true );
if ( ! empty( $post_custom_css ) ) {
$post_custom_css = wp_strip_all_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.
*
* @param int $id
*
* @since 4.2
* @access public
*
*/
public function addShortcodesCustomCss( $id = null ) {
if ( ! is_singular() ) {
return;
}
if ( ! $id ) {
$id = get_the_ID();
}
if ( $id ) {
if ( 'true' === vc_get_param( 'preview' ) && wp_revisions_enabled( get_post( $id ) ) ) {
$latest_revision = wp_get_post_revisions( $id );
if ( ! empty( $latest_revision ) ) {
$array_values = array_values( $latest_revision );
$id = $array_values[0]->ID;
}
}
$shortcodes_custom_css = get_metadata( 'post', $id, '_wpb_shortcodes_custom_css', true );
if ( ! empty( $shortcodes_custom_css ) ) {
$shortcodes_custom_css = wp_strip_all_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() {
$custom_tag = 'style';
$second_tag = 'noscript';
echo '<' . esc_attr( $second_tag ) . '>';
echo '<' . esc_attr( $custom_tag ) . '>';
echo ' .wpb_animate_when_almost_visible { opacity: 1; }';
echo '</' . esc_attr( $custom_tag ) . '>';
echo '</' . esc_attr( $second_tag ) . '>';
}
/**
* 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( 'vc_font_awesome_5_shims', vc_asset_url( 'lib/bower/font-awesome/css/v4-shims.min.css' ), array(), WPB_VC_VERSION );
wp_register_style( 'vc_font_awesome_5', vc_asset_url( 'lib/bower/font-awesome/css/all.min.css' ), array( 'vc_font_awesome_5_shims' ), WPB_VC_VERSION );
wp_register_style( 'vc_animate-css', vc_asset_url( 'lib/bower/animate-css/animate.min.css' ), array(), WPB_VC_VERSION );
$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 && strpos( $post->post_content, '[vc_row' ) !== false ) {
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( 'vc_waypoints', vc_asset_url( 'lib/vc_waypoints/vc-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
* @param $links
* @param $file
*
* @return array
* @throws \Exception
* @since 4.2
*/
public function pluginActionLinks( $links, $file ) {
if ( plugin_basename( vc_path_dir( 'APP_DIR', '/js_composer.php' ) ) === $file ) {
$title = esc_html__( 'WPBakery Page Builder Settings', 'js_composer' );
$html = esc_html__( 'Settings', 'js_composer' );
if ( ! vc_user_access()->part( 'settings' )->can( 'vc-general-tab' )->get() ) {
$title = esc_html__( 'About WPBakery Page Builder', '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
* @return string url to settings page
* @throws \Exception
* @since 4.2
*/
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 WPBakery Page Builder - drag and drop page builder for WordPress."/>' . "\n";
}
/**
* 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.
*
* @param $classes
*
* @return array
* @since 4.2
* @access public
*
*/
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.
*
* @param $output
*
* @return string
* @since 4.2
* @access public
*
*/
public function excerptFilter( $output ) {
global $post;
if ( empty( $output ) && ! empty( $post->post_content ) ) {
$text = wp_strip_all_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.
* @param null $content
*
* @return string|null
* @since 4.2
*
*/
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;
}
/**
* Get array of string for locale.
*
* @return array
* @since 4.7
*
*/
public function getEditorsLocale() {
return array(
'add_remove_picture' => esc_html__( 'Add/remove picture', 'js_composer' ),
'finish_adding_text' => esc_html__( 'Finish Adding Images', 'js_composer' ),
'add_image' => esc_html__( 'Add Image', 'js_composer' ),
'add_images' => esc_html__( 'Add Images', 'js_composer' ),
'settings' => esc_html__( 'Settings', 'js_composer' ),
'main_button_title' => esc_html__( 'WPBakery Page Builder', 'js_composer' ),
'main_button_title_backend_editor' => esc_html__( 'Backend Editor', 'js_composer' ),
'main_button_title_frontend_editor' => esc_html__( 'Frontend Editor', 'js_composer' ),
'main_button_title_revert' => esc_html__( 'Classic Mode', 'js_composer' ),
'main_button_title_gutenberg' => esc_html__( 'Gutenberg Editor', 'js_composer' ),
'please_enter_templates_name' => esc_html__( 'Enter template name you want to save.', 'js_composer' ),
'confirm_deleting_template' => esc_html__( 'Confirm deleting "{template_name}" template, press Cancel to leave. This action cannot be undone.', 'js_composer' ),
'press_ok_to_delete_section' => esc_html__( 'Press OK to delete section, Cancel to leave', 'js_composer' ),
'drag_drop_me_in_column' => esc_html__( 'Drag and drop me in the column', 'js_composer' ),
'press_ok_to_delete_tab' => esc_html__( 'Press OK to delete "{tab_name}" tab, Cancel to leave', 'js_composer' ),
'slide' => esc_html__( 'Slide', 'js_composer' ),
'tab' => esc_html__( 'Tab', 'js_composer' ),
'section' => esc_html__( 'Section', 'js_composer' ),
'please_enter_new_tab_title' => esc_html__( 'Please enter new tab title', 'js_composer' ),
'press_ok_delete_section' => esc_html__( 'Press OK to delete "{tab_name}" section, Cancel to leave', 'js_composer' ),
'section_default_title' => esc_html__( 'Section', 'js_composer' ),
'please_enter_section_title' => esc_html__( 'Please enter new section title', 'js_composer' ),
'error_please_try_again' => esc_html__( 'Error. Please try again.', 'js_composer' ),
'if_close_data_lost' => esc_html__( 'If you close this window all shortcode settings will be lost. Close this window?', 'js_composer' ),
'header_select_element_type' => esc_html__( 'Select element type', 'js_composer' ),
'header_media_gallery' => esc_html__( 'Media gallery', 'js_composer' ),
'header_element_settings' => esc_html__( 'Element settings', 'js_composer' ),
'add_tab' => esc_html__( 'Add tab', 'js_composer' ),
'are_you_sure_convert_to_new_version' => esc_html__( 'Are you sure you want to convert to new version?', 'js_composer' ),
'loading' => esc_html__( 'Loading...', 'js_composer' ),
// Media editor
'set_image' => esc_html__( 'Set Image', 'js_composer' ),
'are_you_sure_reset_css_classes' => esc_html__( 'Are you sure that you want to remove all your data?', 'js_composer' ),
'loop_frame_title' => esc_html__( 'Loop settings', 'js_composer' ),
'enter_custom_layout' => esc_html__( 'Custom row layout', 'js_composer' ),
'wrong_cells_layout' => esc_html__( 'Wrong row layout format! Example: 1/2 + 1/2 or span6 + span6.', 'js_composer' ),
'row_background_color' => esc_html__( 'Row background color', 'js_composer' ),
'row_background_image' => esc_html__( 'Row background image', 'js_composer' ),
'column_background_color' => esc_html__( 'Column background color', 'js_composer' ),
'column_background_image' => esc_html__( 'Column background image', 'js_composer' ),
'guides_on' => esc_html__( 'Guides ON', 'js_composer' ),
'guides_off' => esc_html__( 'Guides OFF', 'js_composer' ),
'template_save' => esc_html__( 'New template successfully saved.', 'js_composer' ),
'template_added' => esc_html__( 'Template added to the page.', 'js_composer' ),
'template_added_with_id' => esc_html__( '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' => esc_html__( 'Template successfully removed.', 'js_composer' ),
'template_is_empty' => esc_html__( 'Template is empty: There is no content to be saved as a template.', 'js_composer' ),
'template_save_error' => esc_html__( 'Error while saving template.', 'js_composer' ),
'css_updated' => esc_html__( 'Page settings updated!', 'js_composer' ),
'update_all' => esc_html__( 'Update all', 'js_composer' ),
'confirm_to_leave' => esc_html__( 'The changes you made will be lost if you navigate away from this page.', 'js_composer' ),
'inline_element_saved' => esc_html__( '%s saved!', 'js_composer' ),
'inline_element_deleted' => esc_html__( '%s deleted!', 'js_composer' ),
'inline_element_cloned' => sprintf( __( '%%s cloned. %sEdit now?%s', 'js_composer' ), '<a href="#" class="vc_edit-cloned" data-model-id="%s">', '</a>' ),
'gfonts_loading_google_font_failed' => esc_html__( 'Loading Google Font failed', 'js_composer' ),
'gfonts_loading_google_font' => esc_html__( 'Loading Font...', 'js_composer' ),
'gfonts_unable_to_load_google_fonts' => esc_html__( 'Unable to load Google Fonts', 'js_composer' ),
'no_title_parenthesis' => sprintf( '(%s)', esc_html__( 'no title', 'js_composer' ) ),
'error_while_saving_image_filtered' => esc_html__( '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', esc_html__( 'Saved!', 'js_composer' ) ),
'ui_danger' => sprintf( '<i class="vc-composer-icon vc-c-icon-close"></i> %s', esc_html__( 'Failed to Save!', 'js_composer' ) ),
'delete_preset_confirmation' => esc_html__( 'You are about to delete this preset. This action can not be undone.', 'js_composer' ),
'ui_template_downloaded' => esc_html__( 'Downloaded', 'js_composer' ),
'ui_template_update' => esc_html__( 'Update', 'js_composer' ),
'ui_templates_failed_to_download' => esc_html__( 'Failed to download template', 'js_composer' ),
'preset_removed' => esc_html__( 'Element successfully removed.', 'js_composer' ),
'vc_successfully_updated' => esc_html__( 'Successfully updated!', 'js_composer' ),
'gutenbergDoesntWorkProperly' => esc_html__( 'Gutenberg plugin doesn\'t work properly. Please check Gutenberg plugin.', 'js_composer' ),
);
}
}

View File

@@ -0,0 +1,870 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Vc starts here. Manager sets mode, adds required wp hooks and loads required object of structure
*
* Manager controls and access to all modules and classes of VC.
*
* @package WPBakeryVisualComposer
* @since 4.2
*/
class Vc_Manager {
/**
* Set status/mode for VC.
*
* It depends on what functionality is required from vc to work with current page/part of WP.
*
* Possible values:
* none - current status is unknown, default mode;
* page - simple wp page;
* admin_page - wp dashboard;
* admin_frontend_editor - WPBakery Page Builder front end editor version;
* admin_settings_page - settings page
* page_editable - inline version for iframe in front end editor;
*
* @since 4.2
* @var string
*/
private $mode = 'none';
/**
* Enables WPBakery Page Builder to act as the theme plugin.
*
* @since 4.2
* @var bool
*/
private $is_as_theme = false;
/**
* Vc is network plugin or not.
* @since 4.2
* @var bool
*/
private $is_network_plugin = null;
/**
* List of paths.
*
* @since 4.2
* @var array
*/
private $paths = array();
/**
* Default post types where to activate WPBakery Page Builder meta box settings
* @since 4.2
* @var array
*/
private $editor_default_post_types = array( 'page' ); // TODO: move to Vc settings
/**
* Directory name in theme folder where composer should search for alternative templates of the shortcode.
* @since 4.2
* @var string
*/
private $custom_user_templates_dir = false;
/**
* Set updater mode
* @since 4.2
* @var bool
*/
private $disable_updater = false;
/**
* Modules and objects instances list
* @since 4.2
* @var array
*/
private $factory = array();
/**
* File name for components manifest file.
*
* @since 4.4
* @var string
*/
private $components_manifest = 'components.json';
/**
* @var string
*/
private $plugin_name = 'js_composer/js_composer.php';
/**
* Core singleton class
* @var self - pattern realization
*/
private static $instance;
/**
* @var Vc_Current_User_Access|false
* @since 4.8
*/
private $current_user_access = false;
/**
* @var Vc_Role_Access|false
* @since 4.8
*/
private $role_access = false;
public $editor_post_types;
/**
* Constructor loads API functions, defines paths and adds required wp actions
*
* @since 4.2
*/
private function __construct() {
$dir = WPB_PLUGIN_DIR;
/**
* Define path settings for WPBakery Page Builder.
*
* APP_ROOT - plugin directory.
* WP_ROOT - WP application root directory.
* APP_DIR - plugin directory name.
* CONFIG_DIR - configuration directory.
* ASSETS_DIR - asset directory full path.
* ASSETS_DIR_NAME - directory name for assets. Used from urls creating.
* CORE_DIR - classes directory for core vc files.
* HELPERS_DIR - directory with helpers functions files.
* SHORTCODES_DIR - shortcodes classes.
* SETTINGS_DIR - main dashboard settings classes.
* TEMPLATES_DIR - directory where all html templates are hold.
* EDITORS_DIR - editors for the post contents
* PARAMS_DIR - complex params for shortcodes editor form.
* UPDATERS_DIR - automatic notifications and updating classes.
*/
$this->setPaths( array(
'APP_ROOT' => $dir,
'WP_ROOT' => preg_replace( '/$\//', '', ABSPATH ),
'APP_DIR' => basename( plugin_basename( $dir ) ),
'CONFIG_DIR' => $dir . '/config',
'ASSETS_DIR' => $dir . '/assets',
'ASSETS_DIR_NAME' => 'assets',
'AUTOLOAD_DIR' => $dir . '/include/autoload',
'CORE_DIR' => $dir . '/include/classes/core',
'HELPERS_DIR' => $dir . '/include/helpers',
'SHORTCODES_DIR' => $dir . '/include/classes/shortcodes',
'SETTINGS_DIR' => $dir . '/include/classes/settings',
'TEMPLATES_DIR' => $dir . '/include/templates',
'EDITORS_DIR' => $dir . '/include/classes/editors',
'PARAMS_DIR' => $dir . '/include/params',
'UPDATERS_DIR' => $dir . '/include/classes/updaters',
'VENDORS_DIR' => $dir . '/include/classes/vendors',
'DEPRECATED_DIR' => $dir . '/include/classes/deprecated',
) );
// Load API
require_once $this->path( 'HELPERS_DIR', 'helpers_factory.php' );
require_once $this->path( 'HELPERS_DIR', 'helpers.php' );
require_once $this->path( 'DEPRECATED_DIR', 'interfaces.php' );
require_once $this->path( 'CORE_DIR', 'class-vc-sort.php' ); // used by wpb-map
require_once $this->path( 'CORE_DIR', 'class-wpb-map.php' );
require_once $this->path( 'CORE_DIR', 'class-vc-shared-library.php' );
require_once $this->path( 'HELPERS_DIR', 'helpers_api.php' );
require_once $this->path( 'DEPRECATED_DIR', 'helpers_deprecated.php' );
require_once $this->path( 'PARAMS_DIR', 'params.php' );
require_once $this->path( 'AUTOLOAD_DIR', 'vc-shortcode-autoloader.php' );
require_once $this->path( 'SHORTCODES_DIR', 'core/class-vc-shortcodes-manager.php' );
require_once $this->path( 'CORE_DIR', 'class-vc-modifications.php' );
// Add hooks
add_action( 'plugins_loaded', array(
$this,
'pluginsLoaded',
), 9 );
add_action( 'init', array(
$this,
'init',
), 11 );
$this->setPluginName( $this->path( 'APP_DIR', 'js_composer.php' ) );
register_activation_hook( WPB_PLUGIN_FILE, array(
$this,
'activationHook',
) );
}
/**
* Get the instane of VC_Manager
*
* @return self
*/
public static function getInstance() {
if ( ! ( self::$instance instanceof self ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* prevent the instance from being cloned (which would create a second instance of it)
*/
private function __clone() {
}
/**
* prevent from being unserialized (which would create a second instance of it)
*/
private function __wakeup() {
}
/**
* Callback function WP plugin_loaded action hook. Loads locale
*
* @since 4.2
* @access public
*/
public function pluginsLoaded() {
// Setup locale
do_action( 'vc_plugins_loaded' );
load_plugin_textdomain( 'js_composer', false, $this->path( 'APP_DIR', 'locale' ) );
}
/**
* Callback function for WP init action hook. Sets Vc mode and loads required objects.
*
* @return void
* @throws \Exception
* @since 4.2
* @access public
*/
public function init() {
ob_start();
do_action( 'vc_before_init' );
ob_end_clean(); // FIX for whitespace issues (#76147)
$this->setMode();
do_action( 'vc_after_set_mode' );
/**
* Set version of VC if required.
*/
$this->setVersion();
// Load required
! vc_is_updater_disabled() && vc_updater()->init();
/**
* Init default hooks and options to load.
*/
$this->vc()->init();
/**
* if is admin and not front end editor.
*/
is_admin() && ! vc_is_frontend_editor() && $this->asAdmin();
/**
* if frontend editor is enabled init editor.
*/
vc_enabled_frontend() && vc_frontend_editor()->init();
do_action( 'vc_before_mapping' ); // VC ACTION
// Include default shortcodes.
$this->mapper()->init(); // execute all required
do_action( 'vc_after_mapping' ); // VC ACTION
// Load && Map shortcodes from Automapper.
vc_automapper()->map();
new Vc_Modifications();
if ( vc_user_access()->wpAny( 'manage_options' )->part( 'settings' )->can( 'vc-updater-tab' )->get() ) {
vc_license()->setupReminder();
}
do_action( 'vc_after_init' );
}
/**
* @return Vc_Current_User_Access
* @since 4.8
*/
public function getCurrentUserAccess() {
if ( ! $this->current_user_access ) {
require_once vc_path_dir( 'CORE_DIR', 'access/class-vc-current-user-access.php' );
$this->current_user_access = new Vc_Current_User_Access();
}
return $this->current_user_access;
}
/**
* @param false|Vc_Current_User_Access $current_user_access
*/
public function setCurrentUserAccess( $current_user_access ) {
$this->current_user_access = $current_user_access;
}
/**
* @return Vc_Role_Access
* @since 4.8
*/
public function getRoleAccess() {
if ( ! $this->role_access ) {
require_once vc_path_dir( 'CORE_DIR', 'access/class-vc-role-access.php' );
$this->role_access = new Vc_Role_Access();
}
return $this->role_access;
}
/**
* @param false|Vc_Role_Access $role_access
*/
public function setRoleAccess( $role_access ) {
$this->role_access = $role_access;
}
/**
* Enables to add hooks in activation process.
* @param $networkWide
* @since 4.5
*
*/
public function activationHook( $networkWide = false ) {
do_action( 'vc_activation_hook', $networkWide );
}
/**
* Load required components to enable useful functionality.
*
* @access public
* @since 4.4
*/
public function loadComponents() {
$manifest_file = apply_filters( 'vc_autoload_components_manifest_file', vc_path_dir( 'AUTOLOAD_DIR', $this->components_manifest ) );
if ( is_file( $manifest_file ) ) {
ob_start();
require_once $manifest_file;
$data = ob_get_clean();
if ( $data ) {
$components = (array) json_decode( $data );
$components = apply_filters( 'vc_autoload_components_list', $components );
$dir = vc_path_dir( 'AUTOLOAD_DIR' );
foreach ( $components as $component => $description ) {
$component_path = $dir . '/' . $component;
if ( false === strpos( $component_path, '*' ) ) {
require_once $component_path;
} else {
$components_paths = glob( $component_path );
if ( is_array( $components_paths ) ) {
foreach ( $components_paths as $path ) {
if ( false === strpos( $path, '*' ) ) {
require_once $path;
}
}
}
}
}
}
}
}
/**
* Load required logic for operating in Wp Admin dashboard.
*
* @return void
* @since 4.2
* @access protected
*
*/
protected function asAdmin() {
vc_license()->init();
vc_backend_editor()->addHooksSettings();
}
/**
* Set VC mode.
*
* Mode depends on which page is requested by client from server and request parameters like vc_action.
*
* @return void
* @throws \Exception
* @since 4.2
* @access protected
*/
protected function setMode() {
/**
* TODO: Create another system (When ajax rebuild).
* Use vc_action param to define mode.
* 1. admin_frontend_editor - set by editor or request param
* 2. admin_backend_editor - set by editor or request param
* 3. admin_frontend_editor_ajax - set by request param
* 4. admin_backend_editor_ajax - set by request param
* 5. admin_updater - by vc_action
* 6. page_editable - by vc_action
*/
if ( is_admin() ) {
if ( 'vc_inline' === vc_action() ) {
vc_user_access()->wpAny( array(
'edit_post',
(int) vc_request_param( 'post_id' ),
) )->validateDie()->part( 'frontend_editor' )->can()->validateDie();
$this->mode = 'admin_frontend_editor';
} elseif ( ( vc_user_access()->wpAny( 'edit_posts', 'edit_pages' )
->get() ) && ( 'vc_upgrade' === vc_action() || ( 'update-selected' === vc_get_param( 'action' ) && $this->pluginName() === vc_get_param( 'plugins' ) ) ) ) {
$this->mode = 'admin_updater';
} elseif ( vc_user_access()->wpAny( 'manage_options' )->get() && array_key_exists( vc_get_param( 'page' ), vc_settings()->getTabs() ) ) {
$this->mode = 'admin_settings_page';
} else {
$this->mode = 'admin_page';
}
} else {
if ( 'true' === vc_get_param( 'vc_editable' ) ) {
vc_user_access()->checkAdminNonce()->validateDie()->wpAny( array(
'edit_post',
(int) vc_request_param( 'vc_post_id' ),
) )->validateDie()->part( 'frontend_editor' )->can()->validateDie();
$this->mode = 'page_editable';
} else {
$this->mode = 'page';
}
}
}
/**
* Sets version of the VC in DB as option `vc_version`
*
* @return void
* @since 4.3.2
* @access protected
*
*/
protected function setVersion() {
$version = get_option( 'vc_version' );
if ( ! is_string( $version ) || version_compare( $version, WPB_VC_VERSION ) !== 0 ) {
add_action( 'vc_after_init', array(
vc_settings(),
'rebuild',
) );
update_option( 'vc_version', WPB_VC_VERSION );
}
}
/**
* Get current mode for VC.
*
* @return string
* @since 4.2
* @access public
*
*/
public function mode() {
return $this->mode;
}
/**
* Setter for paths
*
* @param $paths
* @since 4.2
* @access protected
*
*/
protected function setPaths( $paths ) {
$this->paths = $paths;
}
/**
* Gets absolute path for file/directory in filesystem.
*
* @param $name - name of path dir
* @param string $file - file name or directory inside path
*
* @return string
* @since 4.2
* @access public
*
*/
public function path( $name, $file = '' ) {
$path = $this->paths[ $name ] . ( strlen( $file ) > 0 ? '/' . preg_replace( '/^\//', '', $file ) : '' );
return apply_filters( 'vc_path_filter', $path );
}
/**
* Set default post types. Vc editors are enabled for such kind of posts.
*
* @param array $type - list of default post types.
*/
public function setEditorDefaultPostTypes( array $type ) {
$this->editor_default_post_types = $type;
}
/**
* Returns list of default post types where user can use WPBakery Page Builder editors.
*
* @return array
* @since 4.2
* @access public
*
*/
public function editorDefaultPostTypes() {
return $this->editor_default_post_types;
}
/**
* Get post types where VC editors are enabled.
*
* @return array
* @since 4.2
* @access public
*
*/
public function editorPostTypes() {
if ( is_null( $this->editor_post_types ) ) {
$post_types = array_keys( vc_user_access()->part( 'post_types' )->getAllCaps() );
$this->editor_post_types = $post_types ? $post_types : $this->editorDefaultPostTypes();
}
return $this->editor_post_types;
}
/**
* Set post types where VC editors are enabled.
*
* @param array $post_types
* @throws \Exception
* @since 4.4
* @access public
*/
public function setEditorPostTypes( array $post_types ) {
$this->editor_post_types = ! empty( $post_types ) ? $post_types : $this->editorDefaultPostTypes();
require_once ABSPATH . 'wp-admin/includes/user.php';
$editable_roles = get_editable_roles();
foreach ( $editable_roles as $role => $settings ) {
$part = vc_role_access()->who( $role )->part( 'post_types' );
$all_post_types = $part->getAllCaps();
foreach ( $all_post_types as $post_type => $value ) {
$part->getRole()->remove_cap( $part->getStateKey() . '/' . $post_type );
}
$part->setState( 'custom' );
foreach ( $this->editor_post_types as $post_type ) {
$part->setCapRule( $post_type );
}
}
}
/**
* Setter for as-theme-plugin status for VC.
*
* @param bool $value
* @since 4.2
* @access public
*
*/
public function setIsAsTheme( $value = true ) {
$this->is_as_theme = (bool) $value;
}
/**
* Get as-theme-plugin status
*
* As theme plugin status used by theme developers. It disables settings
*
* @return bool
* @since 4.2
* @access public
*
*/
public function isAsTheme() {
return (bool) $this->is_as_theme;
}
/**
* Setter for as network plugin for MultiWP.
*
* @param bool $value
* @since 4.2
* @access public
*
*/
public function setAsNetworkPlugin( $value = true ) {
$this->is_network_plugin = $value;
}
/**
* Gets VC is activated as network plugin.
*
* @return bool
* @since 4.2
* @access public
*
*/
public function isNetworkPlugin() {
if ( is_null( $this->is_network_plugin ) ) {
// Check is VC as network plugin
if ( is_multisite() && ( is_plugin_active_for_network( $this->pluginName() ) || is_network_only_plugin( $this->pluginName() ) ) ) {
$this->setAsNetworkPlugin( true );
}
}
return $this->is_network_plugin ? true : false;
}
/**
* Setter for disable updater variable.
* @param bool $value
*
* @since 4.2
*/
public function disableUpdater( $value = true ) {
$this->disable_updater = $value;
}
/**
* Get is vc updater is disabled;
*
* @return bool
* @see to where updater will be
*
* @since 4.2
*/
public function isUpdaterDisabled() {
return is_admin() && $this->disable_updater;
}
/**
* Set user directory name.
*
* Directory name is the directory name vc should scan for custom shortcodes template.
*
* @param $dir - path to shortcodes templates inside developers theme
* @since 4.2
* @access public
*
*/
public function setCustomUserShortcodesTemplateDir( $dir ) {
preg_replace( '/\/$/', '', $dir );
$this->custom_user_templates_dir = $dir;
}
/**
* Get default directory where shortcodes templates area placed.
*
* @return string - path to default shortcodes
* @since 4.2
* @access public
*
*/
public function getDefaultShortcodesTemplatesDir() {
return vc_path_dir( 'TEMPLATES_DIR', 'shortcodes' );
}
/**
*
* Get shortcodes template dir.
*
* @param $template
*
* @return string
* @since 4.2
* @access public
*
*/
public function getShortcodesTemplateDir( $template ) {
return false !== $this->custom_user_templates_dir ? $this->custom_user_templates_dir . '/' . $template : locate_template( 'vc_templates/' . $template );
}
/**
* Directory name where template files will be stored.
*
* @return string
* @since 4.2
* @access public
*
*/
public function uploadDir() {
return 'js_composer';
}
/**
* Getter for VC_Mapper instance
*
* @return Vc_Mapper
* @since 4.2
* @access public
*
*/
public function mapper() {
if ( ! isset( $this->factory['mapper'] ) ) {
require_once $this->path( 'CORE_DIR', 'class-vc-mapper.php' );
$this->factory['mapper'] = new Vc_Mapper();
}
return $this->factory['mapper'];
}
/**
* WPBakery Page Builder.
*
* @return Vc_Base
* @since 4.2
* @access public
*
*/
public function vc() {
if ( ! isset( $this->factory['vc'] ) ) {
do_action( 'vc_before_init_vc' );
require_once $this->path( 'CORE_DIR', 'class-vc-base.php' );
$vc = new Vc_Base();
// DI Set template new modal editor.
require_once $this->path( 'EDITORS_DIR', 'popups/class-vc-templates-panel-editor.php' );
require_once $this->path( 'CORE_DIR', 'shared-templates/class-vc-shared-templates.php' );
$vc->setTemplatesPanelEditor( new Vc_Templates_Panel_Editor() );
// Create shared templates
$vc->shared_templates = new Vc_Shared_Templates();
// DI Set edit form
require_once $this->path( 'EDITORS_DIR', 'popups/class-vc-shortcode-edit-form.php' );
$vc->setEditForm( new Vc_Shortcode_Edit_Form() );
// DI Set preset new modal editor.
require_once $this->path( 'EDITORS_DIR', 'popups/class-vc-preset-panel-editor.php' );
$vc->setPresetPanelEditor( new Vc_Preset_Panel_Editor() );
$this->factory['vc'] = $vc;
do_action( 'vc_after_init_vc' );
}
return $this->factory['vc'];
}
/**
* Vc options.
*
* @return Vc_Settings
* @since 4.2
* @access public
*
*/
public function settings() {
if ( ! isset( $this->factory['settings'] ) ) {
do_action( 'vc_before_init_settings' );
require_once $this->path( 'SETTINGS_DIR', 'class-vc-settings.php' );
$this->factory['settings'] = new Vc_Settings();
do_action( 'vc_after_init_settings' );
}
return $this->factory['settings'];
}
/**
* Vc license settings.
*
* @return Vc_License
* @since 4.2
* @access public
*
*/
public function license() {
if ( ! isset( $this->factory['license'] ) ) {
do_action( 'vc_before_init_license' );
require_once $this->path( 'SETTINGS_DIR', 'class-vc-license.php' );
$this->factory['license'] = new Vc_License();
do_action( 'vc_after_init_license' );
}
return $this->factory['license'];
}
/**
* Get frontend VC editor.
*
* @return Vc_Frontend_Editor
* @since 4.2
* @access public
*
*/
public function frontendEditor() {
if ( ! isset( $this->factory['frontend_editor'] ) ) {
do_action( 'vc_before_init_frontend_editor' );
require_once $this->path( 'EDITORS_DIR', 'class-vc-frontend-editor.php' );
$this->factory['frontend_editor'] = new Vc_Frontend_Editor();
}
return $this->factory['frontend_editor'];
}
/**
* Get backend VC editor. Edit page version.
*
* @return Vc_Backend_Editor
* @since 4.2
*
*/
public function backendEditor() {
if ( ! isset( $this->factory['backend_editor'] ) ) {
do_action( 'vc_before_init_backend_editor' );
require_once $this->path( 'EDITORS_DIR', 'class-vc-backend-editor.php' );
$this->factory['backend_editor'] = new Vc_Backend_Editor();
}
return $this->factory['backend_editor'];
}
/**
* Gets automapper instance.
*
* @return Vc_Automapper
* @since 4.2
* @access public
*
*/
public function automapper() {
if ( ! isset( $this->factory['automapper'] ) ) {
do_action( 'vc_before_init_automapper' );
require_once $this->path( 'SETTINGS_DIR', 'automapper/automapper.php' );
require_once $this->path( 'SETTINGS_DIR', 'automapper/class-vc-automap-model.php' );
require_once $this->path( 'SETTINGS_DIR', 'automapper/class-vc-automapper.php' );
$this->factory['automapper'] = new Vc_Automapper();
do_action( 'vc_after_init_automapper' );
}
return $this->factory['automapper'];
}
/**
* Gets updater instance.
* @return Vc_Updater
* @since 4.2
*
*/
public function updater() {
if ( ! isset( $this->factory['updater'] ) ) {
do_action( 'vc_before_init_updater' );
require_once $this->path( 'UPDATERS_DIR', 'class-vc-updater.php' );
$updater = new Vc_Updater();
require_once vc_path_dir( 'UPDATERS_DIR', 'class-vc-updating-manager.php' );
$updater->setUpdateManager( new Vc_Updating_Manager( WPB_VC_VERSION, $updater->versionUrl(), $this->pluginName() ) );
$this->factory['updater'] = $updater;
do_action( 'vc_after_init_updater' );
}
return $this->factory['updater'];
}
/**
* Getter for plugin name variable.
* @return string
* @since 4.2
*
*/
public function pluginName() {
return $this->plugin_name;
}
/**
* @param $name
* @since 4.8.1
*/
public function setPluginName( $name ) {
$this->plugin_name = $name;
}
/**
* Get absolute url for VC asset file.
*
* Assets are css, javascript, less files and images.
*
* @param $file
*
* @return string
* @since 4.2
*
*/
public function assetUrl( $file ) {
return preg_replace( '/\s/', '%20', plugins_url( $this->path( 'ASSETS_DIR_NAME', $file ), WPB_PLUGIN_FILE ) );
}
}

View File

@@ -0,0 +1,216 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* WPBakery WPBakery Page Builder Main manager.
*
* @package WPBakeryPageBuilder
* @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();
protected $checkForAccess = true;
/**
* @since 4.2
*/
public 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.
*
* @param $object - mame of class object
* @param $method - method name
* @param array $params - list of attributes for object method
* @since 4.2
* @access public
*
* @see WPBMAP
*/
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.
*
* @param $tag - shortcode tag of element
* @param $method - method name
* @param array $params - list of attributes for object method
* @since 4.9
* @access public
*
* @see WPBMAP
*/
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' );
foreach ( $this->init_activity as $activity ) {
list( $object, $method, $params ) = $activity;
if ( 'mapper' === $object ) {
switch ( $method ) {
case 'map':
$currentScope = WPBMap::getScope();
if ( isset( $params['scope'] ) ) {
WPBMap::setScope( $params['scope'] );
}
WPBMap::map( $params['tag'], $params['attributes'] );
WPBMap::setScope( $currentScope );
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
*
* @return bool
* @since 4.5
* @todo fix_roles and maybe remove/@deprecate this
*/
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;
}
/**
* @return bool
* @since 4.5
* @todo fix_roles and maybe remove/@deprecate this
*/
public function isCheckForAccess() {
return $this->checkForAccess;
}
/**
* @param bool $checkForAccess
* @since 4.5
*
* @todo fix_roles and maybe remove/@deprecate this
*/
public function setCheckForAccess( $checkForAccess ) {
$this->checkForAccess = $checkForAccess;
}
/**
* @param $tag
* @throws \Exception
*/
public function callElementActivities( $tag ) {
do_action( 'vc_mapper_call_activities_before' );
if ( isset( $this->element_activities[ $tag ] ) ) {
foreach ( $this->element_activities[ $tag ] as $activity ) {
list( $method, $params ) = $activity;
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;
}
}
}
}
}

View File

@@ -0,0 +1,24 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
class Vc_Modifications {
public static $modified = false;
public function __construct() {
add_action( 'wp_footer', array(
$this,
'renderScript',
) );
}
public function renderScript() {
if ( self::$modified ) {
// output script
$tag = 'script';
echo '<' . $tag . ' type="text/html" id="wpb-modifications"></' . $tag . '>';
}
}
}

View File

@@ -0,0 +1,74 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Class Vc_Page
*/
class Vc_Page {
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() {
vc_include_template( $this->getTemplatePath(), array(
'page' => $this,
) );
}
}

View File

@@ -0,0 +1,80 @@
<?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,
) );
}
}

View File

@@ -0,0 +1,179 @@
<?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() {
// Called in BE
add_action( 'save_post', array(
$this,
'save',
) );
// Called in FE
add_action( 'wp_ajax_vc_save', array(
$this,
'saveAjaxFe',
) );
}
/**
* @throws \Exception
*/
public function saveAjaxFe() {
vc_user_access()->checkAdminNonce()->validateDie()->wpAny( 'edit_posts', 'edit_pages' )->validateDie();
$post_id = intval( vc_post_param( 'post_id' ) );
if ( $post_id > 0 ) {
ob_start();
// Update post_content, title and etc.
// post_title
// content
// post_status
if ( vc_post_param( 'content' ) ) {
$post = get_post( $post_id );
$post->post_content = stripslashes( vc_post_param( 'content' ) );
$post_status = vc_post_param( 'post_status' );
$post_title = vc_post_param( 'post_title' );
if ( null !== $post_title ) {
$post->post_title = $post_title;
}
kses_remove_filters();
remove_filter( 'content_save_pre', 'balanceTags', 50 );
if ( $post_status && 'publish' === $post_status ) {
if ( vc_user_access()->wpAll( array(
get_post_type_object( $post->post_type )->cap->publish_posts,
$post_id,
) )->get() ) {
if ( 'private' !== $post->post_status && 'future' !== $post->post_status ) {
$post->post_status = 'publish';
}
} else {
$post->post_status = 'pending';
}
}
wp_update_post( $post );
$this->setPostMeta( $post_id );
}
visual_composer()->buildShortcodesCustomCss( $post_id );
wp_cache_flush();
ob_clean();
wp_send_json_success();
}
wp_send_json_error();
}/** @noinspection PhpDocMissingThrowsInspection */
/**
* Save generated shortcodes, html and WPBakery Page Builder status in posts meta.
*
* @access public
* @param $post_id - current post id
*
* @return void
* @since 4.4
*
*/
public function save( $post_id ) {
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE || vc_is_inline() ) {
return;
}
$this->setPostMeta( $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'.
* @param $post_id
* @since 4.4
*
*/
public function setJsStatus( $post_id ) {
$value = vc_post_param( 'wpb_vc_js_status' );
if ( null !== $value ) {
if ( '' === get_post_meta( $post_id, '_wpb_vc_js_status' ) ) {
add_post_meta( $post_id, '_wpb_vc_js_status', $value, true );
} elseif ( get_post_meta( $post_id, '_wpb_vc_js_status', true ) !== $value ) {
update_post_meta( $post_id, '_wpb_vc_js_status', $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.
* @param $post_id
* @since 4.4
* @todo check is it used everywhere and is it needed?!
* @deprecated not needed anywhere
*/
public function setInterfaceVersion( $post_id ) {
_deprecated_function( '\Vc_Post_Admin::setInterfaceVersion', '4.4', '' );
}
/**
* 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'.
* @param $post_id
* @since 4.4
* vc_filter: vc_hooks_vc_post_settings - hook to override post meta settings for WPBakery Page Builder (used in grid for
* example)
*
*/
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' );
}
}
/**
* @param $post_id
* @throws \Exception
*/
protected function setPostMeta( $post_id ) {
if ( ! vc_user_access()->wpAny( array(
'edit_post',
$post_id,
) )->get() ) {
return;
}
$this->setJsStatus( $post_id );
if ( 'dopreview' !== vc_post_param( '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' ), $post_id );
if ( null !== $post_custom_css && empty( $post_custom_css ) ) {
delete_metadata( 'post', $post_id, '_wpb_post_custom_css' );
} elseif ( null !== $post_custom_css ) {
$post_custom_css = wp_strip_all_tags( $post_custom_css );
update_metadata( 'post', $post_id, '_wpb_post_custom_css', $post_custom_css );
}
visual_composer()->buildShortcodesCustomCss( $post_id );
}
}

View File

@@ -0,0 +1,350 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/*** WPBakery Page Builder 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, true ) ) {
$list += self::$box_styles;
}
if ( ! $groups || in_array( 'round', $groups, true ) ) {
$list += self::$round_box_styles;
}
if ( ! $groups || in_array( 'cirlce', $groups, true ) ) {
$list += self::$circle_box_styles;
}
return $list;
}
/**
* @return array
*/
public static function getColorsDashed() {
$colors = array(
esc_html__( 'Blue', 'js_composer' ) => 'blue',
esc_html__( 'Turquoise', 'js_composer' ) => 'turquoise',
esc_html__( 'Pink', 'js_composer' ) => 'pink',
esc_html__( 'Violet', 'js_composer' ) => 'violet',
esc_html__( 'Peacoc', 'js_composer' ) => 'peacoc',
esc_html__( 'Chino', 'js_composer' ) => 'chino',
esc_html__( 'Mulled Wine', 'js_composer' ) => 'mulled-wine',
esc_html__( 'Vista Blue', 'js_composer' ) => 'vista-blue',
esc_html__( 'Black', 'js_composer' ) => 'black',
esc_html__( 'Grey', 'js_composer' ) => 'grey',
esc_html__( 'Orange', 'js_composer' ) => 'orange',
esc_html__( 'Sky', 'js_composer' ) => 'sky',
esc_html__( 'Green', 'js_composer' ) => 'green',
esc_html__( 'Juicy pink', 'js_composer' ) => 'juicy-pink',
esc_html__( 'Sandy brown', 'js_composer' ) => 'sandy-brown',
esc_html__( 'Purple', 'js_composer' ) => 'purple',
esc_html__( 'White', 'js_composer' ) => 'white',
);
return $colors;
}
}

View File

@@ -0,0 +1,103 @@
<?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';
/**
* @param $data - array to sort
* @since 4.4
*
*/
public function __construct( $data ) {
$this->data = $data;
}
/**
* Used to change/set data to sort
*
* @param $data
* @since 4.5
*
*/
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).
*
* @param string $key
*
* @return array - sorted array
* @since 4.4
*
*/
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
* @param $a - compare value
* @param $b - compare value
*
* @return int
* @since 4.4
*
*/
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 ) {
// @codingStandardsIgnoreLine
$cmp_a = array_search( $a, $this->data );
// @codingStandardsIgnoreLine
$cmp_b = array_search( $b, $this->data );
return $cmp_a - $cmp_b;
}
return $b_weight - $a_weight;
}
/**
* @return array - sorting data
* @since 4.4
*
*/
public function getData() {
return $this->data;
}
}

View File

@@ -0,0 +1,974 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* WPBakery WPBakery Page Builder Main manager.
*
* @package WPBakeryPageBuilder
* @since 4.2
*/
class WPBMap {
protected static $scope = 'default';
/**
* @var array
*/
protected static $sc = array();
protected static $scopes = array(
'default' => array(),
);
protected static $removedElements = 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();
protected static $init_elements_scoped = array(
'default' => 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.
*
* @param bool $value
* @see Vc_Mapper::iniy.
* @static
*
*/
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 ) {
$currentScope = self::getScope();
if ( 'default' !== $currentScope ) {
if ( isset( self::$scopes[ $currentScope ], self::$scopes[ $currentScope ][ $tag ] ) ) {
return true;
}
}
return (bool) 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 ( in_array( $tag, self::$removedElements, true ) ) {
return false;
}
if ( ! self::$is_init ) {
if ( empty( $attributes['name'] ) ) {
throw new Exception( sprintf( esc_html__( 'Wrong name for shortcode:%s. Name required', 'js_composer' ), $tag ) );
} elseif ( empty( $attributes['base'] ) ) {
throw new Exception( sprintf( esc_html__( 'Wrong base for shortcode:%s. Base required', 'js_composer' ), $tag ) );
} else {
vc_mapper()->addActivity( 'mapper', 'map', array(
'tag' => $tag,
'attributes' => $attributes,
'scope' => self::getScope(),
) );
return true;
}
return false;
}
if ( empty( $attributes['name'] ) ) {
throw new Exception( sprintf( esc_html__( 'Wrong name for shortcode:%s. Name required', 'js_composer' ), $tag ) );
} elseif ( empty( $attributes['base'] ) ) {
throw new Exception( sprintf( esc_html__( 'Wrong base for shortcode:%s. Base required', 'js_composer' ), $tag ) );
} else {
if ( self::getScope() !== 'default' ) {
if ( ! isset( self::$scopes[ self::getScope() ] ) ) {
self::$scopes[ self::getScope() ] = array();
}
self::$scopes[ self::getScope() ][ $tag ] = $attributes;
} else {
self::$sc[ $tag ] = $attributes;
}
// Unset cache class object in case if re-map called
if ( Vc_Shortcodes_Manager::getInstance()->isShortcodeClassInitialized( $tag ) ) {
Vc_Shortcodes_Manager::getInstance()->unsetElementClass( $tag );
}
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
* @param $tag
* @param $settings_file
* @param $settings_function
* @param $attributes
*
* @return bool
* @since 4.9
*
*/
public static function leanMap( $tag, $settings_function = null, $settings_file = null, $attributes = array() ) {
if ( in_array( $tag, self::$removedElements, true ) ) {
return false;
}
$currentScope = self::getScope();
if ( 'default' !== $currentScope ) {
if ( ! isset( self::$scopes[ $currentScope ] ) ) {
self::$scopes[ $currentScope ] = array();
}
self::$scopes[ $currentScope ][ $tag ] = $attributes;
self::$scopes[ $currentScope ][ $tag ]['base'] = $tag;
if ( is_string( $settings_file ) ) {
self::$scopes[ $currentScope ][ $tag ]['__vc_settings_file'] = $settings_file;
}
if ( ! is_null( $settings_function ) ) {
self::$scopes[ $currentScope ][ $tag ]['__vc_settings_function'] = $settings_function;
}
} else {
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.
* @throws \Exception
*/
protected static function generateUserData( $force = false ) {
if ( ! $force && false !== self::$user_sc && false !== self::$user_categories ) {
return;
}
self::$user_sc = array();
self::$user_categories = array();
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, true ) ) {
self::$user_categories[] = $c;
}
$values['_category_ids'][] = md5( $c );
}
} else {
if ( false === array_search( $categories, self::$user_categories, true ) ) {
self::$user_categories[] = $categories;
}
$values['_category_ids'][] = md5( $categories );
}
}
}
if ( ! empty( $values['params'] ) ) {
$params = $values['params'];
$values['params'] = array();
foreach ( $params as $attribute ) {
$attribute = apply_filters( 'vc_mapper_attribute', $attribute, $name );
$attribute = apply_filters( 'vc_mapper_attribute_' . $attribute['type'], $attribute, $name );
$values['params'][] = $attribute;
}
$sort = new Vc_Sort( $values['params'] );
$values['params'] = $sort->sortByKey();
}
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.
* @throws \Exception
*/
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
* @throws \Exception
*/
public static function getAllShortCodes() {
self::generateData();
return self::$sc;
}
/**
* Get mapped shortcode settings.
*
* @static
* @return bool
* @throws \Exception
*/
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 bool
* @throws \Exception
*/
public static function getSortedUserShortCodes() {
self::generateUserData();
return self::$user_sorted_sc;
}
/**
* Get list of mapped shortcode settings for current user.
* @static
* @return bool - associated array of shortcodes settings with tag as the key.
* @throws \Exception
*/
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
* @throws \Exception
*/
public static function getShortCode( $tag ) {
return self::setElementSettings( $tag );
}
/**
* Get mapped shortcode settings by tag.
*
* @param $tag - shortcode tag.
*
* @return array|null
* @throws \Exception
* @since 4.5.2
* @static
*/
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
* @throws \Exception
*/
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 bool
* @throws \Exception
*/
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 ) {
$currentScope = self::getScope();
if ( 'default' !== $currentScope ) {
self::setScope( 'default' );
$res = self::dropParam( $name, $attribute_name );
self::setScope( $currentScope );
return $res;
}
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 ] );
// fix indexes
self::$sc[ $name ]['params'] = array_merge( self::$sc[ $name ]['params'] );
return true;
}
}
}
return true;
}
/**
* Returns param settings for mapped shortcodes.
*
* @static
*
* @param $tag
* @param $param_name
*
* @return bool| array
* @throws \Exception
*/
public static function getParam( $tag, $param_name ) {
$currentScope = self::getScope();
$element = false;
if ( 'default' !== $currentScope ) {
if ( isset( self::$scopes[ $currentScope ][ $tag ], self::$scopes[ $currentScope ][ $tag ] ) ) {
$element = self::$scopes[ $currentScope ][ $tag ];
}
}
if ( ! $element && isset( self::$sc[ $tag ] ) ) {
$element = self::$sc[ $tag ];
}
if ( ! $element ) {
// No element found
return false;
}
if ( isset( $element['__vc_settings_function'] ) || isset( $element['__vc_settings_file'] ) ) {
$element = self::setElementSettings( $tag );
}
if ( ! isset( $element['params'] ) ) {
return false;
}
foreach ( $element['params'] as $index => $param ) {
if ( $param['param_name'] === $param_name ) {
return $element['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() ) {
$currentScope = self::getScope();
if ( 'default' !== $currentScope ) {
self::setScope( 'default' );
$res = self::addParam( $name, $attribute );
self::setScope( $currentScope );
return $res;
}
if ( ! isset( self::$init_elements[ $name ] ) ) {
vc_mapper()->addElementActivity( $name, 'add_param', array(
'name' => $name,
'attribute' => $attribute,
) );
return false;
}
if ( ! isset( self::$sc[ $name ] ) ) {
// No shortcode found
return false;
} elseif ( ! isset( $attribute['param_name'] ) ) {
throw new Exception( sprintf( esc_html__( "Wrong attribute for '%s' shortcode. Attribute 'param_name' required", 'js_composer' ), $name ) );
} else {
$replaced = false;
if ( is_array( self::$sc[ $name ]['params'] ) ) {
foreach ( self::$sc[ $name ]['params'] as $index => $param ) {
if ( $param['param_name'] === $attribute['param_name'] ) {
$replaced = true;
self::$sc[ $name ]['params'][ $index ] = $attribute;
break;
}
}
} else {
self::$sc[ $name ]['params'] = array();
}
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() ) {
$currentScope = self::getScope();
if ( 'default' !== $currentScope ) {
self::setScope( 'default' );
$res = self::mutateParam( $name, $attribute );
self::setScope( $currentScope );
return $res;
}
if ( ! isset( self::$init_elements[ $name ] ) ) {
vc_mapper()->addElementActivity( $name, 'mutate_param', array(
'name' => $name,
'attribute' => $attribute,
) );
return false;
}
if ( ! isset( self::$sc[ $name ] ) ) {
// No shortcode found
return false;
} elseif ( ! isset( $attribute['param_name'] ) ) {
throw new Exception( sprintf( esc_html__( "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 ) {
$currentScope = self::getScope();
if ( 'default' !== $currentScope ) {
self::setScope( 'default' );
$res = self::dropShortcode( $name );
self::setScope( $currentScope );
return $res;
}
self::$removedElements[] = $name;
if ( ! isset( self::$init_elements[ $name ] ) ) {
vc_mapper()->addElementActivity( $name, 'drop_shortcode', array(
'name' => $name,
) );
}
unset( self::$sc[ $name ] );
visual_composer()->removeShortCode( $name );
return true;
}
/**
* @return bool
*/
public static function dropAllShortcodes() {
$currentScope = self::getScope();
if ( 'default' !== $currentScope ) {
self::setScope( 'default' );
$res = self::dropAllShortcodes();
self::setScope( $currentScope );
return $res;
}
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 = false;
self::$user_categories = false;
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 string $value - value of settings if $setting_name is option key.
*
* @return array|bool
* @throws \Exception
*/
public static function modify( $name, $setting_name, $value = '' ) {
$currentScope = self::getScope();
if ( 'default' !== $currentScope ) {
self::setScope( 'default' );
$res = self::modify( $name, $setting_name, $value );
self::setScope( $currentScope );
return $res;
}
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 ] ) ) {
// No shortcode found
return false;
} elseif ( 'base' === $setting_name ) {
throw new Exception( sprintf( esc_html__( "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 ) ) {
// fix indexes
$value = array_merge( $value );
}
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.
* @param $a
* @param $b
*
* @return int
* @deprecated - use Vc_Sort::sortByKey since 4.4
* @static
*
*/
public static function sort( $a, $b ) {
$a_weight = isset( $a['weight'] ) ? (int) $a['weight'] : 0;
$b_weight = isset( $b['weight'] ) ? (int) $b['weight'] : 0;
if ( $a_weight === $b_weight ) {
// @codingStandardsIgnoreLine
$cmpa = array_search( $a, (array) self::$user_sorted_sc, true );
// @codingStandardsIgnoreLine
$cmpb = array_search( $b, (array) self::$user_sorted_sc, true );
return ( $cmpa > $cmpb ) ? 1 : - 1;
}
return ( $a_weight < $b_weight ) ? 1 : - 1;
}
/**
* @param $shortcodes
* @return array
*/
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, true ) ) {
$categories[] = $c;
}
$values['_category_ids'][] = md5( $c );
}
} else {
if ( false === array_search( $categories, $categories_list, true ) ) {
$categories_list[] = $categories;
}
/** @var string $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
*
* @param $tag
*
* @return array|null
* @throws \Exception
* @since 4.9
*/
public static function setElementSettings( $tag ) {
$currentScope = self::getScope();
if ( 'default' !== $currentScope ) {
if ( isset( self::$scopes[ $currentScope ], self::$scopes[ $currentScope ][ $tag ] ) && ! in_array( $tag, self::$removedElements, true ) ) {
if ( isset( self::$init_elements_scoped[ $currentScope ], self::$init_elements_scoped[ $currentScope ][ $tag ] ) && ! empty( self::$init_elements_scoped[ $currentScope ][ $tag ] ) ) {
return self::$scopes[ $currentScope ][ $tag ];
}
$settings = self::$scopes[ $currentScope ][ $tag ];
if ( isset( $settings['__vc_settings_function'] ) ) {
self::$scopes[ $currentScope ][ $tag ] = call_user_func( $settings['__vc_settings_function'], $tag );
} elseif ( isset( $settings['__vc_settings_file'] ) ) {
self::$scopes[ $currentScope ][ $tag ] = include $settings['__vc_settings_file'];
}
self::$scopes[ $currentScope ][ $tag ]['base'] = $tag;
self::$init_elements_scoped[ $currentScope ][ $tag ] = true;
vc_mapper()->callElementActivities( $tag );
return self::$scopes[ $currentScope ][ $tag ];
}
}
if ( ! isset( self::$sc[ $tag ] ) || in_array( $tag, self::$removedElements, true ) ) {
return null;
}
if ( isset( self::$init_elements[ $tag ] ) && self::$init_elements[ $tag ] ) {
return self::$sc[ $tag ];
}
$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 self::$sc[ $tag ];
}
/**
* Add elements as shortcodes
*
* @since 4.9
*/
public static function addAllMappedShortcodes() {
foreach ( self::$sc as $tag => $settings ) {
if ( ! in_array( $tag, self::$removedElements, true ) && ! shortcode_exists( $tag ) ) {
add_shortcode( $tag, 'vc_do_shortcode' );
}
}
// Map also custom scopes
foreach ( self::$scopes as $scopeName => $scopeElements ) {
foreach ( $scopeElements as $tag => $settings ) {
if ( ! in_array( $tag, self::$removedElements, true ) && ! shortcode_exists( $tag ) ) {
add_shortcode( $tag, 'vc_do_shortcode' );
}
}
}
}
/**
* @param string $scope
*/
public static function setScope( $scope = 'default' ) {
if ( ! isset( self::$scopes[ $scope ] ) ) {
self::$scopes[ $scope ] = array();
self::$init_elements_scoped[ $scope ] = array();
}
self::$scope = $scope;
}
public static function resetScope() {
self::$scope = 'default';
}
/**
* @return string
*/
public static function getScope() {
return self::$scope;
}
}

View File

@@ -0,0 +1,354 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
require_once dirname( __FILE__ ) . '/importer/class-vc-wp-import.php';
require_once dirname( __FILE__ ) . '/importer/class-vc-wxr-parser-plugin.php';
/**
* Class Vc_Shared_Templates
*/
class Vc_Shared_Templates {
/**
* @var bool
*/
protected $initialized = false;
/**
* @var string
*/
protected $download_link_url = 'https://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_filter( 'wp_ajax_vc_shared_templates_download', array(
$this,
'ajaxDownloadTemplate',
) );
add_filter( 'vc_get_all_templates', array(
$this,
'addTemplatesTab',
) );
$this->registerPostType();
}
/**
* @param $templateId
* @param $templateType
* @return string
*/
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;
}
/**
* @param $templateId
* @param $templateType
* @return mixed
*/
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;
}
/**
* @param $templateId
* @param $templateType
* @return mixed
*/
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( wp_json_encode( array(
'success' => false,
'message' => 'access denied',
) ) )->part( 'templates' )->checkStateAny( true, null )->validateDie( wp_json_encode( array(
'success' => false,
'message' => 'part access denied',
) ) )->check( array(
vc_license(),
'isActivated',
) );
$access->validateDie( wp_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 ) {
// FIX SSL SNI
$filter_add = true;
if ( function_exists( 'curl_version' ) ) {
$version = curl_version();
if ( version_compare( $version['version'], '7.18', '>=' ) ) {
$filter_add = false;
}
}
if ( $filter_add ) {
add_filter( 'https_ssl_verify', '__return_false' );
}
$downloadUrlRequest = wp_remote_get( $requestUrl, array(
'timeout' => 30,
) );
if ( $filter_add ) {
remove_filter( 'https_ssl_verify', '__return_false' );
}
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 ) {
if ( vc_user_access()->part( 'templates' )->checkStateAny( true, null, 'add' )->get() ) {
$templates = $this->getTemplates();
if ( ! empty( $templates ) || vc_user_access()->part( 'templates' )->checkStateAny( true, null )->get() ) {
$newCategory = array(
'category' => 'shared_templates',
'category_name' => esc_html__( '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();
}
/**
* @return array
*/
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;
}
}

View File

@@ -0,0 +1,664 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/*
* Modified by WPBakery Page Builder 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 WPBakery Page Builder
Text Domain: js_composer
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__ ) . '/class-vc-wxr-parser.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
*/
class Vc_WP_Import extends WP_Importer {
/**
* @var float
*/
public $max_wxr_version = 1.2; // max. supported WXR version
/**
* @var
*/
public $id;
/**
* @var information to import from WXR file
*/
public $version;
/**
* @var array
*/
public $posts = array();
/**
* @var string
*/
public $base_url = '';
// mappings from old information to new
/**
* @var array
*/
public $processed_posts = array();
/**
* @var array
*/
public $processed_attachments = array();
/**
* @var array
*/
public $post_orphans = array();
/**
* @var bool
*/
public $fetch_attachments = true;
/**
* @var array
*/
public $url_remap = array();
/**
* @var 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>' . esc_html__( 'Sorry, there has been an error.', 'js_composer' ) . '</strong><br />';
echo esc_html__( 'The file does not exist, please try again.', 'js_composer' ) . '</p>';
die();
}
$import_data = $this->parse( $file );
if ( is_wp_error( $import_data ) ) {
echo '<p><strong>' . esc_html__( 'Sorry, there has been an error.', 'js_composer' ) . '</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>' . esc_html__( 'Sorry, there has been an error.', 'js_composer' ) . '</strong><br />';
echo esc_html( $file['error'] ) . '</p>';
return false;
} elseif ( ! file_exists( $file['file'] ) ) {
echo '<p><strong>' . esc_html__( 'Sorry, there has been an error.', 'js_composer' ) . '</strong><br />';
printf( esc_html__( 'The export file could not be found at %s. It is likely that this was caused by a permissions problem.', 'js_composer' ), '<code>' . esc_html( $file['file'] ) . '</code>' );
echo '</p>';
return false;
}
$this->id = (int) $file['id'];
$import_data = $this->parse( $file['file'] );
if ( is_wp_error( $import_data ) ) {
echo '<p><strong>' . esc_html__( 'Sorry, there has been an error.', 'js_composer' ) . '</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( esc_html__( 'This WXR file (version %s) may not be supported by this version of the importer. Please consider updating.', 'js_composer' ), 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(
'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 ( true === $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', esc_html__( 'Fetching attachments is not enabled', 'js_composer' ) );
}
// 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;
}
$info = wp_check_filetype( $upload['file'] );
if ( $info ) {
$post['post_mime_type'] = $info['type'];
} else {
return new WP_Error( 'attachment_processing_error', esc_html__( 'Invalid file type', 'js_composer' ) );
}
$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;
}
/**
* @param $url
* @param bool $file_path
* @return array|bool|\Requests_Utility_CaseInsensitiveDictionary
*/
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 ( ! $file_path ) {
return $headers;
}
// GET request - write it to the supplied filename
// @codingStandardsIgnoreLine
$out_fp = fopen( $file_path, 'w' );
if ( ! $out_fp ) {
return $headers;
}
// @codingStandardsIgnoreLine
fwrite( $out_fp, wp_remote_retrieve_body( $response ) );
// @codingStandardsIgnoreLine
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, null, '', $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 ) {
// @codingStandardsIgnoreLine
@unlink( $upload['file'] );
return new WP_Error( 'import_file_error', esc_html__( 'Remote server did not respond', 'js_composer' ) );
}
// make sure the fetch was successful
if ( intval( $headers['response'] ) !== 200 ) {
// @codingStandardsIgnoreLine
@unlink( $upload['file'] );
return new WP_Error( 'import_file_error', sprintf( esc_html__( 'Remote server returned error response %1$d %2$s', 'js_composer' ), esc_html( $headers['response'] ), get_status_header_desc( $headers['response'] ) ) );
}
$filesize = filesize( $upload['file'] );
if ( isset( $headers['content-length'] ) && intval( $headers['content-length'] ) !== $filesize ) {
// @codingStandardsIgnoreLine
@unlink( $upload['file'] );
return new WP_Error( 'import_file_error', esc_html__( 'Remote file is incorrect size', 'js_composer' ) );
}
if ( ! $filesize ) {
// @codingStandardsIgnoreLine
@unlink( $upload['file'] );
return new WP_Error( 'import_file_error', esc_html__( 'Zero size file downloaded', 'js_composer' ) );
}
$max_size = (int) $this->max_attachment_size();
if ( ! empty( $max_size ) && $filesize > $max_size ) {
// @codingStandardsIgnoreLine
@unlink( $upload['file'] );
return new WP_Error( 'import_file_error', sprintf( esc_html__( 'Remote file is too large, limit is %s', 'js_composer' ), 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 = false;
$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 ) {
// @codingStandardsIgnoreLine
$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
// @codingStandardsIgnoreLine
$wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->posts} SET post_content = REPLACE(post_content, %s, %s)", $from_url, $to_url ) );
// remap enclosure urls
// @codingStandardsIgnoreLine
$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',
), true ) ) {
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
* @param string $a
* @param string $b
* @return int
*/
public function cmpr_strlen( $a, $b ) {
return strlen( $b ) - strlen( $a );
}
}
}

View File

@@ -0,0 +1,210 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Class Vc_WXR_Parser_Plugin
*/
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 );
}
}
/**
* @param $attachments
* @param $content
* @return mixed
*/
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;
}
/**
* @param $attachments
* @param $content
* @param $url
* @param $vals
* @return mixed
*/
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;
}
/**
* @param $shortcode
* @param $attributes
* @param $newQuery
* @param $attachments
* @return bool|mixed
*/
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;
}
/**
* @param $attributeValue
* @param $key
* @param $data
*/
public function attributesWalker( &$attributeValue, $key, $data ) {
$intValue = intval( $attributeValue );
if ( array_key_exists( $intValue, $data['attachments'] ) ) {
$attributeValue = $data['attachments'][ $intValue ];
}
}
/**
* @param $content
* @return array
*/
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;
}
}

View File

@@ -0,0 +1,375 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* WXR Parser that uses regular expressions. Fallback for installs without an XML parser.
*/
class Vc_WXR_Parser_Regex {
/**
* @var array
*/
public $authors = array();
/**
* @var array
*/
public $posts = array();
/**
* @var array
*/
public $categories = array();
/**
* @var array
*/
public $tags = array();
/**
* @var array
*/
public $terms = array();
/**
* @var string
*/
public $base_url = '';
/**
* Vc_WXR_Parser_Regex constructor.
*/
public function __construct() {
$this->has_gzip = is_callable( 'gzopen' );
}
/**
* @param $file
* @return array|\WP_Error
*/
public function parse( $file ) {
$wxr_version = false;
$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', esc_html__( 'This does not appear to be a WXR file, missing/invalid WXR version number', 'js_composer' ) );
}
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,
);
}
/**
* @param $string
* @param $tag
* @return mixed|string|string[]|null
*/
public 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;
}
/**
* @param $c
* @return array
*/
public 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' ),
);
}
/**
* @param $t
* @return array
*/
public 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' ),
);
}
/**
* @param $t
* @return array
*/
public 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' ),
);
}
/**
* @param $a
* @return array
*/
public 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' ),
);
}
/**
* @param $post
* @return array
*/
public 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;
}
/**
* @param $matches
* @return string
*/
public function normalize_tag( $matches ) {
return '<' . strtolower( $matches[1] );
}
/**
* @param $filename
* @param string $mode
* @return bool|resource
*/
public function fopen( $filename, $mode = 'r' ) {
if ( $this->has_gzip ) {
return gzopen( $filename, $mode );
}
// @codingStandardsIgnoreLine
return fopen( $filename, $mode );
}
/**
* @param $fp
* @return bool|int
*/
public function feof( $fp ) {
if ( $this->has_gzip ) {
return gzeof( $fp );
}
// @codingStandardsIgnoreLine
return feof( $fp );
}
/**
* @param $fp
* @param int $len
* @return bool|string
*/
public function fgets( $fp, $len = 8192 ) {
if ( $this->has_gzip ) {
return gzgets( $fp, $len );
}
// @codingStandardsIgnoreLine
return fgets( $fp, $len );
}
/**
* @param $fp
* @return bool
*/
public function fclose( $fp ) {
if ( $this->has_gzip ) {
return gzclose( $fp );
}
// @codingStandardsIgnoreLine
return fclose( $fp );
}
}

View File

@@ -0,0 +1,240 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* WXR Parser that makes use of the SimpleXML PHP extension.
*/
class Vc_WXR_Parser_SimpleXML {
/**
* @param $file
* @return array|\WP_Error
*/
public function parse( $file ) {
$authors = array();
$posts = array();
$categories = array();
$tags = array();
$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 );
}
/** @var \WP_Filesystem_Direct $wp_filesystem */
global $wp_filesystem;
if ( empty( $wp_filesystem ) ) {
require_once ABSPATH . '/wp-admin/includes/file.php';
WP_Filesystem( false, false, true );
}
$success = $dom->loadXML( $wp_filesystem->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', esc_html__( 'There was an error when reading this WXR file', 'js_composer' ), 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', esc_html__( 'There was an error when reading this WXR file', 'js_composer' ), libxml_get_errors() );
}
$wxr_version = $xml->xpath( '/rss/channel/wp:wxr_version' );
if ( ! $wxr_version ) {
return new WP_Error( 'WXR_parse_error', esc_html__( 'This does not appear to be a WXR file, missing/invalid WXR version number', 'js_composer' ) );
}
$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', esc_html__( 'This does not appear to be a WXR file, missing/invalid WXR version number', 'js_composer' ) );
}
$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,
);
}
}

View File

@@ -0,0 +1,269 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* WXR Parser that makes use of the XML Parser PHP extension.
*/
class Vc_WXR_Parser_XML {
/**
* @var array
*/
public $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 array
*/
public $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',
);
/**
* @param $file
* @return array|\WP_Error
*/
public function parse( $file ) {
$this->wxr_version = false;
$this->in_post = false;
$this->cdata = false;
$this->data = false;
$this->sub_data = false;
$this->in_tag = false;
$this->in_sub_tag = false;
$this->authors = array();
$this->posts = array();
$this->term = array();
$this->category = array();
$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' );
/** @var \WP_Filesystem_Direct $wp_filesystem */ global $wp_filesystem;
if ( empty( $wp_filesystem ) ) {
require_once ABSPATH . '/wp-admin/includes/file.php';
WP_Filesystem( false, false, true );
}
if ( ! xml_parse( $xml, $wp_filesystem->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', esc_html__( 'This does not appear to be a WXR file, missing/invalid WXR version number', 'js_composer' ) );
}
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,
);
}
/**
* @param $parse
* @param $tag
* @param $attr
*/
public function tag_open( $parse, $tag, $attr ) {
if ( in_array( $tag, $this->wp_tags, true ) ) {
$this->in_tag = substr( $tag, 3 );
return;
}
if ( in_array( $tag, $this->wp_sub_tags, true ) ) {
$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;
if ( $this->in_post ) {
$this->in_tag = 'post_title';
}
break;
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;
}
}
/**
* @param $parser
* @param $cdata
*/
public 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 );
}
}
/**
* @param $parser
* @param $tag
*/
public 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;
} elseif ( $this->in_tag ) {
$this->data[ $this->in_tag ] = ! empty( $this->cdata ) ? $this->cdata : '';
$this->in_tag = false;
}
}
$this->cdata = false;
}
}

View File

@@ -0,0 +1,65 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
require_once dirname( __FILE__ ) . '/class-vc-wxr-parser-regex.php';
require_once dirname( __FILE__ ) . '/class-vc-wxr-parser-simplexml.php';
require_once dirname( __FILE__ ) . '/class-vc-wxr-parser-xml.php';
/**
* WordPress eXtended RSS file parser implementations
*
* @package WordPress
* @subpackage Importer
*/
/**
* WordPress Importer class for managing parsing of WXR files.
*/
class Vc_WXR_Parser {
/**
* @param $file
* @return array|\WP_Error
*/
public 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;
}
} elseif ( 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 esc_html( $error->line . ':' . $error->column ) . ' ' . esc_html( $error->message ) . "\n";
}
} elseif ( 'XML_parse_error' === $result->get_error_code() ) {
$error = $result->get_error_data();
echo esc_html( $error[0] . ':' . $error[1] ) . ' ' . esc_html( $error[2] );
}
echo '</pre>';
echo '<p><strong>' . esc_html__( 'There was an error when reading this WXR file', 'js_composer' ) . '</strong><br />';
echo esc_html__( 'Details are shown above. The importer will now try again with a different parser...', 'js_composer' ) . '</p>';
}
// use regular expressions if nothing else available or this is bad XML
$parser = new Vc_WXR_Parser_Regex();
return $parser->parse( $file );
}
}

View File

@@ -0,0 +1,94 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Helper function to register new shortcode attribute hook.
*
* @param $name - attribute name
* @param $form_field_callback - hook, will be called when settings form is shown and attribute added to shortcode
* param list
* @param $script_url - javascript file url which will be attached at the end of settings form.
*
* @return bool
* @deprecated due to without prefix name 4.4
* @since 4.2
*/
function add_shortcode_param( $name, $form_field_callback, $script_url = null ) {
_deprecated_function( 'add_shortcode_param', '4.4 (will be removed in 6.0)', 'vc_add_shortcode_param' );
return vc_add_shortcode_param( $name, $form_field_callback, $script_url );
}
/**
* @return mixed|string
* @since 4.2
* @deprecated 4.2
*/
function get_row_css_class() {
_deprecated_function( 'get_row_css_class', '4.2 (will be removed in 6.0)' );
$custom = vc_settings()->get( 'row_css_class' );
return ! empty( $custom ) ? $custom : 'vc_row-fluid';
}
/**
* @return string
* @deprecated 5.2
*/
function vc_generate_dependencies_attributes() {
_deprecated_function( 'vc_generate_dependencies_attributes', '5.1', '' );
return '';
}
/**
* Extract width/height from string
*
* @param string $dimensions WxH
* @return mixed array(width, height) or false
* @since 4.7
*
* @deprecated since 5.8
*/
function vcExtractDimensions( $dimensions ) {
_deprecated_function( 'vcExtractDimensions', '5.8', 'vc_extract_dimensions' );
return vc_extract_dimensions( $dimensions );
}
/**
* @param array $images IDs or srcs of images
* @return string
* @since 4.2
* @deprecated since 2019, 5.8
*/
function fieldAttachedImages( $images = array() ) {
_deprecated_function( 'fieldAttachedImages', '5.8', 'vc_field_attached_images' );
return vc_field_attached_images( $images );
}
/**
* @param string $asset
*
* @return array|string
* @deprecated
*/
function getVcShared( $asset = '' ) {
return vc_get_shared( $asset );
}
/**
* Return a action param for ajax
* @return bool
* @since 4.8
* @deprecated 6.1
*/
function vc_wp_action() {
_deprecated_function( 'vc_wp_action', '6.1', 'vc_request_param' );
return vc_request_param( 'action' );
}

View File

@@ -0,0 +1,46 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* @since 4.3
* @deprecated since 5.8
* Interface for editors
*/
interface Vc_Editor_Interface {
/**
* @return mixed
* @deprecated 5.8
* @since 4.3
*/
public function renderEditor();
}
/**
* @since 4.3
* @deprecated 5.8
* Default render interface
*/
interface Vc_Render {
/**
* @return mixed
* @deprecated 5.8
* @since 4.3
*/
public function render();
}
/**
* @since 4.3
* @deprecated 5.8
* Interface for third-party plugins classes loader.
*/
interface Vc_Vendor_Interface {
/**
* @return mixed
* @deprecated 5.8
* @since 4.3
*/
public function load();
}

View File

@@ -0,0 +1,304 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* WPBakery WPBakery Page Builder admin editor
*
* @package WPBakeryPageBuilder
*
*/
/**
* VC backend editor.
*
* This editor is available on default Wp post/page admin edit page. ON admin_init callback adds meta box to
* edit page.
*
* @since 4.2
*/
class Vc_Backend_Editor {
/**
* @var
*/
protected $layout;
/**
* @var
*/
public $post_custom_css;
/**
* @var bool|string $post - stores data about post.
*/
public $post = false;
/**
* This method is called by Vc_Manager to register required action hooks for VC backend editor.
*
* @since 4.2
* @access public
*/
public function addHooksSettings() {
// @todo - fix_roles do this only if be editor is enabled.
// load backend editor
if ( function_exists( 'add_theme_support' ) ) {
add_theme_support( 'post-thumbnails' ); // @todo check is it needed?
}
add_action( 'add_meta_boxes', array(
$this,
'render',
), 5 );
add_action( 'admin_print_scripts-post.php', array(
$this,
'registerScripts',
) );
add_action( 'admin_print_scripts-post-new.php', array(
$this,
'registerScripts',
) );
add_action( 'admin_print_scripts-post.php', array(
$this,
'printScriptsMessages',
) );
add_action( 'admin_print_scripts-post-new.php', array(
$this,
'printScriptsMessages',
) );
}
public function registerScripts() {
$this->registerBackendJavascript();
$this->registerBackendCss();
// B.C:
visual_composer()->registerAdminCss();
visual_composer()->registerAdminJavascript();
}
/**
* Calls add_meta_box to create Editor block. Block is rendered by WPBakeryVisualComposerLayout.
*
* @param $post_type
* @throws \Exception
* @since 4.2
* @access public
*
* @see WPBakeryVisualComposerLayout
*/
public function render( $post_type ) {
if ( $this->isValidPostType( $post_type ) ) {
// meta box to render
add_meta_box( 'wpb_visual_composer', esc_html__( 'WPBakery Page Builder', 'js_composer' ), array(
$this,
'renderEditor',
), $post_type, 'normal', 'high' );
}
}
/**
* Output html for backend editor meta box.
*
* @param null|Wp_Post $post
*
* @return bool
*/
public function renderEditor( $post = null ) {
/**
* TODO: setter/getter for $post
*/
if ( ! is_object( $post ) || 'WP_Post' !== get_class( $post ) || ! isset( $post->ID ) ) {
return false;
}
$this->post = $post;
$post_custom_css = wp_strip_all_tags( get_post_meta( $post->ID, '_wpb_post_custom_css', true ) );
$this->post_custom_css = $post_custom_css;
vc_include_template( 'editors/backend_editor.tpl.php', array(
'editor' => $this,
'post' => $this->post,
) );
add_action( 'admin_footer', array(
$this,
'renderEditorFooter',
) );
do_action( 'vc_backend_editor_render' );
return true;
}
/**
* Output required html and js content for VC editor.
*
* Here comes panels, modals and js objects with data for mapped shortcodes.
*/
public function renderEditorFooter() {
vc_include_template( 'editors/partials/backend_editor_footer.tpl.php', array(
'editor' => $this,
'post' => $this->post,
) );
do_action( 'vc_backend_editor_footer_render' );
}
/**
* Check is post type is valid for rendering VC backend editor.
*
* @param string $type
*
* @return bool
* @throws \Exception
*/
public function isValidPostType( $type = '' ) {
$type = ! empty( $type ) ? $type : get_post_type();
if ( 'vc_grid_item' === $type ) {
return false;
}
return apply_filters( 'vc_is_valid_post_type_be', vc_check_post_type( $type ), $type );
}
/**
* Enqueue required javascript libraries and css files.
*
* This method also setups reminder about license activation.
*
* @since 4.2
* @access public
*/
public function printScriptsMessages() {
if ( ! vc_is_frontend_editor() && $this->isValidPostType( get_post_type() ) ) {
$this->enqueueEditorScripts();
}
}
/**
* Enqueue required javascript libraries and css files.
*
* @since 4.8
* @access public
*/
public function enqueueEditorScripts() {
if ( $this->editorEnabled() ) {
$this->enqueueJs();
$this->enqueueCss();
WPBakeryShortCodeFishBones::enqueueCss();
WPBakeryShortCodeFishBones::enqueueJs();
} else {
wp_enqueue_script( 'vc-backend-actions-js' );
$this->enqueueCss(); // needed for navbar @todo split
}
do_action( 'vc_backend_editor_enqueue_js_css' );
}
public function registerBackendJavascript() {
// editor can be disabled but fe can be enabled. so we currently need this file. @todo maybe make backend-disabled.min.js
wp_register_script( 'vc-backend-actions-js', vc_asset_url( 'js/dist/backend-actions.min.js' ), array(
'jquery',
'backbone',
'underscore',
), WPB_VC_VERSION, true );
wp_register_script( 'vc-backend-min-js', vc_asset_url( 'js/dist/backend.min.js' ), array( 'vc-backend-actions-js' ), WPB_VC_VERSION, true );
// used in tta shortcodes, and panels.
wp_register_script( 'vc_accordion_script', vc_asset_url( 'lib/vc_accordion/vc-accordion.min.js' ), array( 'jquery' ), WPB_VC_VERSION, true );
wp_register_script( 'wpb_php_js', vc_asset_url( 'lib/php.default/php.default.min.js' ), array( 'jquery' ), WPB_VC_VERSION, true );
// used as polyfill for JSON.stringify and etc
wp_register_script( 'wpb_json-js', vc_asset_url( 'lib/bower/json-js/json2.min.js' ), array(), WPB_VC_VERSION, true );
// used in post settings editor
wp_register_script( 'ace-editor', vc_asset_url( 'lib/bower/ace-builds/src-min-noconflict/ace.js' ), array( 'jquery' ), WPB_VC_VERSION, true );
wp_register_script( 'webfont', 'https://ajax.googleapis.com/ajax/libs/webfont/1.6.26/webfont.js', array(), WPB_VC_VERSION, true ); // Google Web Font CDN
wp_localize_script( 'vc-backend-actions-js', 'i18nLocale', visual_composer()->getEditorsLocale() );
}
public function registerBackendCss() {
wp_register_style( 'js_composer', vc_asset_url( 'css/js_composer_backend_editor.min.css' ), array(), WPB_VC_VERSION, false );
if ( $this->editorEnabled() ) {
/**
* @deprecated, used for accordions/tabs/tours
*/
wp_register_style( 'ui-custom-theme', vc_asset_url( 'css/ui-custom-theme/jquery-ui-less.custom.min.css' ), array(), WPB_VC_VERSION );
/**
* @todo check vc_add-element-deprecated-warning for fa icon usage ( set to our font )
* also used in vc_icon shortcode
*/
wp_register_style( 'vc_font_awesome_5_shims', vc_asset_url( 'lib/bower/font-awesome/css/v4-shims.min.css' ), array(), WPB_VC_VERSION );
wp_register_style( 'vc_font_awesome_5', vc_asset_url( 'lib/bower/font-awesome/css/all.min.css' ), array( 'vc_font_awesome_5_shims' ), WPB_VC_VERSION );
/**
* @todo check for usages
* definetelly used in edit form param: css_animation, but curreny vc_add_shortcode_param doesn't accept css [ @todo refactor that ]
*/
wp_register_style( 'vc_animate-css', vc_asset_url( 'lib/bower/animate-css/animate.min.css' ), array(), WPB_VC_VERSION );
}
}
public function enqueueJs() {
$wp_dependencies = array(
'jquery',
'underscore',
'backbone',
'media-views',
'media-editor',
'wp-pointer',
'mce-view',
'wp-color-picker',
'jquery-ui-sortable',
'jquery-ui-droppable',
'jquery-ui-draggable',
'jquery-ui-autocomplete',
'jquery-ui-resizable',
// used in @deprecated tabs
'jquery-ui-tabs',
'jquery-ui-accordion',
);
$dependencies = array(
'vc_accordion_script',
'wpb_php_js',
// used in our files [e.g. edit form saving sprintf]
'wpb_json-js',
'ace-editor',
'webfont',
'vc-backend-min-js',
);
// This workaround will allow to disable any of dependency on-the-fly
foreach ( $wp_dependencies as $dependency ) {
wp_enqueue_script( $dependency );
}
foreach ( $dependencies as $dependency ) {
wp_enqueue_script( $dependency );
}
}
public function enqueueCss() {
$wp_dependencies = array(
'wp-color-picker',
'farbtastic',
// deprecated for tabs/accordion
'ui-custom-theme',
// used in deprecated message and also in vc-icon shortcode
'vc_font_awesome_5',
// used in css_animation edit form param
'vc_animate-css',
);
$dependencies = array(
'js_composer',
);
// This workaround will allow to disable any of dependency on-the-fly
foreach ( $wp_dependencies as $dependency ) {
wp_enqueue_style( $dependency );
}
foreach ( $dependencies as $dependency ) {
wp_enqueue_style( $dependency );
}
}
/**
* @return bool
* @throws \Exception
*/
public function editorEnabled() {
return vc_user_access()->part( 'backend_editor' )->can()->get();
}
}

View File

@@ -0,0 +1,315 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* WPBakery WPBakery Page Builder shortcode attributes fields
*
* @package WPBakeryPageBuilder
*
*/
/**
* Edit form fields builder for shortcode attributes.
*
* @since 4.4
*/
class Vc_Edit_Form_Fields {
/**
* @since 4.4
* @var bool
*/
protected $tag = false;
/**
* @since 4.4
* @var array
*/
protected $atts = array();
/**
* @since 4.4
* @var array
*/
protected $settings = array();
/**
* @since 4.4
* @var bool
*/
protected $post_id = false;
/**
* Construct Form fields.
*
* @param $tag - shortcode tag
* @param $atts - list of attribute assign to the shortcode.
* @throws \Exception
* @since 4.4
*/
public function __construct( $tag, $atts ) {
$this->tag = $tag;
$this->atts = apply_filters( 'vc_edit_form_fields_attributes_' . $this->tag, $atts );
$this->setSettings( WPBMap::getShortCode( $this->tag ) );
}
/**
* Get settings
* @param $key
*
* @return null
* @since 4.4
*
*/
public function setting( $key ) {
return isset( $this->settings[ $key ] ) ? $this->settings[ $key ] : null;
}
/**
* Set settings data
* @param array $settings
* @since 4.4
*
*/
public function setSettings( array $settings ) {
$this->settings = $settings;
}
/**
* Shortcode Post ID getter.
* If post id isn't set try to get from get_the_ID function.
* @return int|bool;
* @since 4.4
*/
public function postId() {
if ( ! $this->post_id ) {
$this->post_id = get_the_ID();
}
return $this->post_id;
}
/**
* Shortcode Post ID setter.
* @param $post_id - integer value in post_id
* @since 4.4
*
*/
public function setPostId( $post_id ) {
$this->post_id = (int) $post_id;
}
/**
* Get shortcode attribute value.
*
* This function checks if value isn't set then it uses std or value fields in param settings.
* @param $param_settings
* @param $value
*
* @return null
* @since 4.4
*
*/
protected function parseShortcodeAttributeValue( $param_settings, $value ) {
if ( is_null( $value ) ) { // If value doesn't exists
if ( isset( $param_settings['std'] ) ) {
$value = $param_settings['std'];
} elseif ( isset( $param_settings['value'] ) && is_array( $param_settings['value'] ) && ! empty( $param_settings['type'] ) && 'checkbox' !== $param_settings['type'] ) {
$first_key = key( $param_settings['value'] );
$value = $first_key ? $param_settings['value'][ $first_key ] : '';
} elseif ( isset( $param_settings['value'] ) && ! is_array( $param_settings['value'] ) ) {
$value = $param_settings['value'];
}
}
return $value;
}
/**
* Enqueue js scripts for attributes types.
* @return string
* @since 4.4
*/
public function enqueueScripts() {
$output = '';
$scripts = apply_filters( 'vc_edit_form_enqueue_script', WpbakeryShortcodeParams::getScripts() );
if ( is_array( $scripts ) ) {
foreach ( $scripts as $script ) {
$custom_tag = 'script';
// @todo Check posibility to use wp_add_inline_script
// @codingStandardsIgnoreLine
$output .= '<' . $custom_tag . ' src="' . esc_url( $script ) . '"></' . $custom_tag . '>';
}
}
return $output;
}
/**
* Render grouped fields.
* @param $groups
* @param $groups_content
*
* @return string
* @since 4.4
*
*/
protected function renderGroupedFields( $groups, $groups_content ) {
$output = '';
if ( count( $groups ) > 1 || ( count( $groups ) >= 1 && empty( $groups_content['_general'] ) ) ) {
$output .= '<div class="vc_panel-tabs" id="vc_edit-form-tabs">';
$output .= '<ul class="vc_general vc_ui-tabs-line" data-vc-ui-element="panel-tabs-controls">';
$key = 0;
foreach ( $groups as $g ) {
$output .= '<li class="vc_edit-form-tab-control" data-tab-index="' . esc_attr( $key ) . '"><button data-vc-ui-element-target="#vc_edit-form-tab-' . ( $key ++ ) . '" class="vc_ui-tabs-line-trigger" data-vc-ui-element="panel-tab-control">' . ( '_general' === $g ? esc_html__( 'General', 'js_composer' ) : $g ) . '</button></li>';
}
$output .= '<li class="vc_ui-tabs-line-dropdown-toggle" data-vc-action="dropdown"
data-vc-content=".vc_ui-tabs-line-dropdown" data-vc-ui-element="panel-tabs-line-toggle">
<span class="vc_ui-tabs-line-trigger" data-vc-accordion
data-vc-container=".vc_ui-tabs-line-dropdown-toggle"
data-vc-target=".vc_ui-tabs-line-dropdown"> </span>
<ul class="vc_ui-tabs-line-dropdown" data-vc-ui-element="panel-tabs-line-dropdown">
</ul>
</ul>';
$key = 0;
foreach ( $groups as $g ) {
$output .= '<div id="vc_edit-form-tab-' . ( $key ++ ) . '" class="vc_edit-form-tab vc_row vc_ui-flex-row" data-vc-ui-element="panel-edit-element-tab">';
$output .= $groups_content[ $g ];
$output .= '</div>';
}
$output .= '</div>';
} elseif ( ! empty( $groups_content['_general'] ) ) {
$output .= '<div class="vc_edit-form-tab vc_row vc_ui-flex-row vc_active" data-vc-ui-element="panel-edit-element-tab">' . $groups_content['_general'] . '</div>';
}
return $output;
}
/**
* Render fields html and output it.
* @since 4.4
* vc_filter: vc_edit_form_class - filter to override editor_css_classes array
*/
public function render() {
$this->loadDefaultParams();
$output = $el_position = '';
$groups_content = $groups = array();
$params = $this->setting( 'params' );
$editor_css_classes = apply_filters( 'vc_edit_form_class', array(
'wpb_edit_form_elements',
'vc_edit_form_elements',
), $this->atts, $params );
$deprecated = $this->setting( 'deprecated' );
require_once vc_path_dir( 'AUTOLOAD_DIR', 'class-vc-settings-presets.php' );
// TODO: check presets 6.0
// $list_vendor_presets = Vc_Settings_Preset::listVendorSettingsPresets( $this->tag );
// $list_presets = Vc_Settings_Preset::listSettingsPresets( $this->tag );
$show_settings = false;
$saveAsTemplateElements = apply_filters( 'vc_popup_save_as_template_elements', array(
'vc_row',
'vc_section',
) );
$show_presets = ! in_array( $this->tag, $saveAsTemplateElements, true ) && vc_user_access()->part( 'presets' )->checkStateAny( true, null )->get();
if ( in_array( $this->tag, $saveAsTemplateElements, true ) && vc_user_access()->part( 'templates' )->checkStateAny( true, null )->get() ) {
$show_settings = true;
}
$custom_tag = 'script';
$output .= sprintf( '<' . $custom_tag . '>window.vc_presets_show=%s;</' . $custom_tag . '>', $show_presets ? 'true' : 'false' );
$output .= sprintf( '<' . $custom_tag . '>window.vc_settings_show=%s;</' . $custom_tag . '>', $show_presets || $show_settings ? 'true' : 'false' );
if ( ! empty( $deprecated ) ) {
$output .= '<div class="vc_row vc_ui-flex-row vc_shortcode-edit-form-deprecated-message"><div class="vc_col-sm-12 wpb_element_wrapper">' . vc_message_warning( sprintf( esc_html__( 'You are using outdated element, it is deprecated since version %s.', 'js_composer' ), $this->setting( 'deprecated' ) ) ) . '</div></div>';
}
$output .= '<div class="' . implode( ' ', $editor_css_classes ) . '" data-title="' . esc_attr__( 'Edit', 'js_composer' ) . ' ' . esc_attr( $this->setting( 'name' ) ) . '">';
if ( is_array( $params ) ) {
foreach ( $params as $param ) {
$name = isset( $param['param_name'] ) ? $param['param_name'] : null;
if ( ! is_null( $name ) ) {
$value = isset( $this->atts[ $name ] ) ? $this->atts[ $name ] : null;
$value = $this->parseShortcodeAttributeValue( $param, $value );
$group = isset( $param['group'] ) && '' !== $param['group'] ? $param['group'] : '_general';
if ( ! isset( $groups_content[ $group ] ) ) {
$groups[] = $group;
$groups_content[ $group ] = '';
}
$groups_content[ $group ] .= $this->renderField( $param, $value );
}
}
}
$output .= $this->renderGroupedFields( $groups, $groups_content );
$output .= '</div>';
$output .= $this->enqueueScripts();
// @codingStandardsIgnoreLine
echo $output;
do_action( 'vc_edit_form_fields_after_render' );
}
/**
* Generate html for shortcode attribute.
*
* Method
* @param $param
* @param $value
*
* vc_filter: vc_single_param_edit - hook to edit any shortode param
* vc_filter: vc_form_fields_render_field_{shortcode_name}_{param_name}_param_value - hook to edit shortcode param
* value vc_filter: vc_form_fields_render_field_{shortcode_name}_{param_name}_param - hook to edit shortcode
* param attributes vc_filter: vc_single_param_edit_holder_output - hook to edit output of this method
*
* @return mixed
* @since 4.4
*
*/
public function renderField( $param, $value ) {
$param['vc_single_param_edit_holder_class'] = array(
'wpb_el_type_' . $param['type'],
'vc_wrapper-param-type-' . $param['type'],
'vc_shortcode-param',
'vc_column',
);
if ( ! empty( $param['param_holder_class'] ) ) {
$param['vc_single_param_edit_holder_class'][] = $param['param_holder_class'];
}
$param = apply_filters( 'vc_single_param_edit', $param, $value );
$output = '<div class="' . implode( ' ', $param['vc_single_param_edit_holder_class'] ) . '" data-vc-ui-element="panel-shortcode-param" data-vc-shortcode-param-name="' . esc_attr( $param['param_name'] ) . '" data-param_type="' . esc_attr( $param['type'] ) . '" data-param_settings="' . esc_attr( htmlentities( wp_json_encode( $param ) ) ) . '">';
$output .= ( isset( $param['heading'] ) ) ? '<div class="wpb_element_label">' . $param['heading'] . '</div>' : '';
$output .= '<div class="edit_form_line">';
$value = apply_filters( 'vc_form_fields_render_field_' . $this->setting( 'base' ) . '_' . $param['param_name'] . '_param_value', $value, $param, $this->settings, $this->atts );
$param = apply_filters( 'vc_form_fields_render_field_' . $this->setting( 'base' ) . '_' . $param['param_name'] . '_param', $param, $value, $this->settings, $this->atts );
$output = apply_filters( 'vc_edit_form_fields_render_field_' . $param['type'] . '_before', $output );
$output .= vc_do_shortcode_param_settings_field( $param['type'], $param, $value, $this->setting( 'base' ) );
$output_after = '';
if ( isset( $param['description'] ) ) {
$output_after .= '<span class="vc_description vc_clearfix">' . $param['description'] . '</span>';
}
$output_after .= '</div></div>';
$output .= apply_filters( 'vc_edit_form_fields_render_field_' . $param['type'] . '_after', $output_after );
return apply_filters( 'vc_single_param_edit_holder_output', $output, $param, $value, $this->settings, $this->atts );
}
/**
* Create default shortcode params
*
* List of params stored in global variable $vc_params_list.
* Please check include/params/load.php for default params list.
* @return bool
* @since 4.4
*/
public function loadDefaultParams() {
global $vc_params_list;
if ( empty( $vc_params_list ) ) {
return false;
}
$script_url = vc_asset_url( 'js/dist/edit-form.min.js' );
foreach ( $vc_params_list as $param ) {
vc_add_shortcode_param( $param, 'vc_' . $param . '_form_field', $script_url );
}
do_action( 'vc_load_default_params' );
return true;
}
}

View File

@@ -0,0 +1,148 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
require_once vc_path_dir( 'EDITORS_DIR', 'navbar/class-vc-navbar.php' );
/**
*
*/
class Vc_Navbar_Frontend extends Vc_Navbar {
/**
* @var array
*/
protected $controls = array(
'add_element',
'templates',
'view_post',
'save_update',
'screen_size',
'custom_css',
);
/**
* @var string
*/
protected $controls_filter_name = 'vc_nav_front_controls';
/**
* @var string
*/
protected $brand_url = 'https://wpbakery.com/?utm_campaign=VCplugin&utm_source=vc_user&utm_medium=frontend_editor';
/**
* @var string
*/
protected $css_class = 'vc_navbar vc_navbar-frontend';
/**
* @return string
*/
public function getControlScreenSize() {
$disable_responsive = vc_settings()->get( 'not_responsive_css' );
if ( '1' !== $disable_responsive ) {
$screen_sizes = array(
array(
'title' => esc_html__( 'Desktop', 'js_composer' ),
'size' => '100%',
'key' => 'default',
'active' => true,
),
array(
'title' => esc_html__( 'Tablet landscape mode', 'js_composer' ),
'size' => '1024px',
'key' => 'landscape-tablets',
),
array(
'title' => esc_html__( 'Tablet portrait mode', 'js_composer' ),
'size' => '768px',
'key' => 'portrait-tablets',
),
array(
'title' => esc_html__( 'Smartphone landscape mode', 'js_composer' ),
'size' => '480px',
'key' => 'landscape-smartphones',
),
array(
'title' => esc_html__( 'Smartphone portrait mode', 'js_composer' ),
'size' => '320px',
'key' => 'portrait-smartphones',
),
);
$output = '<li class="vc_pull-right">' . '<div class="vc_dropdown" id="vc_screen-size-control">' . '<a href="#" class="vc_dropdown-toggle"' . ' title="' . esc_attr__( 'Responsive preview', 'js_composer' ) . '"><i class="vc-composer-icon vc_current-layout-icon vc-c-icon-layout_default"' . ' id="vc_screen-size-current"></i><i class="vc-composer-icon vc-c-icon-arrow_drop_down"></i></a>' . '<ul class="vc_dropdown-list">';
$screen = current( $screen_sizes );
while ( $screen ) {
$output .= '<li><a href="#" title="' . esc_attr( $screen['title'] ) . '"' . ' class="vc_screen-width vc-composer-icon vc-c-icon-layout_' . esc_attr( $screen['key'] ) . ( isset( $screen['active'] ) && $screen['active'] ? ' active' : '' ) . '" data-size="' . esc_attr( $screen['size'] ) . '"></a></li>';
next( $screen_sizes );
$screen = current( $screen_sizes );
}
$output .= '</ul></div></li>';
return $output;
}
return '';
}
/**
* @return string
* @throws \Exception
*/
public function getControlSaveUpdate() {
$post = $this->post();
$post_type = get_post_type_object( $this->post->post_type );
$can_publish = current_user_can( $post_type->cap->publish_posts );
ob_start();
?>
<li class="vc_show-mobile vc_pull-right">
<button data-url="<?php echo esc_attr( get_edit_post_link( $post->ID ) . '&wpb_vc_js_status=true&classic-editor' ); ?>"
class="vc_btn vc_btn-default vc_btn-sm vc_navbar-btn vc_btn-backend-editor" id="vc_button-cancel"
title="<?php esc_attr_e( 'Cancel all changes and return to WP dashboard', 'js_composer' ); ?>">
<?php
echo vc_user_access()->part( 'backend_editor' )->can()->get() ? esc_html__( 'Backend Editor', 'js_composer' ) : esc_html__( 'Edit', 'js_composer' );
?>
</button>
<?php
if ( ! in_array( $post->post_status, array(
'publish',
'future',
'private',
), true ) ) :
?>
<?php if ( 'draft' === $post->post_status ) : ?>
<button type="button" class="vc_btn vc_btn-default vc_btn-sm vc_navbar-btn vc_btn-save-draft"
id="vc_button-save-draft"
title="<?php esc_attr_e( 'Save Draft', 'js_composer' ); ?>"><?php esc_html_e( 'Save Draft', 'js_composer' ); ?></button>
<?php elseif ( 'pending' === $post->post_status && $can_publish ) : ?>
<button type="button" class="vc_btn vc_btn-primary vc_btn-sm vc_navbar-btn vc_btn-save"
id="vc_button-save-as-pending"
title="<?php esc_attr_e( 'Save as Pending', 'js_composer' ); ?>"><?php esc_html_e( 'Save as Pending', 'js_composer' ); ?></button>
<?php endif ?>
<?php if ( $can_publish ) : ?>
<button type="button" class="vc_btn vc_btn-primary vc_btn-sm vc_navbar-btn vc_btn-save"
id="vc_button-update" title="<?php esc_attr_e( 'Publish', 'js_composer' ); ?>"
data-change-status="publish"><?php esc_html_e( 'Publish', 'js_composer' ); ?></button>
<?php else : ?>
<button type="button" class="vc_btn vc_btn-primary vc_btn-sm vc_navbar-btn vc_btn-save"
id="vc_button-update" title="<?php esc_attr_e( 'Submit for Review', 'js_composer' ); ?>"
data-change-status="pending"><?php esc_html_e( 'Submit for Review', 'js_composer' ); ?></button>
<?php endif ?>
<?php else : ?>
<button type="button" class="vc_btn vc_btn-primary vc_btn-sm vc_navbar-btn vc_btn-save"
id="vc_button-update"
title="<?php esc_attr_e( 'Update', 'js_composer' ); ?>"><?php esc_html_e( 'Update', 'js_composer' ); ?></button>
<?php endif ?>
</li>
<?php
$output = ob_get_contents();
ob_end_clean();
return $output;
}
/**
* @return string
*/
public function getControlViewPost() {
return '<li class="vc_pull-right">' . '<a href="' . esc_url( get_permalink( $this->post() ) ) . '" class="vc_icon-btn vc_back-button"' . ' title="' . esc_attr__( 'Exit WPBakery Page Builder edit mode', 'js_composer' ) . '"><i class="vc-composer-icon vc-c-icon-close"></i></a>' . '</li>';
}
}

View File

@@ -0,0 +1,40 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Class Vc_Navbar_Undoredo
*/
class Vc_Navbar_Undoredo {
public function __construct() {
// Backend
add_filter( 'vc_nav_controls', array(
$this,
'addControls',
) );
// Frontend
add_filter( 'vc_nav_front_controls', array(
$this,
'addControls',
) );
}
/**
* @param $controls
* @return array
*/
public function addControls( $controls ) {
$controls[] = array(
'redo',
'<li class="vc_pull-right"><a id="vc_navbar-redo" href="javascript:;" class="vc_icon-btn" disabled title="' . esc_attr__( 'Redo', 'js_composer' ) . '"><i class="vc_navbar-icon fa fa-repeat"></i></a></li>',
);
$controls[] = array(
'undo',
'<li class="vc_pull-right"><a id="vc_navbar-undo" href="javascript:;" class="vc_icon-btn" disabled title="' . esc_attr__( 'Undo', 'js_composer' ) . '"><i class="vc_navbar-icon fa fa-undo"></i></a></li>',
);
return $controls;
}
}

View File

@@ -0,0 +1,179 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Renders navigation bar for Editors.
*/
class Vc_Navbar {
/**
* @var array
*/
protected $controls = array(
'add_element',
'templates',
'save_backend',
'preview',
'frontend',
'custom_css',
'fullscreen',
'windowed',
);
/**
* @var string
*/
protected $brand_url = 'https://wpbakery.com/?utm_campaign=VCplugin&utm_source=vc_user&utm_medium=backend_editor';
/**
* @var string
*/
protected $css_class = 'vc_navbar';
/**
* @var string
*/
protected $controls_filter_name = 'vc_nav_controls';
/**
* @var bool|WP_Post
*/
protected $post = false;
/**
* @param WP_Post $post
*/
public function __construct( WP_Post $post ) {
$this->post = $post;
}
/**
* Generate array of controls by iterating property $controls list.
* vc_filter: vc_nav_controls - hook to override list of controls
* @return array - list of arrays witch contains key name and html output for button.
*/
public function getControls() {
$control_list = array();
foreach ( $this->controls as $control ) {
$method = vc_camel_case( 'get_control_' . $control );
if ( method_exists( $this, $method ) ) {
$control_list[] = array(
$control,
$this->$method(),
);
}
}
return apply_filters( $this->controls_filter_name, $control_list );
}
/**
* Get current post.
* @return null|WP_Post
*/
public function post() {
if ( $this->post ) {
return $this->post;
} else {
$this->post = get_post();
}
return $this->post;
}
/**
* Render template.
*/
public function render() {
vc_include_template( 'editors/navbar/navbar.tpl.php', array(
'css_class' => $this->css_class,
'controls' => $this->getControls(),
'nav_bar' => $this,
'post' => $this->post(),
) );
}
/**
* vc_filter: vc_nav_front_logo - hook to override WPBakery Page Builder logo
* @return string
*/
public function getLogo() {
$output = '<a id="vc_logo" class="vc_navbar-brand" title="' . esc_attr__( 'WPBakery Page Builder', 'js_composer' ) . '" href="' . esc_url( $this->brand_url ) . '" target="_blank">' . esc_attr__( 'WPBakery Page Builder', 'js_composer' ) . '</a>';
return apply_filters( 'vc_nav_front_logo', $output );
}
/**
* @return string
* @throws \Exception
*/
public function getControlCustomCss() {
if ( ! vc_user_access()->part( 'post_settings' )->can()->get() ) {
return '';
}
return '<li class="vc_pull-right"><a id="vc_post-settings-button" href="javascript:;" class="vc_icon-btn vc_post-settings" title="' . esc_attr__( 'Page settings', 'js_composer' ) . '">' . '<span id="vc_post-css-badge" class="vc_badge vc_badge-custom-css" style="display: none;">' . esc_attr__( 'CSS', 'js_composer' ) . '</span><i class="vc-composer-icon vc-c-icon-cog"></i></a>' . '</li>';
}
/**
* @return string
*/
public function getControlFullscreen() {
return '<li class="vc_show-mobile vc_pull-right">' . '<a id="vc_fullscreen-button" class="vc_icon-btn vc_fullscreen-button" title="' . esc_attr__( 'Full screen', 'js_composer' ) . '"><i class="vc-composer-icon vc-c-icon-fullscreen"></i></a>' . '</li>';
}
/**
* @return string
*/
public function getControlWindowed() {
return '<li class="vc_show-mobile vc_pull-right">' . '<a id="vc_windowed-button" class="vc_icon-btn vc_windowed-button" title="' . esc_attr__( 'Exit full screen', 'js_composer' ) . '"><i class="vc-composer-icon vc-c-icon-fullscreen_exit"></i></a>' . '</li>';
}
/**
* @return string
* @throws \Exception
*/
public function getControlAddElement() {
if ( vc_user_access()->part( 'shortcodes' )->checkStateAny( true, 'custom', null )
->get() && vc_user_access_check_shortcode_all( 'vc_row' ) && vc_user_access_check_shortcode_all( 'vc_column' ) ) {
return '<li class="vc_show-mobile">' . ' <a href="javascript:;" class="vc_icon-btn vc_element-button" data-model-id="vc_element" id="vc_add-new-element" title="' . '' . esc_attr__( 'Add new element', 'js_composer' ) . '">' . ' <i class="vc-composer-icon vc-c-icon-add_element"></i>' . ' </a>' . '</li>';
}
return '';
}
/**
* @return string
* @throws \Exception
*/
public function getControlTemplates() {
if ( ! vc_user_access()->part( 'templates' )->can()->get() ) {
return '';
}
return '<li><a href="javascript:;" class="vc_icon-btn vc_templates-button" id="vc_templates-editor-button" title="' . esc_attr__( 'Templates', 'js_composer' ) . '"><i class="vc-composer-icon vc-c-icon-add_template"></i></a></li>';
}
/**
* @return string
* @throws \Exception
*/
public function getControlFrontend() {
if ( ! vc_enabled_frontend() ) {
return '';
}
return '<li class="vc_pull-right" style="display: none;">' . '<a href="' . esc_url( vc_frontend_editor()->getInlineUrl() ) . '" class="vc_btn vc_btn-primary vc_btn-sm vc_navbar-btn" id="wpb-edit-inline">' . esc_html__( 'Frontend', 'js_composer' ) . '</a>' . '</li>';
}
/**
* @return string
*/
public function getControlPreview() {
return '';
}
/**
* @return string
*/
public function getControlSaveBackend() {
return '<li class="vc_pull-right vc_save-backend">' . '<a href="javascript:;" class="vc_btn vc_btn-grey vc_btn-sm vc_navbar-btn vc_control-preview">' . esc_attr__( 'Preview', 'js_composer' ) . '</a>' . '<a class="vc_btn vc_btn-sm vc_navbar-btn vc_btn-primary vc_control-save" id="wpb-save-post">' . esc_attr__( 'Update', 'js_composer' ) . '</a>' . '</li>';
}
}

View File

@@ -0,0 +1,161 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Add element for VC editors with a list of mapped shortcodes.
*
* @since 4.3
*/
class Vc_Add_Element_Box {
/**
* Enable show empty message
*
* @since 4.8
* @var bool
*/
protected $show_empty_message = false;
/**
* @param $params
*
* @return string
*/
protected function getIcon( $params ) {
$data = '';
if ( isset( $params['is_container'] ) && true === $params['is_container'] ) {
$data = ' data-is-container="true"';
}
return '<i class="vc_general vc_element-icon' . ( ! empty( $params['icon'] ) ? ' ' . esc_attr( sanitize_text_field( $params['icon'] ) ) : '' ) . '" ' . $data . '></i> ';
}
/**
* Single button html template
*
* @param $params
*
* @return string
*/
public function renderButton( $params ) {
if ( ! is_array( $params ) || empty( $params ) ) {
return '';
}
$output = $class = $class_out = $data = $category_css_classes = '';
if ( ! empty( $params['class'] ) ) {
$class_ar = $class_at_out = explode( ' ', $params['class'] );
$count = count( $class_ar );
for ( $n = 0; $n < $count; $n ++ ) {
$class_ar[ $n ] .= '_nav';
$class_at_out[ $n ] .= '_o';
}
$class = ' ' . implode( ' ', $class_ar );
$class_out = ' ' . implode( ' ', $class_at_out );
}
if ( isset( $params['_category_ids'] ) ) {
foreach ( $params['_category_ids'] as $id ) {
$category_css_classes .= ' js-category-' . $id;
}
}
if ( isset( $params['is_container'] ) && true === $params['is_container'] ) {
$data .= ' data-is-container="true"';
}
$data .= ' data-vc-ui-element="add-element-button"';
$description = ! empty( $params['description'] ) ? '<span class="vc_element-description">' . htmlspecialchars( esc_html( $params['description'] ), ENT_QUOTES, 'UTF-8' ) . '</span>' : '';
$name = '<span data-vc-shortcode-name>' . htmlspecialchars( esc_html( stripslashes( $params['name'] ) ), ENT_QUOTES, 'UTF-8' ) . '</span>';
$output .= '<li data-element="' . esc_attr( $params['base'] ) . '" ' . ( isset( $params['presetId'] ) ? 'data-preset="' . esc_attr( $params['presetId'] ) . '"' : '' ) . ' class="wpb-layout-element-button vc_col-xs-12 vc_col-sm-4 vc_col-md-3 vc_col-lg-2' . ( isset( $params['deprecated'] ) ? ' vc_element-deprecated' : '' ) . esc_attr( $category_css_classes ) . esc_attr( $class_out ) . '" ' . $data . '><div class="vc_el-container"><a id="' . esc_attr( $params['base'] ) . '" data-tag="' . esc_attr( $params['base'] ) . '" class="dropable_el vc_shortcode-link' . esc_attr( $class ) . '" href="javascript:;" data-vc-clickable>' . $this->getIcon( $params ) . $name . $description . '</a></div></li>';
return $output;
}
/**
* Get mapped shortcodes list.
*
* @return array
* @throws \Exception
* @since 4.4
*/
public function shortcodes() {
return apply_filters( 'vc_add_new_elements_to_box', WPBMap::getSortedUserShortCodes() );
}
/**
* Render list of buttons for each mapped and allowed VC shortcodes.
* vc_filter: vc_add_element_box_buttons - hook to override output of getControls method
* @return mixed
* @throws \Exception
* @see WPBMap::getSortedUserShortCodes
*/
public function getControls() {
$output = '<ul class="wpb-content-layouts">';
/** @var array $element */
$buttons_count = 0;
$shortcodes = $this->shortcodes();
foreach ( $shortcodes as $element ) {
if ( isset( $element['content_element'] ) && false === $element['content_element'] ) {
continue;
}
$button = $this->renderButton( $element );
if ( ! empty( $button ) ) {
$buttons_count ++;
}
$output .= $button;
}
$output .= '</ul>';
if ( 0 === $buttons_count ) {
$this->show_empty_message = true;
}
return apply_filters( 'vc_add_element_box_buttons', $output );
}
/**
* Get categories list from mapping data.
* @return array
* @throws \Exception
* @since 4.5
*/
public function getCategories() {
return apply_filters( 'vc_add_new_category_filter', WPBMap::getUserCategories() );
}
/**
*
*/
public function render() {
vc_include_template( 'editors/popups/vc_ui-panel-add-element.tpl.php', array(
'box' => $this,
'template_variables' => array(
'categories' => $this->getCategories(),
),
) );
}
/**
* Render icon for shortcode
*
* @param $params
*
* @return string
* @since 4.8
*/
public function renderIcon( $params ) {
return $this->getIcon( $params );
}
/**
* @return boolean
*/
public function isShowEmptyMessage() {
return $this->show_empty_message;
}
/**
* @return mixed
* @throws \Exception
*/
public function getPartState() {
return vc_user_access()->part( 'shortcodes' )->getState();
}
}

View File

@@ -0,0 +1,18 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Edit row layout
*
* @since 4.3
*/
class Vc_Edit_Layout {
public function renderUITemplate() {
global $vc_row_layouts;
vc_include_template( 'editors/popups/vc_ui-panel-row-layout.tpl.php', array(
'vc_row_layouts' => $vc_row_layouts,
) );
}
}

View File

@@ -0,0 +1,30 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Post settings like custom css for page are displayed here.
*
* @since 4.3
*/
class Vc_Post_Settings {
protected $editor;
/**
* @param $editor
*/
public function __construct( $editor ) {
$this->editor = $editor;
}
public function editor() {
return $this->editor;
}
public function renderUITemplate() {
vc_include_template( 'editors/popups/vc_ui-panel-post-settings.tpl.php', array(
'box' => $this,
) );
}
}

View File

@@ -0,0 +1,118 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Class Vc_Preset_Panel_Editor
* @since 5.2
*/
class Vc_Preset_Panel_Editor {
/**
* @since 5.2
* @var bool
*/
protected $initialized = false;
/**
* @since 5.2
* Add ajax hooks, filters.
*/
public function init() {
if ( $this->initialized ) {
return;
}
$this->initialized = true;
}
/**
* @since 5.2
*/
public function renderUIPreset() {
vc_include_template( 'editors/popups/vc_ui-panel-preset.tpl.php', array(
'box' => $this,
) );
return '';
}
/**
* Get list of all presets for specific shortcode
*
* @return array E.g. array(id1 => title1, id2 => title2, ...)
* @since 5.2
*
*
*/
public function listPresets() {
$list = array();
$args = array(
'post_type' => 'vc_settings_preset',
'orderby' => array( 'post_date' => 'DESC' ),
'posts_per_page' => - 1,
);
$posts = get_posts( $args );
foreach ( $posts as $post ) {
$presetParentName = self::constructPresetParent( $post->post_mime_type );
$list[ $post->ID ] = array(
'title' => $post->post_title,
'parent' => $presetParentName,
);
}
return $list;
}
/**
* Single preset html
*
* @return string
* @since 5.2
*
*
*/
public function getPresets() {
$listPresets = $this->listPresets();
$output = '';
foreach ( $listPresets as $presetId => $preset ) {
$output .= '<div class="vc_ui-template">';
$output .= '<div class="vc_ui-list-bar-item">';
$output .= '<button type="button" class="vc_ui-list-bar-item-trigger" title="' . esc_attr( $preset['title'] ) . '"
data-vc-ui-element="template-title">' . esc_html( $preset['title'] ) . '</button>';
$output .= '<div class="vc_ui-list-bar-item-actions">';
$output .= '<button id="' . esc_attr( $preset['parent'] ) . '" type="button" class="vc_general vc_ui-control-button" title="' . esc_attr( 'Add element', 'js_composer' ) . '" data-template-handler="" data-preset="' . esc_attr( $presetId ) . '" data-tag="' . esc_attr( $preset['parent'] ) . '" data-vc-ui-add-preset>';
$output .= '<i class="vc-composer-icon vc-c-icon-add"></i>';
$output .= '</button>';
$output .= '<button type="button" class="vc_general vc_ui-control-button" data-vc-ui-delete="preset-title" data-preset="' . esc_attr( $presetId ) . '" data-preset-parent="' . esc_attr( $preset['parent'] ) . '" title="' . esc_attr( 'Delete element', 'js_composer' ) . '">';
$output .= '<i class="vc-composer-icon vc-c-icon-delete_empty"></i>';
$output .= '</button>';
$output .= '</div>';
$output .= '</div>';
$output .= '</div>';
}
return $output;
}
/**
* Get preset parent shortcode name from post mime type
*
* @param $presetMimeType
*
* @return string
* @since 5.2
*
*/
public static function constructPresetParent( $presetMimeType ) {
return str_replace( '-', '_', str_replace( 'vc-settings-preset/', '', $presetMimeType ) );
}
}

View File

@@ -0,0 +1,105 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* WPBakery WPBakery Page Builder main class.
*
* @package WPBakeryPageBuilder
* @since 4.2
*/
/**
* Edit form for shortcodes with ability to manage shortcode attributes in more convenient way.
*
* @since 4.2
*/
class Vc_Shortcode_Edit_Form {
protected $initialized;
/**
*
*/
public function init() {
if ( $this->initialized ) {
return;
}
$this->initialized = true;
add_action( 'wp_ajax_vc_edit_form', array(
$this,
'renderFields',
) );
add_filter( 'vc_single_param_edit', array(
$this,
'changeEditFormFieldParams',
) );
add_filter( 'vc_edit_form_class', array(
$this,
'changeEditFormParams',
) );
}
/**
*
*/
public function render() {
vc_include_template( 'editors/popups/vc_ui-panel-edit-element.tpl.php', array(
'box' => $this,
) );
}
/**
* Build edit form fields.
*
* @since 4.4
*/
public function renderFields() {
$tag = vc_post_param( 'tag' );
vc_user_access()->checkAdminNonce()->validateDie( esc_html__( 'Access denied', 'js_composer' ) )->wpAny( array(
'edit_post',
(int) vc_request_param( 'post_id' ),
) )->validateDie( esc_html__( 'Access denied', 'js_composer' ) )->check( 'vc_user_access_check_shortcode_edit', $tag )->validateDie( esc_html__( 'Access denied', 'js_composer' ) );
$params = (array) stripslashes_deep( vc_post_param( 'params' ) );
$params = array_map( 'vc_htmlspecialchars_decode_deep', $params );
require_once vc_path_dir( 'EDITORS_DIR', 'class-vc-edit-form-fields.php' );
$fields = new Vc_Edit_Form_Fields( $tag, $params );
$output = $fields->render();
// @codingStandardsIgnoreLine
wp_die( $output );
}
/**
* @param $param
*
* @return mixed
*/
public function changeEditFormFieldParams( $param ) {
$css = $param['vc_single_param_edit_holder_class'];
if ( isset( $param['edit_field_class'] ) ) {
$new_css = $param['edit_field_class'];
} else {
$new_css = 'vc_col-xs-12';
}
array_unshift( $css, $new_css );
$param['vc_single_param_edit_holder_class'] = $css;
return $param;
}
/**
* @param $css_classes
*
* @return mixed
*/
public function changeEditFormParams( $css_classes ) {
$css = '';
array_unshift( $css_classes, $css );
return $css_classes;
}
}

View File

@@ -0,0 +1,870 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Class Vc_Templates_Panel_Editor
* @since 4.4
*/
class Vc_Templates_Panel_Editor {
/**
* @since 4.4
* @var string
*/
protected $option_name = 'wpb_js_templates';
/**
* @since 4.4
* @var bool
*/
protected $default_templates = false;
/**
* @since 4.4
* @var bool
*/
protected $initialized = false;
/**
* @since 4.4
* Add ajax hooks, filters.
*/
public function init() {
if ( $this->initialized ) {
return;
}
$this->initialized = true;
add_filter( 'vc_load_default_templates_welcome_block', array(
$this,
'loadDefaultTemplatesLimit',
) );
add_filter( 'vc_templates_render_category', array(
$this,
'renderTemplateBlock',
), 10 );
add_filter( 'vc_templates_render_template', array(
$this,
'renderTemplateWindow',
), 10, 2 );
/**
* Ajax methods
* 'vc_save_template' -> saving content as template
* 'vc_backend_load_template' -> loading template content for backend
* 'vc_frontend_load_template' -> loading template content for frontend
* 'vc_delete_template' -> deleting template by index
*/
add_action( 'wp_ajax_vc_save_template', array(
$this,
'save',
) );
add_action( 'wp_ajax_vc_backend_load_template', array(
$this,
'renderBackendTemplate',
) );
add_action( 'wp_ajax_vc_frontend_load_template', array(
$this,
'renderFrontendTemplate',
) );
add_action( 'wp_ajax_vc_load_template_preview', array(
$this,
'renderTemplatePreview',
) );
add_action( 'wp_ajax_vc_delete_template', array(
$this,
'delete',
) );
}
/**
* @return string
*/
public function addBodyClassTemplatePreview() {
return 'vc_general-template-preview';
}
/**
* @param $category
* @return mixed
*/
public function renderTemplateBlock( $category ) {
if ( 'my_templates' === $category['category'] ) {
$category['output'] = '';
if ( vc_user_access()->part( 'templates' )->checkStateAny( true, null )->get() ) {
$category['output'] .= '
<div class="vc_column vc_col-sm-12" data-vc-hide-on-search="true">
<div class="vc_element_label">' . esc_html__( 'Save current layout as a template', 'js_composer' ) . '</div>
<div class="vc_input-group">
<input name="padding" data-js-element="vc-templates-input" class="vc_form-control wpb-textinput vc_panel-templates-name" type="text" value="" placeholder="' . esc_attr__( 'Template name', 'js_composer' ) . '" data-vc-disable-empty="#vc_ui-save-template-btn">
<span class="vc_input-group-btn">
<button class="vc_general vc_ui-button vc_ui-button-size-sm vc_ui-button-action vc_ui-button-shape-rounded vc_template-save-btn" id="vc_ui-save-template-btn" disabled data-vc-ui-element="button-save">' . esc_html__( 'Save Template', 'js_composer' ) . '</button>
</span>
</div>
<span class="vc_description">' . esc_html__( 'Save layout and reuse it on different sections of this site.', 'js_composer' ) . '</span>
</div>';
}
$category['output'] .= '<div class="vc_column vc_col-sm-12">';
if ( isset( $category['category_name'] ) ) {
$category['output'] .= '<h3>' . esc_html( $category['category_name'] ) . '</h3>';
}
if ( isset( $category['category_description'] ) ) {
$category['output'] .= '<p class="vc_description">' . esc_html( $category['category_description'] ) . '</p>';
}
$category['output'] .= '</div>';
$category['output'] .= '
<div class="vc_column vc_col-sm-12">
<div class="vc_ui-template-list vc_templates-list-my_templates vc_ui-list-bar" data-vc-action="collapseAll">';
if ( ! empty( $category['templates'] ) ) {
foreach ( $category['templates'] as $template ) {
$category['output'] .= $this->renderTemplateListItem( $template );
}
}
$category['output'] .= '
</div>
</div>';
} else {
if ( 'default_templates' === $category['category'] ) {
$category['output'] = '<div class="vc_col-md-12">';
if ( isset( $category['category_name'] ) ) {
$category['output'] .= '<h3>' . esc_html( $category['category_name'] ) . '</h3>';
}
if ( isset( $category['category_description'] ) ) {
$category['output'] .= '<p class="vc_description">' . esc_html( $category['category_description'] ) . '</p>';
}
$category['output'] .= '</div>';
$category['output'] .= '
<div class="vc_column vc_col-sm-12">
<div class="vc_ui-template-list vc_templates-list-default_templates vc_ui-list-bar" data-vc-action="collapseAll">';
if ( ! empty( $category['templates'] ) ) {
foreach ( $category['templates'] as $template ) {
$category['output'] .= $this->renderTemplateListItem( $template );
}
}
$category['output'] .= '
</div>
</div>';
}
}
return $category;
}
/** Output rendered template in new panel dialog
* @param $template_name
* @param $template_data
*
* @return string
* @since 4.4
*
*/
public function renderTemplateWindow( $template_name, $template_data ) {
if ( 'my_templates' === $template_data['type'] ) {
return $this->renderTemplateWindowMyTemplates( $template_name, $template_data );
} else {
if ( 'default_templates' === $template_data['type'] ) {
return $this->renderTemplateWindowDefaultTemplates( $template_name, $template_data );
}
}
return $template_name;
}
/**
* @param $template_name
* @param $template_data
*
* @return string
* @since 4.4
*
*/
public function renderTemplateWindowMyTemplates( $template_name, $template_data ) {
ob_start();
$template_id = esc_attr( $template_data['unique_id'] );
$template_id_hash = md5( $template_id ); // needed for jquery target for TTA
$template_name = esc_html( $template_name );
$preview_template_title = esc_attr__( 'Preview template', 'js_composer' );
$add_template_title = esc_attr__( 'Add template', 'js_composer' );
echo '<button type="button" class="vc_ui-list-bar-item-trigger" title="' . esc_attr( $add_template_title ) . '" data-template-handler="" data-vc-ui-element="template-title">' . esc_html( $template_name ) . '</button><div class="vc_ui-list-bar-item-actions"><button type="button" class="vc_general vc_ui-control-button" title="' . esc_attr( $add_template_title ) . '" data-template-handler=""><i class="vc-composer-icon vc-c-icon-add"></i></button>';
if ( vc_user_access()->part( 'templates' )->checkStateAny( true, null )->get() ) {
$delete_template_title = esc_attr__( 'Delete template', 'js_composer' );
echo '<button type="button" class="vc_general vc_ui-control-button" data-vc-ui-delete="template-title" title="' . esc_attr( $delete_template_title ) . '"><i class="vc-composer-icon vc-c-icon-delete_empty"></i></button>';
}
echo '<button type="button" class="vc_general vc_ui-control-button" title="' . esc_attr( $preview_template_title ) . '" data-vc-container=".vc_ui-list-bar" data-vc-preview-handler data-vc-target="[data-template_id_hash=' . esc_attr( $template_id_hash ) . ']"><i class="vc-composer-icon vc-c-icon-arrow_drop_down"></i></button></div>';
return ob_get_clean();
}
/**
* @param $template_name
* @param $template_data
*
* @return string
* @since 4.4
*
*/
public function renderTemplateWindowDefaultTemplates( $template_name, $template_data ) {
ob_start();
$template_id = esc_attr( $template_data['unique_id'] );
$template_id_hash = md5( $template_id ); // needed for jquery target for TTA
$template_name = esc_html( $template_name );
$preview_template_title = esc_attr__( 'Preview template', 'js_composer' );
$add_template_title = esc_attr__( 'Add template', 'js_composer' );
echo sprintf( '<button type="button" class="vc_ui-list-bar-item-trigger" title="%s"
data-template-handler=""
data-vc-ui-element="template-title">%s</button>
<div class="vc_ui-list-bar-item-actions">
<button type="button" class="vc_general vc_ui-control-button" title="%s"
data-template-handler="">
<i class="vc-composer-icon vc-c-icon-add"></i>
</button>
<button type="button" class="vc_general vc_ui-control-button" title="%s"
data-vc-container=".vc_ui-list-bar" data-vc-preview-handler data-vc-target="[data-template_id_hash=%s]">
<i class="vc-composer-icon vc-c-icon-arrow_drop_down"></i>
</button>
</div>', esc_attr( $add_template_title ), esc_html( $template_name ), esc_attr( $add_template_title ), esc_attr( $preview_template_title ), esc_attr( $template_id_hash ) );
return ob_get_clean();
}
/**
* @since 4.4
* vc_filter: vc_templates_render_frontend_template - called when unknown template received to render in frontend.
*/
public function renderFrontendTemplate() {
vc_user_access()->checkAdminNonce()->validateDie()->wpAny( 'edit_posts', 'edit_pages' )->validateDie()->part( 'templates' )->can()->validateDie();
add_filter( 'vc_frontend_template_the_content', array(
$this,
'frontendDoTemplatesShortcodes',
) );
$template_id = vc_post_param( 'template_unique_id' );
$template_type = vc_post_param( 'template_type' );
add_action( 'wp_print_scripts', array(
$this,
'addFrontendTemplatesShortcodesCustomCss',
) );
if ( '' === $template_id ) {
die( 'Error: Vc_Templates_Panel_Editor::renderFrontendTemplate:1' );
}
WPBMap::addAllMappedShortcodes();
if ( 'my_templates' === $template_type ) {
$saved_templates = get_option( $this->option_name );
vc_frontend_editor()->setTemplateContent( $saved_templates[ $template_id ]['template'] );
vc_frontend_editor()->enqueueRequired();
vc_include_template( 'editors/frontend_template.tpl.php', array(
'editor' => vc_frontend_editor(),
) );
die();
} else {
if ( 'default_templates' === $template_type ) {
$this->renderFrontendDefaultTemplate();
} else {
// @codingStandardsIgnoreLine
print apply_filters( 'vc_templates_render_frontend_template', $template_id, $template_type );
}
}
die; // no needs to do anything more. optimization.
}
/**
* Load frontend default template content by index
* @since 4.4
*/
public function renderFrontendDefaultTemplate() {
$template_index = (int) vc_post_param( 'template_unique_id' );
$data = $this->getDefaultTemplate( $template_index );
if ( ! $data ) {
die( 'Error: Vc_Templates_Panel_Editor::renderFrontendDefaultTemplate:1' );
}
vc_frontend_editor()->setTemplateContent( trim( $data['content'] ) );
vc_frontend_editor()->enqueueRequired();
vc_include_template( 'editors/frontend_template.tpl.php', array(
'editor' => vc_frontend_editor(),
) );
die();
}
/**
* @since 4.7
*/
public function renderUITemplate() {
vc_include_template( 'editors/popups/vc_ui-panel-templates.tpl.php', array(
'box' => $this,
) );
return '';
}
/**
* @since 4.4
*/
public function save() {
vc_user_access()->checkAdminNonce()->validateDie()->wpAny( 'edit_posts', 'edit_pages' )->validateDie()->part( 'templates' )->checkStateAny( true, null )->validateDie();
$template_name = vc_post_param( 'template_name' );
$template = vc_post_param( 'template' );
if ( ! isset( $template_name ) || '' === trim( $template_name ) || ! isset( $template ) || '' === trim( $template ) ) {
header( ':', true, 500 );
throw new Exception( 'Error: Vc_Templates_Panel_Editor::save:1' );
}
$template_arr = array(
'name' => stripslashes( $template_name ),
'template' => stripslashes( $template ),
);
$saved_templates = get_option( $this->option_name );
$template_id = sanitize_title( $template_name ) . '_' . wp_rand();
if ( false === $saved_templates ) {
$autoload = 'no';
$new_template = array();
$new_template[ $template_id ] = $template_arr;
add_option( $this->option_name, $new_template, '', $autoload );
} else {
$saved_templates[ $template_id ] = $template_arr;
update_option( $this->option_name, $saved_templates );
}
$template = array(
'name' => $template_arr['name'],
'type' => 'my_templates',
'unique_id' => $template_id,
);
// @codingStandardsIgnoreLine
print $this->renderTemplateListItem( $template );
die;
}
/**
* Loading Any templates Shortcodes for backend by string $template_id from AJAX
* @since 4.4
* vc_filter: vc_templates_render_backend_template - called when unknown template requested to render in backend
*/
public function renderBackendTemplate() {
vc_user_access()->checkAdminNonce()->validateDie()->wpAny( 'edit_posts', 'edit_pages' )->validateDie()->part( 'templates' )->can()->validateDie();
$template_id = vc_post_param( 'template_unique_id' );
$template_type = vc_post_param( 'template_type' );
if ( ! isset( $template_id, $template_type ) || '' === $template_id || '' === $template_type ) {
die( 'Error: Vc_Templates_Panel_Editor::renderBackendTemplate:1' );
}
WPBMap::addAllMappedShortcodes();
if ( 'my_templates' === $template_type ) {
$saved_templates = get_option( $this->option_name );
$content = trim( $saved_templates[ $template_id ]['template'] );
$content = str_replace( '\"', '"', $content );
$pattern = get_shortcode_regex();
$content = preg_replace_callback( "/{$pattern}/s", 'vc_convert_shortcode', $content );
// @codingStandardsIgnoreLine
print $content;
die();
} else {
if ( 'default_templates' === $template_type ) {
$this->getBackendDefaultTemplate();
die();
} else {
// @codingStandardsIgnoreLine
print apply_filters( 'vc_templates_render_backend_template', $template_id, $template_type );
die();
}
}
}
/**
* Render new template view as backened editor content.
*
* @since 4.8
*/
public function renderTemplatePreview() {
vc_user_access()->checkAdminNonce()->validateDie()->wpAny( array(
'edit_post',
(int) vc_request_param( 'post_id' ),
) )->validateDie()->part( 'templates' )->can()->validateDie();
$template_id = vc_request_param( 'template_unique_id' );
$template_type = vc_request_param( 'template_type' );
global $current_user;
wp_get_current_user();
if ( ! isset( $template_id, $template_type ) || '' === $template_id || '' === $template_type ) {
die( esc_html__( 'Error: wrong template id.', 'js_composer' ) );
}
WPBMap::addAllMappedShortcodes();
if ( 'my_templates' === $template_type ) {
$saved_templates = get_option( $this->option_name );
$content = trim( $saved_templates[ $template_id ]['template'] );
$content = str_replace( '\"', '"', $content );
$pattern = get_shortcode_regex();
$content = preg_replace_callback( "/{$pattern}/s", 'vc_convert_shortcode', $content );
} else {
if ( 'default_templates' === $template_type ) {
$content = $this->getBackendDefaultTemplate( true );
} else {
$content = apply_filters( 'vc_templates_render_backend_template_preview', $template_id, $template_type );
}
}
vc_include_template( apply_filters( 'vc_render_template_preview_include_template', 'editors/vc_ui-template-preview.tpl.php' ), array(
'content' => $content,
'editorPost' => get_post( vc_request_param( 'post_id' ) ),
'current_user' => $current_user,
) );
die();
}
public function registerPreviewScripts() {
visual_composer()->registerAdminJavascript();
visual_composer()->registerAdminCss();
vc_backend_editor()->registerBackendJavascript();
vc_backend_editor()->registerBackendCss();
wp_register_script( 'vc_editors-templates-preview-js', vc_asset_url( 'js/editors/templates-preview.js' ), array(
'vc-backend-min-js',
), WPB_VC_VERSION, true );
}
/**
* Enqueue required scripts for template preview
* @since 4.8
*/
public function enqueuePreviewScripts() {
vc_backend_editor()->enqueueCss();
vc_backend_editor()->enqueueJs();
wp_enqueue_script( 'vc_editors-templates-preview-js' );
}
/**
* @since 4.4
*/
public function delete() {
vc_user_access()->checkAdminNonce()->validateDie()->wpAny( 'edit_posts', 'edit_pages' )->validateDie()->part( 'templates' )->checkStateAny( true, null )->validateDie();
$template_id = vc_post_param( 'template_id' );
$template_type = vc_post_param( 'template_type' );
if ( ! isset( $template_id ) || '' === $template_id ) {
die( 'Error: Vc_Templates_Panel_Editor::delete:1' );
}
if ( 'my_templates' === $template_type ) {
$saved_templates = get_option( $this->option_name );
unset( $saved_templates[ $template_id ] );
if ( count( $saved_templates ) > 0 ) {
update_option( $this->option_name, $saved_templates );
} else {
delete_option( $this->option_name );
}
wp_send_json_success();
} else {
do_action( 'vc_templates_delete_templates', $template_id, $template_type );
}
wp_send_json_error();
}
/**
* @param $templates
*
* vc_filter: vc_load_default_templates_limit_total - total items to show
*
* @return array
* @since 4.4
*
*/
public function loadDefaultTemplatesLimit( $templates ) {
$start_index = 0;
$total_templates_to_show = apply_filters( 'vc_load_default_templates_limit_total', 6 );
return array_slice( $templates, $start_index, $total_templates_to_show );
}
/**
* Get user templates
*
* @return mixed
* @since 4.12
*/
public function getUserTemplates() {
return apply_filters( 'vc_get_user_templates', get_option( $this->option_name ) );
}
/**
* Function to get all templates for display
* - with image (optional preview image)
* - with unique_id (required for do something for rendering.. )
* - with name (required for display? )
* - with type (required for requesting data in server)
* - with category key (optional/required for filtering), if no category provided it will be displayed only in
* "All" category type vc_filter: vc_get_user_templates - hook to override "user My Templates" vc_filter:
* vc_get_all_templates - hook for override return array(all templates), hook to add/modify/remove more templates,
* - this depends only to displaying in panel window (more layouts)
* @return array - all templates with name/unique_id/category_key(optional)/image
* @since 4.4
*/
public function getAllTemplates() {
$data = array();
// Here we go..
if ( apply_filters( 'vc_show_user_templates', true ) ) {
// We need to get all "My Templates"
$user_templates = $this->getUserTemplates();
// this has only 'name' and 'template' key and index 'key' is template id.
$arr_category = array(
'category' => 'my_templates',
'category_name' => esc_html__( 'My Templates', 'js_composer' ),
'category_description' => esc_html__( 'Append previously saved template to the current layout.', 'js_composer' ),
'category_weight' => 10,
);
$category_templates = array();
if ( ! empty( $user_templates ) ) {
foreach ( $user_templates as $template_id => $template_data ) {
$category_templates[] = array(
'unique_id' => $template_id,
'name' => $template_data['name'],
'type' => 'my_templates',
// for rendering in backend/frontend with ajax
);
}
}
$arr_category['templates'] = $category_templates;
$data[] = $arr_category;
}
// To get all "Default Templates"
$default_templates = $this->getDefaultTemplates();
if ( ! empty( $default_templates ) ) {
$arr_category = array(
'category' => 'default_templates',
'category_name' => esc_html__( 'Default Templates', 'js_composer' ),
'category_description' => esc_html__( 'Append default template to the current layout.', 'js_composer' ),
'category_weight' => 11,
);
$category_templates = array();
foreach ( $default_templates as $template_id => $template_data ) {
if ( isset( $template_data['disabled'] ) && $template_data['disabled'] ) {
continue;
}
$category_templates[] = array(
'unique_id' => $template_id,
'name' => $template_data['name'],
'type' => 'default_templates',
// for rendering in backend/frontend with ajax
'image' => isset( $template_data['image_path'] ) ? $template_data['image_path'] : false,
// preview image
'custom_class' => isset( $template_data['custom_class'] ) ? $template_data['custom_class'] : false,
);
}
if ( ! empty( $category_templates ) ) {
$arr_category['templates'] = $category_templates;
$data[] = $arr_category;
}
}
// To get any other 3rd "Custom template" - do this by hook filter 'vc_get_all_templates'
return apply_filters( 'vc_get_all_templates', $data );
}
/**
* Load default templates list and initialize variable
* To modify you should use add_filter('vc_load_default_templates','your_custom_function');
* Argument is array of templates data like:
* array(
* array(
* 'name'=>esc_html__('My custom template','my_plugin'),
* 'image_path'=> preg_replace( '/\s/', '%20', plugins_url( 'images/my_image.png', __FILE__ ) ), //
* always use preg replace to be sure that "space" will not break logic
* 'custom_class'=>'my_custom_class', // if needed
* 'content'=>'[my_shortcode]yeah[/my_shortcode]', // Use HEREDoc better to escape all single-quotes
* and double quotes
* ),
* ...
* );
* Also see filters 'vc_load_default_templates_panels' and 'vc_load_default_templates_welcome_block' to modify
* templates in panels tab and/or in welcome block. vc_filter: vc_load_default_templates - filter to override
* default templates array
* @return array
* @since 4.4
*/
public function loadDefaultTemplates() {
if ( ! $this->initialized ) {
$this->init(); // add hooks if not added already (fix for in frontend)
}
if ( ! is_array( $this->default_templates ) ) {
require_once vc_path_dir( 'CONFIG_DIR', 'templates.php' );
$templates = apply_filters( 'vc_load_default_templates', $this->default_templates );
$this->default_templates = $templates;
do_action( 'vc_load_default_templates_action' );
}
return $this->default_templates;
}
/**
* Alias for loadDefaultTemplates
* @return array - list of default templates
* @since 4.4
*/
public function getDefaultTemplates() {
return $this->loadDefaultTemplates();
}
/**
* Get default template data by template index in array.
* @param number $template_index
*
* @return array|bool
* @since 4.4
*
*/
public function getDefaultTemplate( $template_index ) {
$this->loadDefaultTemplates();
if ( ! is_numeric( $template_index ) || ! is_array( $this->default_templates ) || ! isset( $this->default_templates[ $template_index ] ) ) {
return false;
}
return $this->default_templates[ $template_index ];
}
/**
* Add custom template to default templates list ( at end of list )
* $data = array( 'name'=>'', 'image'=>'', 'content'=>'' )
* @param $data
*
* @return bool true if added, false if failed
* @since 4.4
*
*/
public function addDefaultTemplates( $data ) {
if ( is_array( $data ) && ! empty( $data ) && isset( $data['name'], $data['content'] ) ) {
if ( ! is_array( $this->default_templates ) ) {
$this->default_templates = array();
}
$this->default_templates[] = $data;
return true;
}
return false;
}
/**
* Load default template content by index from ajax
* @param bool $return | should function return data or not
*
* @return string
* @since 4.4
*
*/
public function getBackendDefaultTemplate( $return = false ) {
$template_index = (int) vc_request_param( 'template_unique_id' );
$data = $this->getDefaultTemplate( $template_index );
if ( ! $data ) {
die( 'Error: Vc_Templates_Panel_Editor::getBackendDefaultTemplate:1' );
}
if ( $return ) {
return trim( $data['content'] );
} else {
print trim( $data['content'] );
die;
}
}
/**
* @param array $data
*
* @return array
* @since 4.4
*
*/
public function sortTemplatesByCategories( array $data ) {
$buffer = $data;
uasort( $buffer, array(
$this,
'cmpCategory',
) );
return $buffer;
}
/**
* @param array $data
*
* @return array
* @since 4.4
*
*/
public function sortTemplatesByNameWeight( array $data ) {
$buffer = $data;
uasort( $buffer, array(
$this,
'cmpNameWeight',
) );
return $buffer;
}
/**
* Function should return array of templates categories
* @param array $categories
*
* @return array - associative array of category key => and visible Name
* @since 4.4
*
*/
public function getAllCategoriesNames( array $categories ) {
$categories_names = array();
foreach ( $categories as $category ) {
if ( isset( $category['category'] ) ) {
$categories_names[ $category['category'] ] = isset( $category['category_name'] ) ? $category['category_name'] : $category['category'];
}
}
return $categories_names;
}
/**
* @return array
* @since 4.4
*/
public function getAllTemplatesSorted() {
$data = $this->getAllTemplates();
// firstly we need to sort by categories
$data = $this->sortTemplatesByCategories( $data );
// secondly we need to sort templates by their weight or name
foreach ( $data as $key => $category ) {
$data[ $key ]['templates'] = $this->sortTemplatesByNameWeight( $category['templates'] );
}
return $data;
}
/**
* Used to compare two templates by category, category_weight
* If category weight is less template will appear in first positions
* @param array $a - template one
* @param array $b - second template to compare
*
* @return int
* @since 4.4
*
*/
protected function cmpCategory( $a, $b ) {
$a_k = isset( $a['category'] ) ? $a['category'] : '*';
$b_k = isset( $b['category'] ) ? $b['category'] : '*';
$a_category_weight = isset( $a['category_weight'] ) ? $a['category_weight'] : 0;
$b_category_weight = isset( $b['category_weight'] ) ? $b['category_weight'] : 0;
return $a_category_weight === $b_category_weight ? strcmp( $a_k, $b_k ) : $a_category_weight - $b_category_weight;
}
/**
* @param $a
* @param $b
*
* @return int
* @since 4.4
*
*/
protected function cmpNameWeight( $a, $b ) {
$a_k = isset( $a['name'] ) ? $a['name'] : '*';
$b_k = isset( $b['name'] ) ? $b['name'] : '*';
$a_weight = isset( $a['weight'] ) ? $a['weight'] : 0;
$b_weight = isset( $b['weight'] ) ? $b['weight'] : 0;
return $a_weight === $b_weight ? strcmp( $a_k, $b_k ) : $a_weight - $b_weight;
}
/**
* Calls do_shortcode for templates.
*
* @param $content
*
* @return string
*/
public function frontendDoTemplatesShortcodes( $content ) {
return do_shortcode( $content );
}
/**
* Add custom css from shortcodes from template for template editor.
*
* Used by action 'wp_print_scripts'.
*
* @todo move to autoload or else some where.
* @since 4.4.3
*
*/
public function addFrontendTemplatesShortcodesCustomCss() {
$output = $shortcodes_custom_css = '';
$shortcodes_custom_css = visual_composer()->parseShortcodesCustomCss( vc_frontend_editor()->getTemplateContent() );
if ( ! empty( $shortcodes_custom_css ) ) {
$shortcodes_custom_css = wp_strip_all_tags( $shortcodes_custom_css );
$first_tag = 'style';
$output .= '<' . $first_tag . ' data-type="vc_shortcodes-custom-css">';
$output .= $shortcodes_custom_css;
$output .= '</' . $first_tag . '>';
}
// @todo Check for wp_add_inline_style posibility
// @codingStandardsIgnoreLine
print $output;
}
public function addScriptsToTemplatePreview() {
}
/**
* @param $template
* @return string
*/
public function renderTemplateListItem( $template ) {
$name = isset( $template['name'] ) ? esc_html( $template['name'] ) : esc_html__( 'No title', 'js_composer' );
$template_id = esc_attr( $template['unique_id'] );
$template_id_hash = md5( $template_id ); // needed for jquery target for TTA
$template_name = esc_html( $name );
$template_name_lower = esc_attr( vc_slugify( $template_name ) );
$template_type = esc_attr( isset( $template['type'] ) ? $template['type'] : 'custom' );
$custom_class = esc_attr( isset( $template['custom_class'] ) ? $template['custom_class'] : '' );
$output = <<<HTML
<div class="vc_ui-template vc_templates-template-type-$template_type $custom_class"
data-template_id="$template_id"
data-template_id_hash="$template_id_hash"
data-category="$template_type"
data-template_unique_id="$template_id"
data-template_name="$template_name_lower"
data-template_type="$template_type"
data-vc-content=".vc_ui-template-content">
<div class="vc_ui-list-bar-item">
HTML;
$output .= apply_filters( 'vc_templates_render_template', $name, $template );
$output .= <<<HTML
</div>
<div class="vc_ui-template-content" data-js-content>
</div>
</div>
HTML;
return $output;
}
/**
* @return string
*/
/**
* @return string
*/
public function getOptionName() {
return $this->option_name;
}
}

View File

@@ -0,0 +1,37 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
// Helpers
if ( ! function_exists( 'vc_atm_build_categories_array' ) ) {
/**
* @param $string
*
* @return array
*/
function vc_atm_build_categories_array( $string ) {
return explode( ',', preg_replace( '/\,\s+/', ',', trim( $string ) ) );
}
}
if ( ! function_exists( 'vc_atm_build_params_array' ) ) {
/**
* @param $array
*
* @return array
*/
function vc_atm_build_params_array( $array ) {
$params = array();
if ( is_array( $array ) ) {
foreach ( $array as $param ) {
if ( 'dropdown' === $param['type'] ) {
$param['value'] = explode( ',', preg_replace( '/\,\s+/', ',', trim( $param['value'] ) ) );
}
$param['save_always'] = true;
$params[] = $param;
}
}
return $params;
}
}

View File

@@ -0,0 +1,168 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
if ( ! class_exists( 'Vc_Automap_Model' ) ) {
/**
* Shortcode as model for automapper. Provides crud functionality for storing data for shortcodes that mapped by ATM
*
* @see Vc_Automapper
* @since 4.1
*/
class Vc_Automap_Model {
/**
* @var string
*/
protected static $option_name = 'vc_automapped_shortcodes';
/**
* @var
*/
protected static $option_data;
/**
* @var array|bool
*/
public $id = false;
public $tag;
/**
* @var mixed
*/
protected $data;
/**
* @var array
*/
protected $vars = array(
'tag',
'name',
'category',
'description',
'params',
);
public $name;
/**
* @param $data
*/
public function __construct( $data ) {
$this->loadOptionData();
$this->id = is_array( $data ) && isset( $data['id'] ) ? esc_attr( $data['id'] ) : $data;
if ( is_array( $data ) ) {
$this->data = stripslashes_deep( $data );
}
foreach ( $this->vars as $var ) {
$this->{$var} = $this->get( $var );
}
}
/**
* @return array
*/
public static function findAll() {
self::loadOptionData();
$records = array();
foreach ( self::$option_data as $id => $record ) {
$record['id'] = $id;
$model = new self( $record );
if ( $model ) {
$records[] = $model;
}
}
return $records;
}
/**
* @return array|mixed
*/
final protected static function loadOptionData() {
if ( is_null( self::$option_data ) ) {
self::$option_data = get_option( self::$option_name );
}
if ( ! self::$option_data ) {
self::$option_data = array();
}
return self::$option_data;
}
/**
* @param $key
*
* @return null
*/
public function get( $key ) {
if ( is_null( $this->data ) ) {
$this->data = isset( self::$option_data[ $this->id ] ) ? self::$option_data[ $this->id ] : array();
}
return isset( $this->data[ $key ] ) ? $this->data[ $key ] : null;
}
/**
* @param $attr
* @param null $value
*/
public function set( $attr, $value = null ) {
if ( is_array( $attr ) ) {
foreach ( $attr as $key => $value ) {
$this->set( $key, $value );
}
} elseif ( ! is_null( $value ) ) {
$this->{$attr} = $value;
}
}
/**
* @return bool
*/
public function save() {
if ( ! $this->isValid() ) {
return false;
}
foreach ( $this->vars as $var ) {
$this->data[ $var ] = $this->{$var};
}
return $this->saveOption();
}
/**
* @return bool
*/
public function delete() {
return $this->deleteOption();
}
/**
* @return bool
*/
public function isValid() {
if ( ! is_string( $this->name ) || empty( $this->name ) ) {
return false;
}
if ( ! preg_match( '/^\S+$/', $this->tag ) ) {
return false;
}
return true;
}
/**
* @return bool
*/
protected function saveOption() {
self::$option_data[ $this->id ] = $this->data;
return update_option( self::$option_name, self::$option_data );
}
/**
* @return bool
*/
protected function deleteOption() {
unset( self::$option_data[ $this->id ] );
return delete_option( self::$option_name );
}
}
}

View File

@@ -0,0 +1,392 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
if ( ! class_exists( 'Vc_Automapper' ) ) {
/**
* Automated shortcode mapping
*
* Automapper adds settings tab for VC settings tabs with ability to map custom shortcodes to VC editors,
* if shortcode is not mapped by default or developers haven't done this yet.
* No more shortcode copy/paste. Add any third party shortcode to the list of VC menu elements for reuse.
* Edit params, values and description.
*
* @since 4.1
*/
class Vc_Automapper {
/**
* @var bool
*/
protected static $disabled = false;
protected $title;
/**
*
*/
public function __construct() {
$this->title = esc_attr__( 'Shortcode Mapper', 'js_composer' );
}
/**
*
*/
public function addAjaxActions() {
add_action( 'wp_ajax_vc_automapper_create', array(
$this,
'create',
) );
add_action( 'wp_ajax_vc_automapper_read', array(
$this,
'read',
) );
add_action( 'wp_ajax_vc_automapper_update', array(
$this,
'update',
) );
add_action( 'wp_ajax_vc_automapper_delete', array(
$this,
'delete',
) );
return $this;
}
/**
* Builds html for Automapper CRUD like administration block
*
* @return bool
*/
public function renderHtml() {
if ( $this->disabled() ) {
return false;
}
?>
<div class="tab_intro">
<p><?php esc_html_e( 'WPBakery Page Builder Shortcode Mapper adds custom 3rd party vendors shortcodes to the list of WPBakery Page Builder content elements menu (Note: to map shortcode it needs to be installed on site).', 'js_composer' ); ?></p>
</div>
<div class="vc_automapper-toolbar">
<a href=javascript:;" class="button button-primary"
id="vc_automapper-add-btn"><?php esc_html_e( 'Map Shortcode', 'js_composer' ); ?></a>
</div>
<ul class="vc_automapper-list">
</ul>
<?php $this->renderTemplates(); ?>
<?php
return true;
}
/**
* @param $shortcode
*/
public function renderListItem( $shortcode ) {
echo sprintf( '<li class="vc_automapper-item" data-item-id=""><label>%s</label><span class="vc_automapper-item-controls"><a href="javascript:;" class="vc_automapper-edit-btn" data-id="%s" data-tag="%s"></a><a href="javascript:;" class="vc_automapper-delete-btn" data-id="%s" data-tag="%s"></a></span></li>', esc_html( $shortcode->name ), esc_attr( $shortcode->id ), esc_attr( $shortcode->tag ), esc_attr( $shortcode->id ), esc_attr( $shortcode->tag ) );
}
/**
*
*/
public function renderMapFormTpl() {
$custom_tag = 'script'; // Maybe use html shadow dom or ajax response for templates
?>
<<?php echo esc_attr( $custom_tag ); ?> type="text/html" id="vc_automapper-add-form-tpl">
<label for="vc_atm-shortcode-string"
class="vc_info"><?php esc_html_e( 'Shortcode string', 'js_composer' ); ?></label>
<div class="vc_wrapper">
<div class="vc_string">
<input id="vc_atm-shortcode-string"
placeholder="<?php esc_attr_e( 'Please enter valid shortcode', 'js_composer' ); ?>"
type="text" class="vc_atm-string">
</div>
<div class="vc_buttons">
<a href="#" id="vc_atm-parse-string"
class="button button-primary vc_parse-btn"><?php esc_attr_e( 'Parse Shortcode', 'js_composer' ); ?></a>
<a href="#" class="button vc_atm-cancel"><?php esc_attr_e( 'Cancel', 'js_composer' ); ?></a>
</div>
</div>
<span
class="description"><?php esc_html_e( 'Enter valid shortcode (Example: [my_shortcode first_param="first_param_value"]My shortcode content[/my_shortcode]).', 'js_composer' ); ?></span>
</<?php echo esc_attr( $custom_tag ); ?>>
<<?php echo esc_attr( $custom_tag ); ?> type="text/html" id="vc_automapper-item-complex-tpl">
<div class="widget-top">
<div class="widget-title-action">
<button type="button" class="widget-action hide-if-no-js" aria-expanded="true">
<span class="screen-reader-text"><?php esc_html_e( 'Edit widget: Search', 'js_composer' ); ?></span>
<span class="toggle-indicator" aria-hidden="true"></span>
</button>
</div>
<div class="widget-title"><h4>{{ name }}<span class="in-widget-title"></span></h4></div>
</div>
<div class="widget-inside">
</div>
</<?php echo esc_attr( $custom_tag ); ?>>
<<?php echo esc_attr( $custom_tag ); ?> type="text/html" id="vc_automapper-form-tpl">
<input type="hidden" name="name" id="vc_atm-name" value="{{ name }}">
<div class="vc_shortcode-preview" id="vc_shortcode-preview">
{{{ shortcode_preview }}}
</div>
<div class="vc_line"></div>
<div class="vc_wrapper">
<h4 class="vc_h"><?php esc_html_e( 'General Information', 'js_composer' ); ?></h4>
<div class="vc_field vc_tag">
<label for="vc_atm-tag"><?php esc_html_e( 'Tag:', 'js_composer' ); ?></label>
<input type="text" name="tag" id="vc_atm-tag" value="{{ tag }}">
</div>
<div class="vc_field vc_description">
<label for="vc_atm-description"><?php esc_html_e( 'Description:', 'js_composer' ); ?></label>
<textarea name="description" id="vc_atm-description">{{ description }}</textarea>
</div>
<div class="vc_field vc_category">
<label for="vc_atm-category"><?php esc_html_e( 'Category:', 'js_composer' ); ?></label>
<input type="text" name="category" id="vc_atm-category" value="{{ category }}">
<span
class="description"><?php esc_html_e( 'Comma separated categories names', 'js_composer' ); ?></span>
</div>
<div class="vc_field vc_is-container">
<label for="vc_atm-is-container"><input type="checkbox" name="is_container"
id="vc_atm-is-container"
value=""> <?php esc_html_e( 'Include content param into shortcode', 'js_composer' ); ?>
</label>
</div>
</div>
<div class="vc_line"></div>
<div class="vc_wrapper">
<h4 class="vc_h"><?php esc_html_e( 'Shortcode Parameters', 'js_composer' ); ?></h4>
<a href="#" id="vc_atm-add-param"
class="button vc_add-param">+ <?php esc_html_e( 'Add Param', 'js_composer' ); ?></a>
<div class="vc_params" id="vc_atm-params-list"></div>
</div>
<div class="vc_buttons">
<a href="#" id="vc_atm-save"
class="button button-primary"><?php esc_html_e( 'Save Changes', 'js_composer' ); ?></a>
<a href="#" class="button vc_atm-cancel"><?php esc_html_e( 'Cancel', 'js_composer' ); ?></a>
<a href="#" class="button vc_atm-delete"><?php esc_html_e( 'Delete', 'js_composer' ); ?></a>
</div>
</<?php echo esc_attr( $custom_tag ); ?>>
<<?php echo esc_attr( $custom_tag ); ?> type="text/html" id="vc_atm-form-param-tpl">
<div class="vc_controls vc_controls-row vc_clearfix"><a
class="vc_control column_move vc_column-move vc_move-param" href="#"
title="<?php esc_html_e( 'Drag row to reorder', 'js_composer' ); ?>" data-vc-control="move"><i
class="vc-composer-icon vc-c-icon-dragndrop"></i></a><span class="vc_row_edit_clone_delete"><a
class="vc_control column_delete vc_delete-param" href="#"
title="<?php esc_html_e( 'Delete this param', 'js_composer' ); ?>"><i class="vc-composer-icon vc-c-icon-delete_empty"></i></a></span>
</div>
<div class="wpb_element_wrapper">
<div class="vc_row vc_row-fluid wpb_row_container">
<div class="wpb_vc_column wpb_sortable vc_col-sm-12 wpb_content_holder vc_empty-column">
<div class="wpb_element_wrapper">
<div class="vc_fields vc_clearfix">
<div class="vc_param_name vc_param-field">
<label><?php esc_html_e( 'Param name', 'js_composer' ); ?></label>
<# if ( 'content' === param_name) { #>
<span class="vc_content"><?php esc_html_e( 'Content', 'js_composer' ); ?></span>
<input type="text" style="display: none;" name="param_name"
value="{{ param_name }}"
placeholder="<?php esc_attr_e( 'Required value', 'js_composer' ); ?>"
class="vc_param-name"
data-system="true">
<span class="description"
style="display: none;"><?php esc_html_e( 'Use only letters, numbers and underscore.', 'js_composer' ); ?></span>
<# } else { #>
<input type="text" name="param_name" value="{{ param_name }}"
placeholder="<?php esc_attr_e( 'Required value', 'js_composer' ); ?>"
class="vc_param-name">
<span
class="description"><?php esc_html_e( 'Please use only letters, numbers and underscore.', 'js_composer' ); ?></span>
<# } #>
</div>
<div class="vc_heading vc_param-field">
<label><?php esc_html_e( 'Heading', 'js_composer' ); ?></label>
<input type="text" name="heading" value="{{ heading }}"
placeholder="<?php esc_attr_e( 'Input heading', 'js_composer' ); ?>"
<# if ( 'hidden' === type) { #>
disabled="disabled"
<# } #>>
<span
class="description"><?php esc_html_e( 'Heading for field in shortcode edit form.', 'js_composer' ); ?></span>
</div>
<div class="vc_type vc_param-field">
<label><?php esc_html_e( 'Field type', 'js_composer' ); ?></label>
<select name="type">
<option value=""><?php esc_html_e( 'Select field type', 'js_composer' ); ?></option>
<option
value="textfield"<?php echo '<# if (type === "textfield") { #> selected<# } #>'; ?>><?php esc_html_e( 'Textfield', 'js_composer' ); ?></option>
<option
value="dropdown"<?php echo '<# if (type === "dropdown") { #> selected<# } #>'; ?>><?php esc_html_e( 'Dropdown', 'js_composer' ); ?></option>
<option
value="textarea"<?php echo '<# if(type==="textarea") { #> selected="selected"<# } #>'; ?>><?php esc_html_e( 'Textarea', 'js_composer' ); ?></option>
<# if ( 'content' === param_name ) { #>
<option
value="textarea_html"<?php echo '<# if (type === "textarea_html") { #> selected<# } #>'; ?>><?php esc_html_e( 'Textarea HTML', 'js_composer' ); ?></option>
<# } #>
<option
value="hidden"<?php echo '<# if (type === "hidden") { #> selected<# } #>'; ?>><?php esc_html_e( 'Hidden', 'js_composer' ); ?></option>
</select>
<span
class="description"><?php esc_html_e( 'Field type for shortcode edit form.', 'js_composer' ); ?></span>
</div>
<div class="vc_value vc_param-field">
<label><?php esc_html_e( 'Default value', 'js_composer' ); ?></label>
<input type="text" name="value" value="{{ value }}" class="vc_param-value">
<span
class="description"><?php esc_html_e( 'Default value or list of values for dropdown type (Note: separate by comma).', 'js_composer' ); ?></span>
</div>
<div class="description vc_param-field">
<label><?php esc_html_e( 'Description', 'js_composer' ); ?></label>
<textarea name="description" placeholder=""
<# if ( 'hidden' === type ) { #>
disabled="disabled"
<# } #> >{{ description
}}</textarea>
<span
class="description"><?php esc_html_e( 'Enter description for parameter.', 'js_composer' ); ?></span>
</div>
</div>
</div>
</div>
</div>
</div>
</<?php echo esc_attr( $custom_tag ); ?>>
<?php
}
/**
*
*/
public function renderTemplates() {
$custom_tag = 'script'; // Maybe use ajax resonse for template
?>
<<?php echo esc_attr( $custom_tag ); ?> type="text/html" id="vc_automapper-item-tpl">
<label class="vc_automapper-edit-btn">{{ name }}</label>
<span class="vc_automapper-item-controls">
<a href="#" class="vc_automapper-delete-btn" title="<?php esc_html_e( 'Delete', 'js_composer' ); ?>"></a>
<a href="#" class="vc_automapper-edit-btn" title="<?php esc_html_e( 'Edit', 'js_composer' ); ?>"></a>
</span>
</<?php echo esc_attr( $custom_tag ); ?>>
<?php
$this->renderMapFormTpl();
}
public function create() {
if ( ! vc_request_param( '_vcnonce' ) ) {
return;
}
vc_user_access()->checkAdminNonce()->validateDie()->wpAny( 'manage_options' )->validateDie()->part( 'settings' )->can( 'vc-automapper-tab' )->validateDie();
$data = vc_post_param( 'data' );
$shortcode = new Vc_Automap_Model( $data );
$this->result( $shortcode->save() );
}
public function update() {
if ( ! vc_request_param( '_vcnonce' ) ) {
return;
}
vc_user_access()->checkAdminNonce()->validateDie()->wpAny( 'manage_options' )->validateDie()->part( 'settings' )->can( 'vc-automapper-tab' )->validateDie();
$id = (int) vc_post_param( 'id' );
$data = vc_post_param( 'data' );
$shortcode = new Vc_Automap_Model( $id );
if ( ! isset( $data['params'] ) ) {
$data['params'] = array();
}
$shortcode->set( $data );
$this->result( $shortcode->save() );
}
public function delete() {
if ( ! vc_request_param( '_vcnonce' ) ) {
return;
}
vc_user_access()->checkAdminNonce()->validateDie()->wpAny( 'manage_options' )->validateDie()->part( 'settings' )->can( 'vc-automapper-tab' )->validateDie();
$id = vc_post_param( 'id' );
$shortcode = new Vc_Automap_Model( $id );
$this->result( $shortcode->delete() );
}
public function read() {
if ( ! vc_request_param( '_vcnonce' ) ) {
return;
}
vc_user_access()->checkAdminNonce()->validateDie()->wpAny( 'manage_options' )->validateDie()->part( 'settings' )->can( 'vc-automapper-tab' )->validateDie();
$this->result( Vc_Automap_Model::findAll() );
}
/**
* Ajax result output
*
* @param $data
*/
public function result( $data ) {
if ( false !== $data ) {
wp_send_json_success( $data );
} else {
wp_send_json_error( $data );
}
}
/**
* Setter/Getter for Disabling Automapper
* @static
*
* @param bool $disable
*/
public static function setDisabled( $disable = true ) {
self::$disabled = $disable;
}
/**
* @return bool
*/
public static function disabled() {
return self::$disabled;
}
/**
* Setter/Getter for Automapper title
*
* @static
*
* @param string $title
*/
public function setTitle( $title ) {
$this->title = $title;
}
/**
* @return string|void
*/
public function title() {
return $this->title;
}
/**
*
*/
public static function map() {
$shortcodes = Vc_Automap_Model::findAll();
foreach ( $shortcodes as $shortcode ) {
vc_map( array(
'name' => $shortcode->name,
'base' => $shortcode->tag,
'category' => vc_atm_build_categories_array( $shortcode->category ),
'description' => $shortcode->description,
'params' => vc_atm_build_params_array( $shortcode->params ),
'show_settings_on_create' => ! empty( $shortcode->params ),
'atm' => true,
'icon' => 'icon-wpb-atm',
) );
}
}
}
}

View File

@@ -0,0 +1,555 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* WPBakery WPBakery Page Builder Plugin
*
* @package WPBakeryPageBuilder
*
*/
/**
* Manage license
*
* Activation/deactivation is done via support portal and does not use Envato username and
* api_key anymore
*/
class Vc_License {
/**
* Option name where license key is stored
*
* @var string
*/
protected static $license_key_option = 'js_composer_purchase_code';
/**
* Option name where license key token is stored
*
* @var string
*/
protected static $license_key_token_option = 'license_key_token';
/**
* @var string
*/
protected static $support_host = 'https://support.wpbakery.com';
/**
* @var string
*/
public $error = null;
public function init() {
if ( 'vc-updater' === vc_get_param( 'page' ) ) {
$activate = vc_get_param( 'activate' );
$deactivate = vc_get_param( 'deactivate' );
if ( $activate ) {
$this->finishActivationDeactivation( true, $activate );
} elseif ( $deactivate ) {
$this->finishActivationDeactivation( false, $deactivate );
}
}
add_action( 'wp_ajax_vc_get_activation_url', array(
$this,
'startActivationResponse',
) );
add_action( 'wp_ajax_vc_get_deactivation_url', array(
$this,
'startDeactivationResponse',
) );
add_action( 'wp_ajax_nopriv_vc_check_license_key', array(
vc_license(),
'checkLicenseKeyFromRemote',
) );
}
/**
* Output notice
*
* @param string $message
* @param bool $success
*/
public function outputNotice( $message, $success = true ) {
echo sprintf( '<div class="%s"><p>%s</p></div>', (bool) $success ? 'updated' : 'error', esc_html( $message ) );
}
/**
* Show error
*
* @param string $error
*/
public function showError( $error ) {
$this->error = $error;
add_action( 'admin_notices', array(
$this,
'outputLastError',
) );
}
/**
* Output last error
*/
public function outputLastError() {
$this->outputNotice( $this->error, false );
}
/**
* Output successful activation message
*/
public function outputActivatedSuccess() {
$this->outputNotice( esc_html__( 'WPBakery Page Builder successfully activated.', 'js_composer' ), true );
}
/**
* Output successful deactivation message
*/
public function outputDeactivatedSuccess() {
$this->outputNotice( esc_html__( 'WPBakery Page Builder successfully deactivated.', 'js_composer' ), true );
}
/**
* Finish pending activation/deactivation
*
* 1) Make API call to support portal
* 2) Receive success status and license key
* 3) Set new license key
*
* @param bool $activation
* @param string $user_token
*
* @return bool
*/
public function finishActivationDeactivation( $activation, $user_token ) {
if ( ! $this->isValidToken( $user_token ) ) {
$this->showError( esc_html__( 'Token is not valid or has expired', 'js_composer' ) );
return false;
}
if ( $activation ) {
$url = self::$support_host . '/finish-license-activation';
} else {
$url = self::$support_host . '/finish-license-deactivation';
}
$params = array(
'body' => array( 'token' => $user_token ),
'timeout' => 30,
);
// FIX SSL SNI
$filter_add = true;
if ( function_exists( 'curl_version' ) ) {
$version = curl_version();
if ( version_compare( $version['version'], '7.18', '>=' ) ) {
$filter_add = false;
}
}
if ( $filter_add ) {
add_filter( 'https_ssl_verify', '__return_false' );
}
$response = wp_remote_post( $url, $params );
if ( $filter_add ) {
remove_filter( 'https_ssl_verify', '__return_false' );
}
if ( is_wp_error( $response ) ) {
$this->showError( sprintf( esc_html__( '%s. Please try again.', 'js_composer' ), $response->get_error_message() ) );
return false;
}
if ( 200 !== $response['response']['code'] ) {
$this->showError( sprintf( esc_html__( 'Server did not respond with OK: %s', 'js_composer' ), $response['response']['code'] ) );
return false;
}
$json = json_decode( $response['body'], true );
if ( ! $json || ! isset( $json['status'] ) ) {
$this->showError( esc_html__( 'Invalid response structure. Please contact us for support.', 'js_composer' ) );
return false;
}
if ( ! $json['status'] ) {
$this->showError( esc_html__( 'Something went wrong. Please contact us for support.', 'js_composer' ) );
return false;
}
if ( $activation ) {
if ( ! isset( $json['license_key'] ) || ! $this->isValidFormat( $json['license_key'] ) ) {
$this->showError( esc_html__( 'Invalid response structure. Please contact us for support.', 'js_composer' ) );
return false;
}
$this->setLicenseKey( $json['license_key'] );
add_action( 'admin_notices', array(
$this,
'outputActivatedSuccess',
) );
} else {
$this->setLicenseKey( '' );
add_action( 'admin_notices', array(
$this,
'outputDeactivatedSuccess',
) );
}
$this->setLicenseKeyToken( '' );
return true;
}
/**
* @return boolean
*/
public function isActivated() {
return (bool) $this->getLicenseKey();
}
/**
* Check license key from remote
*
* Function is used by support portal to check if VC w/ specific license is still installed
*/
public function checkLicenseKeyFromRemote() {
$license_key = vc_request_param( 'license_key' );
if ( ! $this->isValid( $license_key ) ) {
$response = array(
'status' => false,
'error' => esc_html__( 'Invalid license key', 'js_composer' ),
);
} else {
$response = array( 'status' => true );
}
die( wp_json_encode( $response ) );
}
/**
* Generate action URL
*
* @return string
*/
public function generateActivationUrl() {
$token = sha1( $this->newLicenseKeyToken() );
$url = esc_url( self::getSiteUrl() );
$redirect = esc_url( vc_updater()->getUpdaterUrl() );
return sprintf( '%s/activate-license?token=%s&url=%s&redirect=%s', self::$support_host, $token, $url, $redirect );
}
/**
* Generate action URL
*
* @return string
*/
public function generateDeactivationUrl() {
$license_key = $this->getLicenseKey();
$token = sha1( $this->newLicenseKeyToken() );
$url = esc_url( self::getSiteUrl() );
$redirect = esc_url( vc_updater()->getUpdaterUrl() );
return sprintf( '%s/deactivate-license?license_key=%s&token=%s&url=%s&redirect=%s', self::$support_host, $license_key, $token, $url, $redirect );
}
/**
* Start activation process and output redirect URL as JSON
*/
public function startActivationResponse() {
vc_user_access()->checkAdminNonce()->validateDie()->wpAny( 'manage_options' )->validateDie()->part( 'settings' )->can( 'vc-updater-tab' )->validateDie();
$response = array(
'status' => true,
'url' => $this->generateActivationUrl(),
);
die( wp_json_encode( $response ) );
}
/**
* Start deactivation process and output redirect URL as JSON
*/
public function startDeactivationResponse() {
vc_user_access()->checkAdminNonce()->validateDie( 'Failed nonce check' )->wpAny( 'manage_options' )->validateDie( 'Failed access check' )->part( 'settings' )->can( 'vc-updater-tab' )
->validateDie( 'Failed access check #2' );
$response = array(
'status' => true,
'url' => $this->generateDeactivationUrl(),
);
die( wp_json_encode( $response ) );
}
/**
* Set license key
*
* @param string $license_key
*/
public function setLicenseKey( $license_key ) {
if ( vc_is_network_plugin() ) {
update_site_option( 'wpb_js_' . self::$license_key_option, $license_key );
} else {
vc_settings()->set( self::$license_key_option, $license_key );
}
}
/**
* Get license key
*
* @return string
*/
public function getLicenseKey() {
if ( vc_is_network_plugin() ) {
$value = get_site_option( 'wpb_js_' . self::$license_key_option );
} else {
$value = vc_settings()->get( self::$license_key_option );
}
return $value;
}
/**
* Check if specified license key is valid
*
* @param string $license_key
*
* @return bool
*/
public function isValid( $license_key ) {
return $license_key === $this->getLicenseKey();
}
/**
* Set up license activation notice if needed
*
* Don't show notice on dev environment
*/
public function setupReminder() {
if ( self::isDevEnvironment() ) {
return;
}
$version1 = isset( $_COOKIE['vchideactivationmsg_vc11'] ) ? sanitize_text_field( wp_unslash( $_COOKIE['vchideactivationmsg_vc11'] ) ) : '';
if ( ! $this->isActivated() && ( empty( $version1 ) || version_compare( $version1, WPB_VC_VERSION, '<' ) ) && ! ( vc_is_network_plugin() && is_network_admin() ) ) {
add_action( 'admin_notices', array(
$this,
'adminNoticeLicenseActivation',
) );
}
}
/**
* Check if current enviroment is dev
*
* Environment is considered dev if host is:
* - ip address
* - tld is local, dev, wp, test, example, localhost or invalid
* - no tld (localhost, custom hosts)
*
* @param string $host Hostname to check. If null, use HTTP_HOST
*
* @return boolean
*/
public static function isDevEnvironment( $host = null ) {
if ( ! $host ) {
$host = self::getSiteUrl();
}
$chunks = explode( '.', $host );
if ( 1 === count( $chunks ) ) {
return true;
}
if ( in_array( end( $chunks ), array(
'local',
'dev',
'wp',
'test',
'example',
'localhost',
'invalid',
), true ) ) {
return true;
}
if ( preg_match( '/^[0-9\.]+$/', $host ) ) {
return true;
}
return false;
}
public function adminNoticeLicenseActivation() {
if ( vc_is_network_plugin() ) {
update_site_option( 'wpb_js_composer_license_activation_notified', 'yes' );
} else {
vc_settings()->set( 'composer_license_activation_notified', 'yes' );
}
$redirect = esc_url( vc_updater()->getUpdaterUrl() );
$first_tag = 'style';
$second_tag = 'script';
// @codingStandardsIgnoreStart
?>
<<?php echo esc_attr( $first_tag ); ?>>
.vc_license-activation-notice {
position: relative;
}
</<?php echo esc_attr( $first_tag ); ?>>
<<?php echo esc_attr( $second_tag ); ?>>
(function ( $ ) {
var setCookie = function ( c_name, value, exdays ) {
var exdate = new Date();
exdate.setDate( exdate.getDate() + exdays );
var c_value = encodeURIComponent( value ) + ((null === exdays) ? "" : "; expires=" + exdate.toUTCString());
document.cookie = c_name + "=" + c_value;
};
$( document ).off( 'click.vc-notice-dismiss' ).on( 'click.vc-notice-dismiss',
'.vc-notice-dismiss',
function ( e ) {
e.preventDefault();
var $el = $( this ).closest(
'#vc_license-activation-notice' );
$el.fadeTo( 100, 0, function () {
$el.slideUp( 100, function () {
$el.remove();
} );
} );
setCookie( 'vchideactivationmsg_vc11',
'<?php echo esc_attr( WPB_VC_VERSION ); ?>',
30 );
} );
})( window.jQuery );
</<?php echo esc_attr( $second_tag ); ?>>
<?php
echo '<div class="updated vc_license-activation-notice" id="vc_license-activation-notice"><p>' . sprintf( esc_html__( 'Hola! Would you like to receive automatic updates and unlock premium support? Please %sactivate your copy%s of WPBakery Page Builder.', 'js_composer' ), '<a href="' . esc_url( wp_nonce_url( $redirect ) ) . '">', '</a>' ) . '</p>' . '<button type="button" class="notice-dismiss vc-notice-dismiss"><span class="screen-reader-text">' . esc_html__( 'Dismiss this notice.', 'js_composer' ) . '</span></button></div>';
// @codingStandardsIgnoreEnd
}
/**
* Get license key token
*
* @return string
*/
public function getLicenseKeyToken() {
$value = vc_is_network_plugin() ? get_site_option( self::$license_key_token_option ) : get_option( self::$license_key_token_option );
return $value;
}
/**
* Set license key token
*
* @param string $token
*
* @return string
*/
public function setLicenseKeyToken( $token ) {
if ( vc_is_network_plugin() ) {
$value = update_site_option( self::$license_key_token_option, $token );
} else {
$value = update_option( self::$license_key_token_option, $token );
}
return $value;
}
/**
* Return new license key token
*
* Token is used to change license key from remote location
*
* Format is: timestamp|20-random-characters
*
* @return string
*/
public function generateLicenseKeyToken() {
$token = current_time( 'timestamp' ) . '|' . vc_random_string( 20 );
return $token;
}
/**
* Generate and set new license key token
*
* @return string
*/
public function newLicenseKeyToken() {
$token = $this->generateLicenseKeyToken();
$this->setLicenseKeyToken( $token );
return $token;
}
/**
* Check if specified license key token is valid
*
* @param string $token_to_check SHA1 hashed token
* @param int $ttl_in_seconds Time to live in seconds. Default = 20min
*
* @return boolean
*/
public function isValidToken( $token_to_check, $ttl_in_seconds = 1200 ) {
$token = $this->getLicenseKeyToken();
if ( ! $token_to_check || sha1( $token ) !== $token_to_check ) {
return false;
}
$chunks = explode( '|', $token );
if ( intval( $chunks[0] ) < ( current_time( 'timestamp' ) - $ttl_in_seconds ) ) {
return false;
}
return true;
}
/**
* Check if license key format is valid
*
* license key is version 4 UUID, that have form xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
* where x is any hexadecimal digit and y is one of 8, 9, A, or B.
*
* @param string $license_key
*
* @return boolean
*/
public function isValidFormat( $license_key ) {
$pattern = '/^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i';
return (bool) preg_match( $pattern, $license_key );
}
/**
* @return string|void
*/
/**
* @return string|void
*/
public static function getSiteUrl() {
if ( vc_is_network_plugin() ) {
return network_site_url();
} else {
return site_url();
}
}
}

View File

@@ -0,0 +1,165 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Manage role.
* @since 4.8
*
* Class Vc_Roles
*/
class Vc_Roles {
protected $post_types = false;
protected $vc_excluded_post_types = false;
protected $parts = array(
'post_types',
'backend_editor',
'frontend_editor',
'post_settings',
'settings',
'templates',
'shortcodes',
'grid_builder',
'presets',
'dragndrop',
);
/**
* Get list of parts
* @return mixed
*/
public function getParts() {
return apply_filters( 'vc_roles_parts_list', $this->parts );
}
/**
* Check required capability for this role to have user access.
*
* @param $part
*
* @return array|string
*/
public function getPartCapability( $part ) {
return 'settings' !== $part ? array(
'edit_posts',
'edit_pages',
) : 'manage_options';
}
/**
* @param $role
* @param $caps
* @return bool
*/
public function hasRoleCapability( $role, $caps ) {
$has = false;
$wp_role = get_role( $role );
if ( is_string( $caps ) ) {
$has = $wp_role->has_cap( $caps );
} elseif ( is_array( $caps ) ) {
$i = 0;
$count = count( $caps );
while ( false === $has && $i < $count ) {
$has = $this->hasRoleCapability( $role, $caps[ $i ++ ] );
}
}
return $has;
}
/**
* @return \WP_Roles
*/
public function getWpRoles() {
global $wp_roles;
if ( function_exists( 'wp_roles' ) ) {
return $wp_roles;
} else {
if ( ! isset( $wp_roles ) ) {
// @codingStandardsIgnoreLine
$wp_roles = new WP_Roles();
}
}
return $wp_roles;
}
/**
* @param array $params
* @return array
* @throws \Exception
*/
public function save( $params = array() ) {
$data = array( 'message' => '' );
$roles = $this->getWpRoles();
$editable_roles = get_editable_roles();
foreach ( $params as $role => $parts ) {
if ( is_string( $parts ) ) {
$parts = json_decode( stripslashes( $parts ), true );
}
if ( isset( $editable_roles[ $role ] ) ) {
foreach ( $parts as $part => $settings ) {
$part_key = vc_role_access()->who( $role )->part( $part )->getStateKey();
$stateValue = '0';
$roles->use_db = false; // Disable saving in DB on every cap change
foreach ( $settings as $key => $value ) {
if ( '_state' === $key ) {
$stateValue = in_array( $value, array(
'0',
'1',
), true ) ? (bool) $value : $value;
} else {
if ( empty( $value ) ) {
$roles->remove_cap( $role, $part_key . '/' . $key );
} else {
$roles->add_cap( $role, $part_key . '/' . $key, true );
}
}
}
$roles->use_db = true; // Enable for the lat change in cap of role to store data in DB
$roles->add_cap( $role, $part_key, $stateValue );
}
}
}
$data['message'] = esc_html__( 'Roles settings successfully saved.', 'js_composer' );
return $data;
}
/**
* @return array|bool
*/
public function getPostTypes() {
if ( false === $this->post_types ) {
$this->post_types = array();
$exclude = $this->getExcludePostTypes();
foreach ( get_post_types( array( 'public' => true ) ) as $post_type ) {
if ( ! in_array( $post_type, $exclude, true ) ) {
$this->post_types[] = array(
$post_type,
$post_type,
);
}
}
}
return $this->post_types;
}
/**
* @return bool|mixed|void
*/
public function getExcludePostTypes() {
if ( false === $this->vc_excluded_post_types ) {
$this->vc_excluded_post_types = apply_filters( 'vc_settings_exclude_post_type', array(
'attachment',
'revision',
'nav_menu_item',
'mediapage',
) );
}
return $this->vc_excluded_post_types;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,217 @@
<?php
/**
* @package WPBakery
* @noinspection PhpIncludeInspection
*/
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
*
*/
define( 'VC_SHORTCODE_CUSTOMIZE_PREFIX', 'vc_theme_' );
/**
*
*/
define( 'VC_SHORTCODE_BEFORE_CUSTOMIZE_PREFIX', 'vc_theme_before_' );
/**
*
*/
define( 'VC_SHORTCODE_AFTER_CUSTOMIZE_PREFIX', 'vc_theme_after_' );
/**
*
*/
define( 'VC_SHORTCODE_CUSTOM_CSS_FILTER_TAG', 'vc_shortcodes_css_class' );
require_once $this->path( 'SHORTCODES_DIR', 'core/class-wpbakery-visualcomposer-abstract.php' );
require_once $this->path( 'SHORTCODES_DIR', 'core/class-wpbakeryshortcode.php' );
require_once $this->path( 'SHORTCODES_DIR', 'core/class-wbpakeryshortcodefishbones.php' );
require_once $this->path( 'SHORTCODES_DIR', 'core/class-wpbakeryshortcodescontainer.php' );
/**
* @since 4.9
*
* Class Vc_Shortcodes_Manager
*/
class Vc_Shortcodes_Manager {
private $shortcode_classes = array(
'default' => array(),
);
private $tag;
/**
* Core singleton class
* @var self - pattern realization
*/
private static $instance;
/**
* Get the instance of Vc_Shortcodes_Manager
*
* @return self
*/
public static function getInstance() {
if ( ! ( self::$instance instanceof self ) ) {
self::$instance = new self();
}
return self::$instance;
}
public function getTag() {
return $this->tag;
}
/**
* @param $tag
* @return $this
*/
/**
* @param $tag
* @return $this
*/
public function setTag( $tag ) {
$this->tag = $tag;
return $this;
}
/**
* @param $tag
* @return \WPBakeryShortCodeFishBones
* @throws \Exception
*/
/**
* @param $tag
* @return \WPBakeryShortCodeFishBones
* @throws \Exception
*/
public function getElementClass( $tag ) {
$currentScope = WPBMap::getScope();
if ( isset( $this->shortcode_classes[ $currentScope ], $this->shortcode_classes[ $currentScope ][ $tag ] ) ) {
return $this->shortcode_classes[ $currentScope ][ $tag ];
}
if ( ! isset( $this->shortcode_classes[ $currentScope ] ) ) {
$this->shortcode_classes[ $currentScope ] = array();
}
$settings = WPBMap::getShortCode( $tag );
if ( empty( $settings ) ) {
throw new Exception( 'Element must be mapped in system' );
}
require_once vc_path_dir( 'SHORTCODES_DIR', 'wordpress-widgets.php' );
$class_name = ! empty( $settings['php_class_name'] ) ? $settings['php_class_name'] : 'WPBakeryShortCode_' . $settings['base'];
$autoloaded_dependencies = VcShortcodeAutoloader::includeClass( $class_name );
if ( ! $autoloaded_dependencies ) {
$file = vc_path_dir( 'SHORTCODES_DIR', str_replace( '_', '-', $settings['base'] ) . '.php' );
if ( is_file( $file ) ) {
require_once $file;
}
}
if ( class_exists( $class_name ) && is_subclass_of( $class_name, 'WPBakeryShortCode' ) ) {
$shortcode_class = new $class_name( $settings );
} else {
$shortcode_class = new WPBakeryShortCodeFishBones( $settings );
}
$this->shortcode_classes[ $currentScope ][ $tag ] = $shortcode_class;
return $shortcode_class;
}
/**
* @return \WPBakeryShortCodeFishBones
* @throws \Exception
*/
/**
* @return \WPBakeryShortCodeFishBones
* @throws \Exception
*/
public function shortcodeClass() {
return $this->getElementClass( $this->tag );
}
/**
* @param string $content
*
* @return string
* @throws \Exception
*/
public function template( $content = '' ) {
return $this->getElementClass( $this->tag )->contentAdmin( array(), $content );
}
/**
* @param $name
*
* @return null
* @throws \Exception
*/
public function settings( $name ) {
$settings = WPBMap::getShortCode( $this->tag );
return isset( $settings[ $name ] ) ? $settings[ $name ] : null;
}
/**
* @param $atts
* @param null $content
* @param null $tag
*
* @return string
* @throws \Exception
*/
public function render( $atts, $content = null, $tag = null ) {
return $this->getElementClass( $this->tag )->output( $atts, $content );
}
public function buildShortcodesAssets() {
$elements = WPBMap::getAllShortCodes();
foreach ( $elements as $tag => $settings ) {
$element_class = $this->getElementClass( $tag );
$element_class->enqueueAssets();
$element_class->printIconStyles();
}
}
public function buildShortcodesAssetsForEditable() {
$elements = WPBMap::getAllShortCodes(); // @todo create pull to use only where it is set inside function. BC problem
foreach ( $elements as $tag => $settings ) {
$element_class = $this->getElementClass( $tag );
$element_class->printIconStyles();
}
}
/**
* @param $tag
* @return bool
*/
/**
* @param $tag
* @return bool
*/
public function isShortcodeClassInitialized( $tag ) {
$currentScope = WPBMap::getScope();
return isset( $this->shortcode_classes[ $currentScope ], $this->shortcode_classes[ $currentScope ][ $tag ] );
}
/**
* @param $tag
* @return bool
*/
/**
* @param $tag
* @return bool
*/
public function unsetElementClass( $tag ) {
$currentScope = WPBMap::getScope();
unset( $this->shortcode_classes[ $currentScope ][ $tag ] );
return true;
}
}

View File

@@ -0,0 +1,154 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Class WPBakeryShortCodeFishBones
*/
class WPBakeryShortCodeFishBones extends WPBakeryShortCode {
/**
* @var bool
*/
protected $shortcode_class = false;
/**
* @param $settings
* @throws \Exception
*/
public function __construct( $settings ) {
if ( ! $settings ) {
throw new Exception( 'Element must have settings to register' );
}
$this->settings = $settings;
$this->shortcode = $this->settings['base'];
add_action( 'admin_init', array(
$this,
'hookAdmin',
) );
if ( ! shortcode_exists( $this->shortcode ) ) {
add_shortcode( $this->shortcode, array(
$this,
'render',
) );
}
}
public function hookAdmin() {
$this->enqueueAssets();
add_action( 'admin_init', array(
$this,
'enqueueAssets',
) );
if ( vc_is_page_editable() ) {
// fix for page editable
add_action( 'wp_head', array(
$this,
'printIconStyles',
) );
}
add_action( 'admin_head', array(
$this,
'printIconStyles',
) ); // fe+be
add_action( 'admin_print_scripts-post.php', array(
$this,
'enqueueAssets',
) );
add_action( 'admin_print_scripts-post-new.php', array(
$this,
'enqueueAssets',
) );
}
/**
* @return WPBakeryShortCodeFishBones
* @throws \Exception
*/
public function shortcodeClass() {
if ( false !== $this->shortcode_class ) {
return $this->shortcode_class;
}
require_once vc_path_dir( 'SHORTCODES_DIR', 'wordpress-widgets.php' );
$class_name = $this->settings( 'php_class_name' ) ? $this->settings( 'php_class_name' ) : 'WPBakeryShortCode_' . $this->settings( 'base' );
$autoloaded_dependencies = VcShortcodeAutoloader::includeClass( $class_name );
if ( ! $autoloaded_dependencies ) {
$file = vc_path_dir( 'SHORTCODES_DIR', str_replace( '_', '-', $this->settings( 'base' ) ) . '.php' );
if ( is_file( $file ) ) {
require_once $file;
}
}
if ( class_exists( $class_name ) && is_subclass_of( $class_name, 'WPBakeryShortCode' ) ) {
$this->shortcode_class = new $class_name( $this->settings );
} else {
$this->shortcode_class = new WPBakeryShortCodeFishBones( $this->settings );
}
return $this->shortcode_class;
}
/**
*
*
* @param $tag
*
* @return \WPBakeryShortCodeFishBones
* @throws \Exception
* @since 4.9
*
*/
public static function getElementClass( $tag ) {
$settings = WPBMap::getShortCode( $tag );
if ( empty( $settings ) ) {
throw new Exception( 'Element must be mapped in system' );
}
require_once vc_path_dir( 'SHORTCODES_DIR', 'wordpress-widgets.php' );
$class_name = ! empty( $settings['php_class_name'] ) ? $settings['php_class_name'] : 'WPBakeryShortCode_' . $settings['base'];
$autoloaded_dependencies = VcShortcodeAutoloader::includeClass( $class_name );
if ( ! $autoloaded_dependencies ) {
$file = vc_path_dir( 'SHORTCODES_DIR', str_replace( '_', '-', $settings['base'] ) . '.php' );
if ( is_file( $file ) ) {
require_once $file;
}
}
if ( class_exists( $class_name ) && is_subclass_of( $class_name, 'WPBakeryShortCode' ) ) {
$shortcode_class = new $class_name( $settings );
} else {
$shortcode_class = new WPBakeryShortCodeFishBones( $settings );
}
return $shortcode_class;
}
/**
* @param $atts
* @param null $content
* @param null $tag
*
* @return string
* @throws \Exception
*/
public function render( $atts, $content = null, $tag = null ) {
return self::getElementClass( $tag )->output( $atts, $content );
}
/**
* @param string $content
*
* @return string
* @throws \Exception
*/
public function template( $content = '' ) {
return $this->shortcodeClass()->contentAdmin( array(), $content );
}
}

View File

@@ -0,0 +1,197 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/* abstract VisualComposer class to create structural object of any type */
/**
* Class WPBakeryVisualComposerAbstract
*/
abstract class WPBakeryVisualComposerAbstract {
/**
* @var
*/
public static $config;
/**
* @var string
*/
protected $controls_css_settings = 'cc';
/**
* @var array
*/
protected $controls_list = array(
'edit',
'clone',
'delete',
);
/**
* @var string
*/
protected $shortcode_content = '';
/**
*
*/
public function __construct() {
}
/**
* @param $settings
* @deprecated not used
*/
public function init( $settings ) {
self::$config = (array) $settings;
}
/**
* @param $action
* @param $method
* @param int $priority
* @return true|void
* @deprecated 6.0 use native WordPress actions
*/
public function addAction( $action, $method, $priority = 10 ) {
return add_action( $action, array(
$this,
$method,
), $priority );
}
/**
* @param $action
* @param $method
* @param int $priority
*
* @return bool
* @deprecated 6.0 use native WordPress actions
*
*/
public function removeAction( $action, $method, $priority = 10 ) {
return remove_action( $action, array(
$this,
$method,
), $priority );
}
/**
* @param $filter
* @param $method
* @param int $priority
*
* @return bool|void
* @deprecated 6.0 use native WordPress actions
*
*/
public function addFilter( $filter, $method, $priority = 10 ) {
return add_filter( $filter, array(
$this,
$method,
), $priority );
}
/**
* @param $filter
* @param $method
* @param int $priority
* @return bool
* @deprecated 6.0 use native WordPress
*
*/
public function removeFilter( $filter, $method, $priority = 10 ) {
return remove_filter( $filter, array(
$this,
$method,
), $priority );
}
/**
* @param $tag
* @param $func
* @deprecated 6.0 not used
*
*/
public function addShortCode( $tag, $func ) {
// this function is deprecated since 6.0
}
/**
* @param $content
* @deprecated 6.0 not used
*
*/
public function doShortCode( $content ) {
// this function is deprecated since 6.0
}
/**
* @param $tag
* @deprecated 6.0 not used
*
*/
public function removeShortCode( $tag ) {
// this function is deprecated since 6.0
}
/**
* @param $param
*
* @return null
* @deprecated 6.0 not used, use vc_post_param
*
*/
public function post( $param ) {
// this function is deprecated since 6.0
return vc_post_param( $param );
}
/**
* @param $param
*
* @return null
* @deprecated 6.0 not used, use vc_get_param
*
*/
public function get( $param ) {
// this function is deprecated since 6.0
return vc_get_param( $param );
}
/**
* @param $asset
*
* @return string
* @deprecated 4.5 use vc_asset_url
*
*/
public function assetURL( $asset ) {
// this function is deprecated since 4.5
return vc_asset_url( $asset );
}
/**
* @param $asset
*
* @return string
* @deprecated 6.0 not used
*/
public function assetPath( $asset ) {
// this function is deprecated since 6.0
return self::$config['APP_ROOT'] . self::$config['ASSETS_DIR'] . $asset;
}
/**
* @param $name
*
* @return null
* @deprecated 6.0 not used
*/
public static function config( $name ) {
return isset( self::$config[ $name ] ) ? self::$config[ $name ] : null;
}
}

View File

@@ -0,0 +1,867 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Class WPBakeryShortCode
*/
abstract class WPBakeryShortCode extends WPBakeryVisualComposerAbstract {
/**
* @var string - shortcode tag
*/
protected $shortcode;
/**
* @var
*/
protected $html_template;
/**
* @var
*/
protected $atts;
/**
* @var
*/
protected $settings;
/**
* @var array
*/
protected static $js_scripts = array();
/**
* @var array
*/
protected static $css_scripts = array();
/**
* default scripts like scripts
* @var bool
* @since 4.4.3
*/
protected static $default_scripts_enqueued = false;
/**
* @var string
*/
protected $shortcode_string = '';
/**
* @var string
*/
protected $controls_template_file = 'editors/partials/backend_controls.tpl.php';
public $nonDraggableClass = 'vc-non-draggable';
/** @noinspection PhpMissingParentConstructorInspection */
/**
* @param $settings
*/
public function __construct( $settings ) {
$this->settings = $settings;
$this->shortcode = $this->settings['base'];
}
/**
* @param $content
*
* @return string
*/
public function addInlineAnchors( $content ) {
return ( $this->isInline() || $this->isEditor() && true === $this->settings( 'is_container' ) ? '<span class="vc_container-anchor"></span>' : '' ) . $content;
}
/**
*
*/
public function enqueueAssets() {
if ( ! empty( $this->settings['admin_enqueue_js'] ) ) {
$this->registerJs( $this->settings['admin_enqueue_js'] );
}
if ( ! empty( $this->settings['admin_enqueue_css'] ) ) {
$this->registerCss( $this->settings['admin_enqueue_css'] );
}
}
/**
* Prints out the styles needed to render the element icon for the back end interface.
* Only performed if the 'icon' setting is a valid URL.
*
* @return void
* @since 4.2
* @modified 4.4
* @author Benjamin Intal
*/
public function printIconStyles() {
if ( ! filter_var( $this->settings( 'icon' ), FILTER_VALIDATE_URL ) ) {
return;
}
$first_tag = 'style';
echo '
<' . esc_attr( $first_tag ) . '>
.vc_el-container #' . esc_attr( $this->settings['base'] ) . ' .vc_element-icon,
.wpb_' . esc_attr( $this->settings['base'] ) . ' > .wpb_element_wrapper > .wpb_element_title > .vc_element-icon,
.vc_el-container > #' . esc_attr( $this->settings['base'] ) . ' > .vc_element-icon,
.vc_el-container > #' . esc_attr( $this->settings['base'] ) . ' > .vc_element-icon[data-is-container="true"],
.compose_mode .vc_helper.vc_helper-' . esc_attr( $this->settings['base'] ) . ' > .vc_element-icon,
.vc_helper.vc_helper-' . esc_attr( $this->settings['base'] ) . ' > .vc_element-icon,
.compose_mode .vc_helper.vc_helper-' . esc_attr( $this->settings['base'] ) . ' > .vc_element-icon[data-is-container="true"],
.vc_helper.vc_helper-' . esc_attr( $this->settings['base'] ) . ' > .vc_element-icon[data-is-container="true"],
.wpb_' . esc_attr( $this->settings['base'] ) . ' > .wpb_element_wrapper > .wpb_element_title > .vc_element-icon,
.wpb_' . esc_attr( $this->settings['base'] ) . ' > .wpb_element_wrapper > .wpb_element_title > .vc_element-icon[data-is-container="true"] {
background-position: 0 0;
background-image: url(' . esc_url( $this->settings['icon'] ) . ');
-webkit-background-size: contain;
-moz-background-size: contain;
-ms-background-size: contain;
-o-background-size: contain;
background-size: contain;
}
</' . esc_attr( $first_tag ) . '>';
}
/**
* @param $param
*/
protected function registerJs( $param ) {
if ( is_array( $param ) && ! empty( $param ) ) {
foreach ( $param as $value ) {
$this->registerJs( $value );
}
} elseif ( is_string( $param ) && ! empty( $param ) ) {
$name = 'admin_enqueue_js_' . md5( $param );
self::$js_scripts[] = $name;
wp_register_script( $name, $param, array( 'jquery' ), WPB_VC_VERSION, true );
}
}
/**
* @param $param
*/
protected function registerCss( $param ) {
if ( is_array( $param ) && ! empty( $param ) ) {
foreach ( $param as $value ) {
$this->registerCss( $value );
}
} elseif ( is_string( $param ) && ! empty( $param ) ) {
$name = 'admin_enqueue_css_' . md5( $param );
self::$css_scripts[] = $name;
wp_register_style( $name, $param, array( 'js_composer' ), WPB_VC_VERSION );
}
}
/**
*
*/
public static function enqueueCss() {
if ( ! empty( self::$css_scripts ) ) {
foreach ( self::$css_scripts as $stylesheet ) {
wp_enqueue_style( $stylesheet );
}
}
}
/**
*
*/
public static function enqueueJs() {
if ( ! empty( self::$js_scripts ) ) {
foreach ( self::$js_scripts as $script ) {
wp_enqueue_script( $script );
}
}
}
/**
* @param $shortcode
*/
public function shortcode( $shortcode ) {
}
/**
* @param $template
*
* @return string
*/
protected function setTemplate( $template ) {
return $this->html_template = apply_filters( 'vc_shortcode_set_template_' . $this->shortcode, $template );
}
/**
* @return bool
*/
protected function getTemplate() {
if ( isset( $this->html_template ) ) {
return $this->html_template;
}
return false;
}
/**
* @return mixed
*/
protected function getFileName() {
return $this->shortcode;
}
/**
* Find html template for shortcode output.
*/
protected function findShortcodeTemplate() {
// Check template path in shortcode's mapping settings
if ( ! empty( $this->settings['html_template'] ) && is_file( $this->settings( 'html_template' ) ) ) {
return $this->setTemplate( $this->settings['html_template'] );
}
// Check template in theme directory
$user_template = vc_shortcodes_theme_templates_dir( $this->getFileName() . '.php' );
if ( is_file( $user_template ) ) {
return $this->setTemplate( $user_template );
}
// Check default place
$default_dir = vc_manager()->getDefaultShortcodesTemplatesDir() . '/';
if ( is_file( $default_dir . $this->getFileName() . '.php' ) ) {
return $this->setTemplate( $default_dir . $this->getFileName() . '.php' );
}
$template = apply_filters( 'vc_shortcode_set_template_' . $this->shortcode, '' );
if ( ! empty( $template ) ? $template : '' ) {
return $this->setTemplate( $template );
}
return '';
}
/**
* @param $atts
* @param null $content
*
* @return mixed
* @throws \Exception
*/
protected function content( $atts, $content = null ) {
return $this->loadTemplate( $atts, $content );
}
/**
* @param $atts
* @param null $content
*
* vc_filter: vc_shortcode_content_filter - hook to edit template content
* vc_filter: vc_shortcode_content_filter_after - hook after template is loaded to override output
*
* @return mixed
* @throws \Exception
*/
protected function loadTemplate( $atts, $content = null ) {
$output = '';
if ( ! is_null( $content ) ) {
/** @var string $content */
$content = apply_filters( 'vc_shortcode_content_filter', $content, $this->shortcode );
}
$this->findShortcodeTemplate();
if ( $this->html_template && file_exists( $this->html_template ) ) {
if ( strpos( $this->html_template, WPB_PLUGIN_DIR ) === false ) {
// Modified or new
Vc_Modifications::$modified = true;
}
ob_start();
/** @var string $content - used inside template */
$output = require $this->html_template;
// Allow return in template files
if ( 1 === $output ) {
$output = ob_get_contents();
}
ob_end_clean();
}
return apply_filters( 'vc_shortcode_content_filter_after', $output, $this->shortcode, $atts, $content );
}
/**
* @param $atts
* @param $content
*
* @return string
* @throws \Exception
*/
public function contentAdmin( $atts, $content = null ) {
$output = $custom_markup = $width = $el_position = '';
if ( null !== $content ) {
$content = wpautop( stripslashes( $content ) );
}
$shortcode_attributes = array( 'width' => '1/1' );
$atts = vc_map_get_attributes( $this->getShortcode(), $atts ) + $shortcode_attributes;
$this->atts = $atts;
$elem = $this->getElementHolder( $width );
if ( isset( $this->settings['custom_markup'] ) && '' !== $this->settings['custom_markup'] ) {
$markup = $this->settings['custom_markup'];
$elem = str_ireplace( '%wpb_element_content%', $this->customMarkup( $markup, $content ), $elem );
$output .= $elem;
} else {
$inner = $this->outputTitle( $this->settings['name'] );
$inner .= $this->paramsHtmlHolders( $atts );
$elem = str_ireplace( '%wpb_element_content%', $inner, $elem );
$output .= $elem;
}
return $output;
}
/**
* @return bool
*/
public function isAdmin() {
return apply_filters( 'vc_shortcodes_is_admin', is_admin() );
}
/**
* @return bool
*/
public function isInline() {
return vc_is_inline();
}
/**
* @return bool
*/
public function isEditor() {
return vc_is_editor();
}
/**
* @param $atts
* @param null $content
* @param string $base
*
* vc_filter: vc_shortcode_output - hook to override output of shortcode
*
* @return string
* @throws \Exception
*/
public function output( $atts, $content = null, $base = '' ) {
$this->atts = $prepared_atts = $this->prepareAtts( $atts );
$this->shortcode_content = $content;
$output = '';
$content = empty( $content ) && ! empty( $atts['content'] ) ? $atts['content'] : $content;
if ( ( $this->isInline() || vc_is_page_editable() ) && method_exists( $this, 'contentInline' ) ) {
$output .= $this->contentInline( $this->atts, $content );
} else {
$this->enqueueDefaultScripts();
$custom_output = VC_SHORTCODE_CUSTOMIZE_PREFIX . $this->shortcode;
$custom_output_before = VC_SHORTCODE_BEFORE_CUSTOMIZE_PREFIX . $this->shortcode; // before shortcode function hook
$custom_output_after = VC_SHORTCODE_AFTER_CUSTOMIZE_PREFIX . $this->shortcode; // after shortcode function hook
// Before shortcode
if ( function_exists( $custom_output_before ) ) {
$output .= $custom_output_before( $this->atts, $content );
} else {
$output .= $this->beforeShortcode( $this->atts, $content );
}
// Shortcode content
if ( function_exists( $custom_output ) ) {
$output .= $custom_output( $this->atts, $content );
} else {
$output .= $this->content( $this->atts, $content );
}
// After shortcode
if ( function_exists( $custom_output_after ) ) {
$output .= $custom_output_after( $this->atts, $content );
} else {
$output .= $this->afterShortcode( $this->atts, $content );
}
}
// Filter for overriding outputs
$output = apply_filters( 'vc_shortcode_output', $output, $this, $prepared_atts, $this->shortcode );
return $output;
}
public function enqueueDefaultScripts() {
if ( false === self::$default_scripts_enqueued ) {
wp_enqueue_script( 'wpb_composer_front_js' );
wp_enqueue_style( 'js_composer_front' );
self::$default_scripts_enqueued = true;
}
}
/**
* Return shortcode attributes, see \WPBakeryShortCode::output
* @return array
* @since 4.4
*/
public function getAtts() {
return $this->atts;
}
/**
* Creates html before shortcode html.
*
* @param $atts - shortcode attributes list
* @param $content - shortcode content
*
* @return string - html which will be displayed before shortcode html.
*/
public function beforeShortcode( $atts, $content ) {
return '';
}
/**
* Creates html before shortcode html.
*
* @param $atts - shortcode attributes list
* @param $content - shortcode content
*
* @return string - html which will be displayed after shortcode html.
*/
public function afterShortcode( $atts, $content ) {
return '';
}
/**
* @param $el_class
*
* @return string
*/
public function getExtraClass( $el_class ) {
$output = '';
if ( '' !== $el_class ) {
$output = ' ' . str_replace( '.', '', $el_class );
}
return $output;
}
/**
* @param $css_animation
*
* @return string
*/
public function getCSSAnimation( $css_animation ) {
$output = '';
if ( '' !== $css_animation && 'none' !== $css_animation ) {
wp_enqueue_script( 'vc_waypoints' );
wp_enqueue_style( 'vc_animate-css' );
$output = ' wpb_animate_when_almost_visible wpb_' . $css_animation . ' ' . $css_animation;
}
return $output;
}
/**
* Create HTML comment for blocks only if wpb_debug=true
*
* @param $string
*
* @return string
* @deprecated 4.7 For debug type html comments use more generic debugComment function.
*
*/
public function endBlockComment( $string ) {
return '';
}
/**
* if wpb_debug=true return HTML comment
*
* @param string $comment
*
* @return string
* @since 4.7
* @deprecated 5.5 no need for extra info in output, use xdebug
*/
public function debugComment( $comment ) {
return '';
}
/**
* @param $name
*
* @return null
*/
public function settings( $name ) {
return isset( $this->settings[ $name ] ) ? $this->settings[ $name ] : null;
}
/**
* @param $name
* @param $value
*/
public function setSettings( $name, $value ) {
$this->settings[ $name ] = $value;
}
/**
* @return mixed
* @since 5.5
*/
public function getSettings() {
return $this->settings;
}
/**
* @param $width
*
* @return string
* @throws \Exception
*/
public function getElementHolder( $width ) {
$output = '';
$column_controls = $this->getColumnControlsModular();
$sortable = ( vc_user_access_check_shortcode_all( $this->shortcode ) ? 'wpb_sortable' : $this->nonDraggableClass );
$css_class = 'wpb_' . $this->settings['base'] . ' wpb_content_element ' . $sortable . '' . ( ! empty( $this->settings['class'] ) ? ' ' . $this->settings['class'] : '' );
$output .= '<div data-element_type="' . $this->settings['base'] . '" class="' . $css_class . '">';
$output .= str_replace( '%column_size%', wpb_translateColumnWidthToFractional( $width ), $column_controls );
$output .= $this->getCallbacks( $this->shortcode );
$output .= '<div class="wpb_element_wrapper ' . $this->settings( 'wrapper_class' ) . '">';
$output .= '%wpb_element_content%';
$output .= '</div>';
$output .= '</div>';
return $output;
}
// Return block controls
/**
* @param $controls
* @param string $extended_css
*
* @return string
* @throws \Exception
*/
public function getColumnControls( $controls, $extended_css = '' ) {
$controls_start = '<div class="vc_controls controls_element' . ( ! empty( $extended_css ) ? " {$extended_css}" : '' ) . '">';
$controls_end = '</div>';
$controls_add = '';
$controls_edit = ' <a class="vc_control column_edit" href="javascript:;" title="' . sprintf( esc_attr__( 'Edit %s', 'js_composer' ), strtolower( $this->settings( 'name' ) ) ) . '"><span class="vc_icon"></span></a>';
$controls_delete = ' <a class="vc_control column_clone" href="javascript:;" title="' . sprintf( esc_attr__( 'Clone %s', 'js_composer' ), strtolower( $this->settings( 'name' ) ) ) . '"><span class="vc_icon"></span></a> <a class="column_delete" href="javascript:;" title="' . sprintf( esc_attr__( 'Delete %s', 'js_composer' ), strtolower( $this->settings( 'name' ) ) ) . '"><span class="vc_icon"></span></a>';
$column_controls_full = $controls_start . $controls_add . $controls_edit . $controls_delete . $controls_end;
$column_controls_size_delete = $controls_start . $controls_delete . $controls_end;
$column_controls_popup_delete = $controls_start . $controls_delete . $controls_end;
$column_controls_edit_popup_delete = $controls_start . $controls_edit . $controls_delete . $controls_end;
$column_controls_edit = $controls_start . $controls_edit . $controls_end;
$editAccess = vc_user_access_check_shortcode_edit( $this->shortcode );
$allAccess = vc_user_access_check_shortcode_all( $this->shortcode );
if ( 'popup_delete' === $controls ) {
return $allAccess ? $column_controls_popup_delete : '';
} elseif ( 'edit_popup_delete' === $controls ) {
return $allAccess ? $column_controls_edit_popup_delete : ( $editAccess ? $column_controls_edit : '' );
} elseif ( 'size_delete' === $controls ) {
return $allAccess ? $column_controls_size_delete : '';
} elseif ( 'add' === $controls ) {
return $allAccess ? ( $controls_start . $controls_add . $controls_end ) : '';
} else {
return $allAccess ? $column_controls_full : ( $editAccess ? $column_controls_edit : '' );
}
}
/**
* Return list of controls
* @return array
* @throws \Exception
*/
public function getControlsList() {
$editAccess = vc_user_access_check_shortcode_edit( $this->shortcode );
$allAccess = vc_user_access_check_shortcode_all( $this->shortcode );
if ( $allAccess ) {
return apply_filters( 'vc_wpbakery_shortcode_get_controls_list', $this->controls_list, $this->shortcode );
} else {
$controls = apply_filters( 'vc_wpbakery_shortcode_get_controls_list', $this->controls_list, $this->shortcode );
if ( $editAccess ) {
foreach ( $controls as $key => $value ) {
if ( 'edit' !== $value && 'add' !== $value ) {
unset( $controls[ $key ] );
}
}
return $controls;
} else {
return in_array( 'add', $controls, true ) ? array( 'add' ) : array();
}
}
}
/**
* Build new modern controls for shortcode.
*
* @param string $extended_css
*
* @return string
* @throws \Exception
*/
public function getColumnControlsModular( $extended_css = '' ) {
ob_start();
vc_include_template( apply_filters( 'vc_wpbakery_shortcode_get_column_controls_modular_template', $this->controls_template_file ), array(
'shortcode' => $this->shortcode,
'position' => $this->controls_css_settings,
'extended_css' => $extended_css,
'name' => $this->settings( 'name' ),
'controls' => $this->getControlsList(),
'name_css_class' => $this->getBackendEditorControlsElementCssClass(),
'add_allowed' => $this->getAddAllowed(),
) );
return ob_get_clean();
}
/**
* @return string
* @throws \Exception
*/
public function getBackendEditorControlsElementCssClass() {
$moveAccess = vc_user_access()->part( 'dragndrop' )->checkStateAny( true, null )->get();
$sortable = ( vc_user_access_check_shortcode_all( $this->shortcode ) && $moveAccess ? ' vc_element-move' : ' ' . $this->nonDraggableClass );
return 'vc_control-btn vc_element-name' . $sortable;
}
/**
* This will fire callbacks if they are defined in map.php
*
* @param $id
*
* @return string
*/
public function getCallbacks( $id ) {
$output = '';
if ( isset( $this->settings['js_callback'] ) ) {
foreach ( $this->settings['js_callback'] as $text_val => $val ) {
// TODO: name explain
$output .= '<input type="hidden" class="wpb_vc_callback wpb_vc_' . esc_attr( $text_val ) . '_callback " name="' . esc_attr( $text_val ) . '" value="' . $val . '" />';
}
}
return $output;
}
/**
* @param $param
* @param $value
*
* vc_filter: vc_wpbakeryshortcode_single_param_html_holder_value - hook to override param value (param type and etc is available in args)
*
* @return string
*/
public function singleParamHtmlHolder( $param, $value ) {
$value = apply_filters( 'vc_wpbakeryshortcode_single_param_html_holder_value', $value, $param, $this->settings, $this->atts );
$output = '';
// Compatibility fixes
$old_names = array(
'yellow_message',
'blue_message',
'green_message',
'button_green',
'button_grey',
'button_yellow',
'button_blue',
'button_red',
'button_orange',
);
$new_names = array(
'alert-block',
'alert-info',
'alert-success',
'btn-success',
'btn',
'btn-info',
'btn-primary',
'btn-danger',
'btn-warning',
);
$value = str_ireplace( $old_names, $new_names, $value );
$param_name = isset( $param['param_name'] ) ? $param['param_name'] : '';
$type = isset( $param['type'] ) ? $param['type'] : '';
$class = isset( $param['class'] ) ? $param['class'] : '';
if ( ! empty( $param['holder'] ) ) {
if ( 'input' === $param['holder'] ) {
$output .= '<' . $param['holder'] . ' readonly="true" class="wpb_vc_param_value ' . $param_name . ' ' . $type . ' ' . $class . '" name="' . $param_name . '" value="' . $value . '">';
} elseif ( in_array( $param['holder'], array(
'img',
'iframe',
), true ) ) {
$output .= '<' . $param['holder'] . ' class="wpb_vc_param_value ' . $param_name . ' ' . $type . ' ' . $class . '" name="' . $param_name . '" src="' . esc_url( $value ) . '">';
} elseif ( 'hidden' !== $param['holder'] ) {
$output .= '<' . $param['holder'] . ' class="wpb_vc_param_value ' . $param_name . ' ' . $type . ' ' . $class . '" name="' . $param_name . '">' . $value . '</' . $param['holder'] . '>';
}
}
if ( ! empty( $param['admin_label'] ) && true === $param['admin_label'] ) {
$output .= '<span class="vc_admin_label admin_label_' . $param['param_name'] . ( empty( $value ) ? ' hidden-label' : '' ) . '"><label>' . $param['heading'] . '</label>: ' . $value . '</span>';
}
return $output;
}
/**
* @param $params
*
* @return string
*/
protected function getIcon( $params ) {
$data = '';
if ( isset( $params['is_container'] ) && true === $params['is_container'] ) {
$data = ' data-is-container="true"';
}
$title = '';
if ( isset( $params['title'] ) ) {
$title = 'title="' . esc_attr( $params['title'] ) . '" ';
}
return '<i ' . $title . 'class="vc_general vc_element-icon' . ( ! empty( $params['icon'] ) ? ' ' . sanitize_text_field( $params['icon'] ) : '' ) . '"' . $data . '></i> ';
}
/**
* @param $title
*
* @return string
*/
protected function outputTitle( $title ) {
$icon = $this->settings( 'icon' );
if ( filter_var( $icon, FILTER_VALIDATE_URL ) ) {
$icon = '';
}
$params = array(
'icon' => $icon,
'is_container' => $this->settings( 'is_container' ),
);
return '<h4 class="wpb_element_title"> ' . $this->getIcon( $params ) . esc_attr( $title ) . '</h4>';
}
/**
* @param string $content
*
* @return string
* @throws \Exception
*/
public function template( $content = '' ) {
return $this->contentAdmin( $this->atts, $content );
}
/**
* This functions prepares attributes to use in template
* Converts back escaped characters
*
* @param $atts
*
* @return array
*/
protected function prepareAtts( $atts ) {
$returnAttributes = array();
if ( is_array( $atts ) ) {
foreach ( $atts as $key => $val ) {
$returnAttributes[ $key ] = str_replace( array(
'`{`',
'`}`',
'``',
), array(
'[',
']',
'"',
), $val );
}
}
return apply_filters( 'vc_shortcode_prepare_atts', $returnAttributes, $this->shortcode, $this->settings );
}
/**
* @return string
*/
public function getShortcode() {
return $this->shortcode;
}
/**
* Since 4.5
* Possible placeholders:
* {{ content }}
* {{ title }}
* {{ container-class }}
*
* Possible keys:
* {{
* <%
* %
* @param $markup
* @param string $content
*
* @return string
* @throws \Exception
* @since 4.5
*/
protected function customMarkup( $markup, $content = '' ) {
$pattern = '/\{\{([\s\S][^\n]+?)\}\}|<%([\s\S][^\n]+?)%>|%([\s\S][^\n]+?)%/';
preg_match_all( $pattern, $markup, $matches, PREG_SET_ORDER );
if ( is_array( $matches ) && ! empty( $matches ) ) {
foreach ( $matches as $match ) {
switch ( strtolower( trim( $match[1] ) ) ) {
case 'content':
if ( '' !== $content ) {
$markup = str_replace( $match[0], $content, $markup );
} elseif ( isset( $this->settings['default_content_in_template'] ) && '' !== $this->settings['default_content_in_template'] ) {
$markup = str_replace( $match[0], $this->settings['default_content_in_template'], $markup );
} else {
$markup = str_replace( $match[0], '', $markup );
}
break;
case 'title':
$markup = str_replace( $match[0], $this->outputTitle( $this->settings['name'] ), $markup );
break;
case 'container-class':
if ( method_exists( $this, 'containerContentClass' ) ) {
$markup = str_replace( $match[0], $this->containerContentClass(), $markup );
} else {
$markup = str_replace( $match[0], '', $markup );
}
break;
case 'editor_controls':
$markup = str_replace( $match[0], $this->getColumnControls( $this->settings( 'controls' ) ), $markup );
break;
case 'editor_controls_bottom_add':
$markup = str_replace( $match[0], $this->getColumnControls( 'add', 'bottom-controls' ), $markup );
break;
}
}
}
return do_shortcode( $markup );
}
/**
* @param $atts
*
* @return string
*/
protected function paramsHtmlHolders( $atts ) {
$inner = '';
if ( isset( $this->settings['params'] ) && is_array( $this->settings['params'] ) ) {
foreach ( $this->settings['params'] as $param ) {
$param_value = isset( $atts[ $param['param_name'] ] ) ? $atts[ $param['param_name'] ] : '';
$inner .= $this->singleParamHtmlHolder( $param, $param_value );
}
}
return $inner;
}
/**
* Check is allowed to add another element inside current element.
*
* @return bool
* @since 4.8
*
*/
public function getAddAllowed() {
return true;
}
}

View File

@@ -0,0 +1,182 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Class WPBakeryShortCodesContainer
*/
abstract class WPBakeryShortCodesContainer extends WPBakeryShortCode {
/**
* @var array
*/
protected $predefined_atts = array();
protected $backened_editor_prepend_controls = true;
/**
* @return string
*/
public function customAdminBlockParams() {
return '';
}
/**
* @param $width
* @param $i
*
* @return string
* @throws \Exception
*/
public function mainHtmlBlockParams( $width, $i ) {
$sortable = ( vc_user_access_check_shortcode_all( $this->shortcode ) ? 'wpb_sortable' : $this->nonDraggableClass );
return 'data-element_type="' . esc_attr( $this->settings['base'] ) . '" class="wpb_' . esc_attr( $this->settings['base'] ) . ' ' . esc_attr( $sortable ) . '' . ( ! empty( $this->settings['class'] ) ? ' ' . esc_attr( $this->settings['class'] ) : '' ) . ' wpb_content_holder vc_shortcodes_container"' . $this->customAdminBlockParams();
}
/**
* @param $width
* @param $i
*
* @return string
*/
public function containerHtmlBlockParams( $width, $i ) {
return 'class="' . $this->containerContentClass() . '"';
}
/**
*
* @return string
*/
public function containerContentClass() {
return 'wpb_column_container vc_container_for_children vc_clearfix';
}/** @noinspection PhpMissingParentCallCommonInspection */
/**
* @param string $controls
* @param string $extended_css
*
* @return string
* @throws \Exception
*/
public function getColumnControls( $controls = 'full', $extended_css = '' ) {
$controls_html = array();
$controls_html['start'] = '<div class="vc_controls vc_controls-visible controls_column' . ( ! empty( $extended_css ) ? " {$extended_css}" : '' ) . '">';
$controls_html['end'] = '</div>';
if ( 'bottom-controls' === $extended_css ) {
$controls_html['title'] = sprintf( esc_attr__( 'Append to this %s', 'js_composer' ), strtolower( $this->settings( 'name' ) ) );
} else {
$controls_html['title'] = sprintf( esc_attr__( 'Prepend to this %s', 'js_composer' ), strtolower( $this->settings( 'name' ) ) );
}
$controls_html['move'] = '<a class="vc_control column_move vc_column-move" data-vc-control="move" href="#" title="' . sprintf( esc_attr__( 'Move this %s', 'js_composer' ), strtolower( $this->settings( 'name' ) ) ) . '"><i class="vc-composer-icon vc-c-icon-dragndrop"></i></a>';
$moveAccess = vc_user_access()->part( 'dragndrop' )->checkStateAny( true, null )->get();
if ( ! $moveAccess ) {
$controls_html['move'] = '';
}
$controls_html['add'] = '<a class="vc_control column_add" data-vc-control="add" href="#" title="' . $controls_html['title'] . '"><i class="vc-composer-icon vc-c-icon-add"></i></a>';
$controls_html['edit'] = '<a class="vc_control column_edit" data-vc-control="edit" href="#" title="' . sprintf( esc_html__( 'Edit this %s', 'js_composer' ), strtolower( $this->settings( 'name' ) ) ) . '"><i class="vc-composer-icon vc-c-icon-mode_edit"></i></a>';
$controls_html['clone'] = '<a class="vc_control column_clone" data-vc-control="clone" href="#" title="' . sprintf( esc_html__( 'Clone this %s', 'js_composer' ), strtolower( $this->settings( 'name' ) ) ) . '"><i class="vc-composer-icon vc-c-icon-content_copy"></i></a>';
$controls_html['delete'] = '<a class="vc_control column_delete" data-vc-control="delete" href="#" title="' . sprintf( esc_html__( 'Delete this %s', 'js_composer' ), strtolower( $this->settings( 'name' ) ) ) . '"><i class="vc-composer-icon vc-c-icon-delete_empty"></i></a>';
$controls_html['full'] = $controls_html['move'] . $controls_html['add'] . $controls_html['edit'] . $controls_html['clone'] . $controls_html['delete'];
$editAccess = vc_user_access_check_shortcode_edit( $this->shortcode );
$allAccess = vc_user_access_check_shortcode_all( $this->shortcode );
if ( ! empty( $controls ) ) {
if ( is_string( $controls ) ) {
$controls = array( $controls );
}
$controls_string = $controls_html['start'];
foreach ( $controls as $control ) {
if ( ( $editAccess && 'edit' === $control ) || $allAccess ) {
if ( isset( $controls_html[ $control ] ) ) {
$controls_string .= $controls_html[ $control ];
}
}
}
return $controls_string . $controls_html['end'];
}
if ( $allAccess ) {
return $controls_html['start'] . $controls_html['full'] . $controls_html['end'];
} elseif ( $editAccess ) {
return $controls_html['start'] . $controls_html['edit'] . $controls_html['end'];
}
return $controls_html['start'] . $controls_html['end'];
}
/**
* @param $atts
* @param null $content
*
* @return string
* @throws \Exception
*/
public function contentAdmin( $atts, $content = null ) {
$width = '';
$atts = shortcode_atts( $this->predefined_atts, $atts );
extract( $atts );
$this->atts = $atts;
$output = '';
$output .= '<div ' . $this->mainHtmlBlockParams( $width, 1 ) . '>';
if ( $this->backened_editor_prepend_controls ) {
$output .= $this->getColumnControls( $this->settings( 'controls' ) );
}
$output .= '<div class="wpb_element_wrapper">';
if ( isset( $this->settings['custom_markup'] ) && '' !== $this->settings['custom_markup'] ) {
$markup = $this->settings['custom_markup'];
$output .= $this->customMarkup( $markup );
} else {
$output .= $this->outputTitle( $this->settings['name'] );
$output .= '<div ' . $this->containerHtmlBlockParams( $width, 1 ) . '>';
$output .= do_shortcode( shortcode_unautop( $content ) );
$output .= '</div>';
$output .= $this->paramsHtmlHolders( $atts );
}
$output .= '</div>';
if ( $this->backened_editor_prepend_controls ) {
$output .= $this->getColumnControls( 'add', 'bottom-controls' );
}
$output .= '</div>';
return $output;
}
/**
* @param $title
*
* @return string
*/
protected function outputTitle( $title ) {
$icon = $this->settings( 'icon' );
if ( filter_var( $icon, FILTER_VALIDATE_URL ) ) {
$icon = '';
}
$params = array(
'icon' => $icon,
'is_container' => $this->settings( 'is_container' ),
'title' => $title,
);
return '<h4 class="wpb_element_title"> ' . $this->getIcon( $params ) . '</h4>';
}
/**
* @return string
*/
/**
* @return string
*/
public function getBackendEditorChildControlsElementCssClass() {
return 'vc_element-name';
}
}

View File

@@ -0,0 +1,10 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Class WPBakeryShortCode_Layerslider_Vc
*/
class WPBakeryShortCode_Layerslider_Vc extends WPBakeryShortCode {
}

View File

@@ -0,0 +1,133 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Class Vc_Pageable
*/
class WPBakeryShortCode_Vc_Pageable extends WPBakeryShortCode {
/**
* @param $settings
*/
public function __construct( $settings ) {
parent::__construct( $settings );
$this->shortcodeScripts();
}
/**
* Register scripts and styles for pager
*/
public function shortcodeScripts() {
wp_register_script( 'vc_pageable_owl-carousel', vc_asset_url( 'lib/owl-carousel2-dist/owl.carousel.min.js' ), array(
'jquery',
), WPB_VC_VERSION, true );
wp_register_script( 'vc_waypoints', vc_asset_url( 'lib/vc_waypoints/vc-waypoints.min.js' ), array( 'jquery' ), WPB_VC_VERSION, true );
wp_register_style( 'vc_pageable_owl-carousel-css', vc_asset_url( 'lib/owl-carousel2-dist/assets/owl.min.css' ), array(), WPB_VC_VERSION );
}
/**
* @param $grid_style
* @param $settings
* @param $content
*
* @return string
*/
protected function contentAll( $grid_style, $settings, $content ) {
return '<div class="vc_pageable-slide-wrapper vc_clearfix" data-vc-grid-content="true">' . $content . '</div>';
}
/**
* @param $grid_style
* @param $settings
* @param $content
*
* @return string
*/
protected function contentLoadMore( $grid_style, $settings, $content ) {
if ( ! isset( $settings['btn_data'] ) && isset( $settings['button_style'] ) && isset( $settings['button_size'] ) && isset( $settings['button_color'] ) ) {
// BC: for those who overrided
$output = sprintf( '<div class="vc_pageable-slide-wrapper vc_clearfix" data-vc-grid-content="true">%s</div><div class="vc_pageable-load-more-btn" data-vc-grid-load-more-btn="true">%s</div>', $content, do_shortcode( '[vc_button2 size="' . $settings['button_size'] . '" title="' . esc_attr__( 'Load more', 'js_composer' ) . '" style="' . $settings['button_style'] . '" color="' . $settings['button_color'] . '" el_class="vc_grid-btn-load_more"]' ) );
return $output;
} elseif ( isset( $settings['btn_data'] ) ) {
$data = $settings['btn_data'];
$data['el_class'] = 'vc_grid-btn-load_more';
$data['link'] = 'load-more-grid';
$button3 = new WPBakeryShortCode_Vc_Btn( array( 'base' => 'vc_btn' ) );
$output = sprintf( '<div class="vc_pageable-slide-wrapper vc_clearfix" data-vc-grid-content="true">%s</div><div class="vc_pageable-load-more-btn" data-vc-grid-load-more-btn="true">%s</div>', $content, apply_filters( 'vc_gitem_template_attribute_vc_btn', '', array(
'post' => new stdClass(),
'data' => str_replace( array(
'{{ vc_btn:',
'}}',
), '', $button3->output( $data ) ),
) ) );
return $output;
}
return '';
}
/**
* @param $grid_style
* @param $settings
* @param $content
*
* @return string
*/
protected function contentLazy( $grid_style, $settings, $content ) {
return '<div class="vc_pageable-slide-wrapper vc_clearfix" data-vc-grid-content="true">' . $content . '</div><div data-lazy-loading-btn="true" style="display: none;"><a href="' . esc_url( get_permalink( $settings['page_id'] ) ) . '"></a></div>';
}
/**
* @param $grid_style
* @param $settings
* @param string $content
*
* @param string $css_class
*
* @return string
*/
public function renderPagination( $grid_style, $settings, $content = '', $css_class = '' ) {
$css_class .= empty( $css_class ) ? '' : ' vc_pageable-wrapper vc_hook_hover';
$content_method = vc_camel_case( 'content-' . $grid_style );
$content = method_exists( $this, $content_method ) ? $this->$content_method( $grid_style, $settings, $content ) : $content;
$output = '<div class="' . esc_attr( $css_class ) . '" data-vc-pageable-content="true">' . $content . '</div>';
return $output;
}
public function enqueueScripts() {
wp_enqueue_script( 'vc_pageable_owl-carousel' );
wp_enqueue_style( 'vc_pageable_owl-carousel-css' );
wp_enqueue_style( 'vc_animate-css' );
}
/**
* Check is pageable
* @return bool
* @since 4.7.4
*/
public function isObjectPageable() {
return true;
}
/**
* Check can user manage post.
*
* @param int $page_id
*
* @return bool
*/
public function currentUserCanManage( $page_id ) {
return vc_user_access()->wpAny( array(
'edit_post',
(int) $page_id,
) )->get();
}
}

View File

@@ -0,0 +1,10 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Class WPBakeryShortCode_Rev_Slider_Vc
*/
class WPBakeryShortCode_Rev_Slider_Vc extends WPBakeryShortCode {
}

View File

@@ -0,0 +1,151 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
require_once vc_path_dir( 'SHORTCODES_DIR', 'vc-tab.php' );
/**
* Class WPBakeryShortCode_VC_Accordion_tab
*/
class WPBakeryShortCode_VC_Accordion_Tab extends WPBakeryShortCode_VC_Tab {
/**
* @var string
*/
protected $controls_css_settings = 'tc vc_control-container';
/**
* @var array
*/
protected $controls_list = array(
'add',
'edit',
'clone',
'delete',
);
/**
* @var string
*/
public $nonDraggableClass = 'vc-non-draggable-container';
/**
* @param $atts
* @param null $content
* @return string
* @throws \Exception
*/
public function contentAdmin( $atts, $content = null ) {
$width = '';
// @codingStandardsIgnoreLine
extract( vc_map_get_attributes( $this->getShortcode(), $atts ) );
$output = '';
$column_controls = $this->getColumnControls( $this->settings( 'controls' ) );
$column_controls_bottom = $this->getColumnControls( 'add', 'bottom-controls' );
if ( 'column_14' === $width || '1/4' === $width ) {
$width = array( 'vc_col-sm-3' );
} elseif ( 'column_14-14-14-14' === $width ) {
$width = array(
'vc_col-sm-3',
'vc_col-sm-3',
'vc_col-sm-3',
'vc_col-sm-3',
);
} elseif ( 'column_13' === $width || '1/3' === $width ) {
$width = array( 'vc_col-sm-4' );
} elseif ( 'column_13-23' === $width ) {
$width = array(
'vc_col-sm-4',
'vc_col-sm-8',
);
} elseif ( 'column_13-13-13' === $width ) {
$width = array(
'vc_col-sm-4',
'vc_col-sm-4',
'vc_col-sm-4',
);
} elseif ( 'column_12' === $width || '1/2' === $width ) {
$width = array( 'vc_col-sm-6' );
} elseif ( 'column_12-12' === $width ) {
$width = array(
'vc_col-sm-6',
'vc_col-sm-6',
);
} elseif ( 'column_23' === $width || '2/3' === $width ) {
$width = array( 'vc_col-sm-8' );
} elseif ( 'column_34' === $width || '3/4' === $width ) {
$width = array( 'vc_col-sm-9' );
} elseif ( 'column_16' === $width || '1/6' === $width ) {
$width = array( 'vc_col-sm-2' );
} else {
$width = array( '' );
}
$sortable = ( vc_user_access_check_shortcode_all( $this->shortcode ) ? 'wpb_sortable' : $this->nonDraggableClass );
$count = count( $width );
for ( $i = 0; $i < $count; $i ++ ) {
$output .= '<div class="group ' . $sortable . '">';
$output .= '<h3><span class="tab-label"><%= params.title %></span></h3>';
$output .= '<div ' . $this->mainHtmlBlockParams( $width, $i ) . '>';
$output .= str_replace( '%column_size%', wpb_translateColumnWidthToFractional( $width[ $i ] ), $column_controls );
$output .= '<div class="wpb_element_wrapper">';
$output .= '<div ' . $this->containerHtmlBlockParams( $width, $i ) . '>';
$output .= do_shortcode( shortcode_unautop( $content ) );
$output .= '</div>';
if ( isset( $this->settings['params'] ) ) {
$inner = '';
foreach ( $this->settings['params'] as $param ) {
$param_value = isset( ${$param['param_name']} ) ? ${$param['param_name']} : '';
if ( is_array( $param_value ) ) {
// Get first element from the array
reset( $param_value );
$first_key = key( $param_value );
$param_value = $param_value[ $first_key ];
}
$inner .= $this->singleParamHtmlHolder( $param, $param_value );
}
$output .= $inner;
}
$output .= '</div>';
$output .= str_replace( '%column_size%', wpb_translateColumnWidthToFractional( $width[ $i ] ), $column_controls_bottom );
$output .= '</div>';
$output .= '</div>';
}
return $output;
}
/**
* @param $width
* @param $i
* @return string
*/
public function mainHtmlBlockParams( $width, $i ) {
return 'data-element_type="' . esc_attr( $this->settings['base'] ) . '" class=" wpb_' . esc_attr( $this->settings['base'] ) . '"' . $this->customAdminBlockParams();
}
/**
* @param $width
* @param $i
* @return string
*/
public function containerHtmlBlockParams( $width, $i ) {
return 'class="wpb_column_container vc_container_for_children"';
}
/**
* @param $title
* @return string
*/
protected function outputTitle( $title ) {
return '';
}
/**
* @return string
*/
public function customAdminBlockParams() {
return '';
}
}

View File

@@ -0,0 +1,63 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* WPBakery WPBakery Page Builder shortcodes
*
* @package WPBakeryPageBuilder
*
*/
class WPBakeryShortCode_Vc_Accordion extends WPBakeryShortCode {
protected $controls_css_settings = 'out-tc vc_controls-content-widget';
/**
* @param $atts
* @param null $content
* @return mixed|string
* @throws \Exception
*/
public function contentAdmin( $atts, $content = null ) {
$width = $custom_markup = '';
$shortcode_attributes = array( 'width' => '1/1' );
foreach ( $this->settings['params'] as $param ) {
if ( 'content' !== $param['param_name'] ) {
$shortcode_attributes[ $param['param_name'] ] = isset( $param['value'] ) ? $param['value'] : null;
} elseif ( 'content' === $param['param_name'] && null === $content ) {
$content = $param['value'];
}
}
extract( shortcode_atts( $shortcode_attributes, $atts ) );
$elem = $this->getElementHolder( $width );
$inner = '';
foreach ( $this->settings['params'] as $param ) {
$param_value = isset( ${$param['param_name']} ) ? ${$param['param_name']} : '';
if ( is_array( $param_value ) ) {
// Get first element from the array
reset( $param_value );
$first_key = key( $param_value );
$param_value = $param_value[ $first_key ];
}
$inner .= $this->singleParamHtmlHolder( $param, $param_value );
}
$tmp = '';
if ( isset( $this->settings['custom_markup'] ) && '' !== $this->settings['custom_markup'] ) {
if ( '' !== $content ) {
$custom_markup = str_ireplace( '%content%', $tmp . $content, $this->settings['custom_markup'] );
} elseif ( '' === $content && isset( $this->settings['default_content_in_template'] ) && '' !== $this->settings['default_content_in_template'] ) {
$custom_markup = str_ireplace( '%content%', $this->settings['default_content_in_template'], $this->settings['custom_markup'] );
} else {
$custom_markup = str_ireplace( '%content%', '', $this->settings['custom_markup'] );
}
$inner .= do_shortcode( $custom_markup );
}
$output = str_ireplace( '%wpb_element_content%', $inner, $elem );
return $output;
}
}

View File

@@ -0,0 +1,588 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
require_once vc_path_dir( 'SHORTCODES_DIR', 'paginator/class-vc-pageable.php' );
require_once vc_path_dir( 'SHORTCODES_DIR', 'vc-btn.php' );
/**
* Class WPBakeryShortCode_Vc_Basic_Grid
*/
class WPBakeryShortCode_Vc_Basic_Grid extends WPBakeryShortCode_Vc_Pageable {
public $pagable_type = 'grid';
public $items = array();
public static $excluded_ids = array();
protected $element_template = '';
protected static $default_max_items = 1000;
public $post_id = false;
/** @var \Vc_Grid_Item $grid_item */
public $grid_item = false;
protected $filter_terms;
public $attributes_defaults = array(
'initial_loading_animation' => 'zoomIn',
'full_width' => '',
'layout' => '',
'element_width' => '4',
'items_per_page' => '5',
'gap' => '',
'style' => 'all',
'show_filter' => '',
'filter_default_title' => 'all',
'exclude_filter' => '',
'filter_style' => '',
'filter_size' => 'md',
'filter_align' => '',
'filter_color' => '',
'arrows_design' => '',
'arrows_position' => '',
'arrows_color' => '',
'paging_design' => '',
'paging_color' => '',
'paging_animation_in' => '',
'paging_animation_out' => '',
'loop' => '',
'autoplay' => '',
'post_type' => 'post',
'filter_source' => 'category',
'orderby' => '',
'order' => 'DESC',
// @codingStandardsIgnoreLine
'meta_key' => '',
'max_items' => '10',
'offset' => '0',
'taxonomies' => '',
'custom_query' => '',
'data_type' => 'query',
'include' => '',
'exclude' => '',
'item' => 'none',
'grid_id' => '',
// disabled, needed for-BC:
'button_style' => '',
'button_color' => '',
'button_size' => '',
// New button3:
'btn_title' => '',
'btn_style' => 'modern',
'btn_el_id' => '',
'btn_custom_background' => '#ededed',
'btn_custom_text' => '#666',
'btn_outline_custom_color' => '#666',
'btn_outline_custom_hover_background' => '#666',
'btn_outline_custom_hover_text' => '#fff',
'btn_shape' => 'rounded',
'btn_color' => 'blue',
'btn_size' => 'md',
'btn_align' => 'inline',
'btn_button_block' => '',
'btn_add_icon' => '',
'btn_i_align' => 'left',
'btn_i_type' => 'fontawesome',
'btn_i_icon_fontawesome' => 'fa fa-adjust',
'btn_i_icon_openiconic' => 'vc-oi vc-oi-dial',
'btn_i_icon_typicons' => 'typcn typcn-adjust-brightness',
'btn_i_icon_entypo' => 'entypo-icon entypo-icon-note',
'btn_i_icon_linecons' => 'vc_li vc_li-heart',
'btn_i_icon_pixelicons' => 'vc_pixel_icon vc_pixel_icon-alert',
'btn_custom_onclick' => '',
'btn_custom_onclick_code' => '',
// fix template
'page_id' => '',
);
protected $grid_settings = array();
protected $grid_id_unique_name = 'vc_gid'; // if you change this also change in hook-vc-grid.php
/**
* @var \WP_Query
*/
protected $query;
/**
* WPBakeryShortCode_Vc_Basic_Grid constructor.
* @param $settings
*/
public function __construct( $settings ) {
parent::__construct( $settings );
$this->attributes_defaults['btn_title'] = esc_html__( 'Load more', 'js_composer' );
$this->shortcodeScripts();
}
public function shortcodeScripts() {
parent::shortcodeScripts();
wp_register_script( 'vc_grid-js-imagesloaded', vc_asset_url( 'lib/bower/imagesloaded/imagesloaded.pkgd.min.js' ), array( 'jquery' ), WPB_VC_VERSION, true );
wp_register_script( 'vc_grid', vc_asset_url( 'js/dist/vc_grid.min.js' ), array(
'jquery',
'underscore',
'vc_pageable_owl-carousel',
'vc_waypoints',
// 'isotope',
'vc_grid-js-imagesloaded',
), WPB_VC_VERSION, true );
}
public function enqueueScripts() {
parent::enqueueScripts();
wp_enqueue_script( 'vc_grid-js-imagesloaded' );
wp_enqueue_script( 'vc_grid' );
}
/**
* @param $id
*/
public static function addExcludedId( $id ) {
self::$excluded_ids[] = $id;
}
/**
* @return array
*/
public static function excludedIds() {
return self::$excluded_ids;
}
/**
* @param $atts
* @param $content
* @return false|mixed|string|void
*/
public function getId( $atts, $content ) {
if ( vc_is_page_editable() || is_preview() ) {
/*
* We are in Frontend editor
* We need to send RAW shortcode data, so hash is just json_encode of atts and content
*/
return rawurlencode( wp_json_encode( array(
'tag' => $this->shortcode,
'atts' => $atts,
'content' => $content,
) ) );
}
$id_pattern = '/' . $this->grid_id_unique_name . '\:([\w\-_]+)/';
$id_value = isset( $atts['grid_id'] ) ? $atts['grid_id'] : '';
preg_match( $id_pattern, $id_value, $id_matches );
$id_to_save = wp_json_encode( array( 'failed_to_get_id' => esc_attr( $id_value ) ) );
if ( ! empty( $id_matches ) ) {
$id_to_save = $id_matches[1];
}
return $id_to_save;
}
/**
* @param $page_id
* @param $grid_id
* @return array|mixed|object|void
*/
public function findPostShortcodeById( $page_id, $grid_id ) {
if ( $this->currentUserCanManage( $page_id ) && preg_match( '/\"tag\"\:/', urldecode( $grid_id ) ) ) {
return json_decode( urldecode( $grid_id ), true ); // if frontend, no hash exists - just RAW data
}
$post_meta = get_post_meta( (int) $page_id, '_vc_post_settings' );
$shortcode = false;
if ( is_array( $post_meta ) ) {
foreach ( $post_meta as $meta ) {
if ( isset( $meta['vc_grid_id'] ) && ! empty( $meta['vc_grid_id']['shortcodes'] ) && isset( $meta['vc_grid_id']['shortcodes'][ $grid_id ] ) ) {
$shortcode = $meta['vc_grid_id']['shortcodes'][ $grid_id ];
break;
}
}
}
return apply_filters( 'vc_basic_grid_find_post_shortcode', $shortcode, $page_id, $grid_id );
}
/**
* @return string
* @throws \Exception
*/
public function renderItems() {
$output = '';
$items = '';
$this->buildGridSettings();
$atts = $this->atts;
$settings = $this->grid_settings;
$filter_terms = $this->filter_terms;
$is_end = isset( $this->is_end ) && $this->is_end;
$css_classes = 'vc_grid vc_row' . esc_attr( $atts['gap'] > 0 ? ' vc_grid-gutter-' . (int) $atts['gap'] . 'px' : '' );
$currentScope = WPBMap::getScope();
if ( is_array( $this->items ) && ! empty( $this->items ) ) {
// Adding before vc_map
WPBMap::setScope( Vc_Grid_Item_Editor::postType() );
require_once vc_path_dir( 'PARAMS_DIR', 'vc_grid_item/class-vc-grid-item.php' );
$this->grid_item = new Vc_Grid_Item();
$this->grid_item->setGridAttributes( $atts );
$this->grid_item->setIsEnd( $is_end );
$this->grid_item->setTemplateById( $atts['item'] );
$output .= $this->grid_item->addShortcodesCustomCss();
ob_start();
if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
wp_print_styles();
}
$output .= ob_get_clean();
$attributes = array(
'filter_terms' => $filter_terms,
'atts' => $atts,
'grid_item',
$this->grid_item,
);
$output .= apply_filters( 'vc_basic_grid_template_filter', vc_get_template( 'shortcodes/vc_basic_grid_filter.php', $attributes ), $attributes );
global $post;
$backup = $post;
foreach ( $this->items as $postItem ) {
$this->query->setup_postdata( $postItem );
// @codingStandardsIgnoreLine
$post = $postItem;
$items .= $this->grid_item->renderItem( $postItem );
}
wp_reset_postdata();
$post = $backup;
} else {
return '';
}
$items = apply_filters( $this->shortcode . '_items_list', $items );
$output .= $this->renderPagination( $atts['style'], $settings, $items, $css_classes );
WPBMap::setScope( $currentScope );
return $output;
}
public function setContentLimits() {
$atts = $this->atts;
if ( 'ids' === $this->atts['post_type'] ) {
$this->atts['max_items'] = 0;
$this->atts['offset'] = 0;
$this->atts['items_per_page'] = apply_filters( 'vc_basic_grid_max_items', self::$default_max_items );
} else {
$offset = isset( $atts['offset'] ) ? (int) $atts['offset'] : $this->attributes_defaults['offset'];
$this->atts['offset'] = $offset;
$this->atts['max_items'] = isset( $atts['max_items'] ) ? (int) $atts['max_items'] : (int) $this->attributes_defaults['max_items'];
$this->atts['items_per_page'] = ! isset( $atts['items_per_page'] ) ? (int) $this->attributes_defaults['items_per_page'] : (int) $atts['items_per_page'];
if ( $this->atts['max_items'] < 1 ) {
$this->atts['max_items'] = apply_filters( 'vc_basic_grid_max_items', self::$default_max_items );
}
}
$this->setPagingAll( $this->atts['max_items'] );
}
/**
* @param $max_items
*/
protected function setPagingAll( $max_items ) {
$atts = $this->atts;
$this->atts['query_items_per_page'] = $max_items > 0 ? $max_items : apply_filters( 'vc_basic_grid_items_per_page_all_max_items', self::$default_max_items );
$this->atts['items_per_page'] = $this->atts['query_items_per_page'];
$this->atts['query_offset'] = isset( $atts['offset'] ) ? (int) $atts['offset'] : $this->attributes_defaults['offset'];
}
/**
* @param $vc_request_param
* @return false|mixed|string|void
* @throws \Exception
*/
public function renderAjax( $vc_request_param ) {
$this->items = array(); // clear this items array (if used more than once);
$id = isset( $vc_request_param['shortcode_id'] ) ? $vc_request_param['shortcode_id'] : false;
$shortcode = false;
if ( ! isset( $vc_request_param['page_id'] ) ) {
return wp_json_encode( array( 'status' => 'Nothing found' ) );
}
if ( $id ) {
$shortcode = $this->findPostShortcodeById( $vc_request_param['page_id'], $id );
}
if ( ! is_array( $shortcode ) ) {
return wp_json_encode( array( 'status' => 'Nothing found' ) );
}
visual_composer()->registerAdminCss();
visual_composer()->registerAdminJavascript();
// Set post id
$this->post_id = (int) $vc_request_param['page_id'];
$shortcode_atts = $shortcode['atts'];
$this->shortcode_content = $shortcode['content'];
$this->buildAtts( $shortcode_atts, $shortcode['content'] );
$this->buildItems();
return $this->renderItems();
}
/**
* @return bool|false|int
*/
public function postID() {
if ( ! $this->post_id ) {
$this->post_id = get_the_ID();
}
return $this->post_id;
}
/**
* @param $atts
* @param $content
* @throws \Exception
*/
public function buildAtts( $atts, $content ) {
$this->post_id = false;
$this->grid_settings = array();
$this->filter_terms = null;
$this->items = array();
$arr_keys = array_keys( $atts );
$count = count( $atts );
for ( $i = 0; $i < $count; $i ++ ) {
$atts[ $arr_keys[ $i ] ] = html_entity_decode( $atts[ $arr_keys[ $i ] ], ENT_QUOTES, 'utf-8' );
}
if ( isset( $atts['grid_id'] ) && ! empty( $atts['grid_id'] ) ) {
$id_to_save = $this->getId( $atts, $content );
}
$atts = $this->convertButton2ToButton3( $atts );
$atts = shortcode_atts( $this->attributes_defaults, vc_map_get_attributes( $this->getShortcode(), $atts ) );
$this->atts = $atts;
if ( isset( $id_to_save ) ) {
$this->atts['shortcode_id'] = $id_to_save;
}
$this->atts['page_id'] = $this->postID();
$this->element_template = $content;
// @since 4.4.3
if ( 'custom' === $this->attr( 'post_type' ) ) {
$this->atts['style'] = 'all';
}
}
/**
* Getter attribute.
*
* @param $key
*
* @return mixed|null
*/
public function attr( $key ) {
return isset( $this->atts[ $key ] ) ? $this->atts[ $key ] : null;
}
public function buildGridSettings() {
$this->grid_settings = array(
'page_id' => $this->atts['page_id'],
// used in basic grid for initialization
'style' => $this->atts['style'],
'action' => 'vc_get_vc_grid_data',
);
// used in ajax request for items
if ( isset( $this->atts['shortcode_id'] ) && ! empty( $this->atts['shortcode_id'] ) ) {
$this->grid_settings['shortcode_id'] = $this->atts['shortcode_id'];
} elseif ( isset( $this->atts['shortcode_hash'] ) && ! empty( $this->atts['shortcode_hash'] ) ) {
// @deprecated since 4.4.3
$this->grid_settings['shortcode_hash'] = $this->atts['shortcode_hash'];
}
if ( 'load-more' === $this->atts['style'] ) {
$this->grid_settings = array_merge( $this->grid_settings, array(
// used in dispaly style load more button, lazy, pagination
'items_per_page' => $this->atts['items_per_page'],
'btn_data' => vc_map_integrate_parse_atts( $this->shortcode, 'vc_btn', $this->atts, 'btn_' ),
) );
} elseif ( 'lazy' === $this->atts['style'] ) {
$this->grid_settings = array_merge( $this->grid_settings, array(
'items_per_page' => $this->atts['items_per_page'],
) );
} elseif ( 'pagination' === $this->atts['style'] ) {
$this->grid_settings = array_merge( $this->grid_settings, array(
'items_per_page' => $this->atts['items_per_page'],
// used in pagination style
'auto_play' => $this->atts['autoplay'] > 0 ? true : false,
'gap' => (int) $this->atts['gap'],
// not used yet, but can be used in isotope..
'speed' => (int) $this->atts['autoplay'] * 1000,
'loop' => $this->atts['loop'],
'animation_in' => $this->atts['paging_animation_in'],
'animation_out' => $this->atts['paging_animation_out'],
'arrows_design' => $this->atts['arrows_design'],
'arrows_color' => $this->atts['arrows_color'],
'arrows_position' => $this->atts['arrows_position'],
'paging_design' => $this->atts['paging_design'],
'paging_color' => $this->atts['paging_color'],
) );
}
$this->grid_settings['tag'] = $this->shortcode;
}
// TODO: setter & getter to attributes
/**
* @param $atts
* @return array
*/
public function buildQuery( $atts ) {
// Set include & exclude
if ( 'ids' !== $atts['post_type'] && ! empty( $atts['exclude'] ) ) {
$atts['exclude'] .= ',' . implode( ',', $this->excludedIds() );
} else {
$atts['exclude'] = implode( ',', $this->excludedIds() );
}
if ( 'ids' !== $atts['post_type'] ) {
$settings = array(
'posts_per_page' => $atts['query_items_per_page'],
'offset' => $atts['query_offset'],
'orderby' => $atts['orderby'],
'order' => $atts['order'],
'meta_key' => in_array( $atts['orderby'], array(
'meta_value',
'meta_value_num',
), true ) ? $atts['meta_key'] : '',
'post_type' => $atts['post_type'],
'exclude' => $atts['exclude'],
);
if ( ! empty( $atts['taxonomies'] ) ) {
$vc_taxonomies_types = get_taxonomies( array( 'public' => true ) );
$terms = get_terms( array_keys( $vc_taxonomies_types ), array(
'hide_empty' => false,
'include' => $atts['taxonomies'],
) );
$settings['tax_query'] = array();
$tax_queries = array(); // List of taxnonimes
foreach ( $terms as $term ) {
if ( ! isset( $tax_queries[ $term->taxonomy ] ) ) {
$tax_queries[ $term->taxonomy ] = array(
'taxonomy' => $term->taxonomy,
'field' => 'id',
'terms' => array( $term->term_id ),
'relation' => 'IN',
);
} else {
$tax_queries[ $term->taxonomy ]['terms'][] = $term->term_id;
}
}
$settings['tax_query'] = array_values( $tax_queries );
$settings['tax_query']['relation'] = 'OR';
}
} else {
if ( empty( $atts['include'] ) ) {
$atts['include'] = - 1;
} elseif ( ! empty( $atts['exclude'] ) ) {
$include = array_map( 'trim', explode( ',', $atts['include'] ) );
$exclude = array_map( 'trim', explode( ',', $atts['exclude'] ) );
$diff = array_diff( $include, $exclude );
$atts['include'] = implode( ', ', $diff );
}
$settings = array(
'include' => $atts['include'],
'posts_per_page' => $atts['query_items_per_page'],
'offset' => $atts['query_offset'],
'post_type' => 'any',
'orderby' => 'post__in',
);
$this->atts['items_per_page'] = - 1;
}
return $settings;
}
public function buildItems() {
$this->filter_terms = $this->items = array();
$this->query = new WP_Query();
$this->setContentLimits();
$this->addExcludedId( $this->postID() );
if ( 'custom' === $this->atts['post_type'] && ! empty( $this->atts['custom_query'] ) ) {
$query = html_entity_decode( vc_value_from_safe( $this->atts['custom_query'] ), ENT_QUOTES, 'utf-8' );
$query = apply_filters( 'vc_basic_grid_filter_query_filters', $query, $this->atts, $this->shortcode );
$post_data = $this->query->query( $query );
$this->atts['items_per_page'] = - 1;
} elseif ( false !== $this->atts['query_items_per_page'] ) {
$settings = $this->filterQuerySettings( $this->buildQuery( $this->atts ) );
$post_data = $this->query->query( $settings );
} else {
return;
}
if ( $this->atts['items_per_page'] > 0 && count( $post_data ) > $this->atts['items_per_page'] ) {
$post_data = array_slice( $post_data, 0, $this->atts['items_per_page'] );
}
foreach ( $post_data as $post ) {
$post->filter_terms = wp_get_object_terms( $post->ID, $this->atts['filter_source'], array( 'fields' => 'ids' ) );
$this->filter_terms = wp_parse_args( $this->filter_terms, $post->filter_terms );
$this->items[] = $post;
}
}
/**
* @param $args
* @return array
*/
public function filterQuerySettings( $args ) {
$defaults = array(
'numberposts' => 5,
'offset' => 0,
'category' => 0,
'orderby' => 'date',
'order' => 'DESC',
'include' => array(),
'exclude' => array(),
'meta_key' => '',
'meta_value' => '',
'post_type' => 'post',
'suppress_filters' => apply_filters( 'vc_basic_grid_filter_query_suppress_filters', true ),
'public' => true,
);
$r = wp_parse_args( $args, $defaults );
if ( empty( $r['post_status'] ) ) {
$r['post_status'] = ( 'attachment' === $r['post_type'] ) ? 'inherit' : 'publish';
}
if ( ! empty( $r['numberposts'] ) && empty( $r['posts_per_page'] ) ) {
$r['posts_per_page'] = $r['numberposts'];
}
if ( ! empty( $r['category'] ) ) {
$r['cat'] = $r['category'];
}
if ( ! empty( $r['include'] ) ) {
$incposts = wp_parse_id_list( $r['include'] );
$r['posts_per_page'] = count( $incposts ); // only the number of posts included
$r['post__in'] = $incposts;
} elseif ( ! empty( $r['exclude'] ) ) {
$r['post__not_in'] = wp_parse_id_list( $r['exclude'] );
}
$r['ignore_sticky_posts'] = true;
$r['no_found_rows'] = true;
return $r;
}
/**
* @param $atts
* @return mixed
*/
public static function convertButton2ToButton3( $atts ) {
if ( isset( $atts['button_style'] ) || isset( $atts['button_size'] ) || isset( $atts['button_color'] ) ) {
// we use old button 2 attributes:
$style = isset( $atts['button_style'] ) ? $atts['button_style'] : 'rounded';
$size = isset( $atts['button_size'] ) ? $atts['button_size'] : 'md';
$color = isset( $atts['button_color'] ) ? $atts['button_color'] : 'blue';
$oldData = array(
'style' => $style,
'size' => $size,
'color' => str_replace( '_', '-', $color ),
);
// remove attributes on save
$atts['button_style'] = '';
$atts['button_size'] = '';
$atts['button_color'] = '';
$newData = WPBakeryShortCode_Vc_Btn::convertAttributesToButton3( $oldData );
foreach ( $newData as $key => $value ) {
$atts[ 'btn_' . $key ] = $value;
}
}
return $atts;
}
}

View File

@@ -0,0 +1,99 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* WPBakery WPBakery Page Builder shortcodes
*
* @package WPBakeryPageBuilder
*
*/
/**
* Class WPBakeryShortCode_Vc_Btn
* @since 4.5
*/
class WPBakeryShortCode_Vc_Btn extends WPBakeryShortCode {
/**
* @param $atts
* @return mixed
*/
public static function convertAttributesToButton3( $atts ) {
// size btn1 to size btn2
$btn1_sizes = array(
'wpb_regularsize',
'btn-large',
'btn-small',
'btn-mini',
);
if ( isset( $atts['size'] ) && in_array( $atts['size'], $btn1_sizes, true ) ) {
$atts['size'] = str_replace( $btn1_sizes, array(
'md',
'lg',
'sm',
'xs',
), $atts['size'] );
}
// Convert Btn1 href+target attributes to Btn2 `link` attribute
if ( ! isset( $atts['link'] ) && isset( $atts['href'] ) && strlen( $atts['href'] ) > 0 ) {
$link = $atts['href'];
$target = isset( $atts['target'] ) ? $atts['target'] : '';
$title = isset( $atts['title'] ) ? $atts['title'] : $link;
$atts['link'] = 'url:' . rawurlencode( $link ) . '|title:' . $title . ( strlen( $target ) > 0 ? '|target:' . rawurlencode( $target ) : '' );
}
if ( ( ! isset( $atts['add_icon'] ) || 'true' !== $atts['add_icon'] ) && isset( $atts['icon'] ) && strlen( $atts['icon'] ) > 0 && 'none' !== $atts['icon'] ) {
// old icon from btn1 is set, let's convert it to new btn
$atts['add_icon'] = 'true';
$atts['icon_type'] = 'pixelicons';
$atts['icon_align'] = 'right';
$atts['icon_pixelicons'] = 'vc_pixel_icon vc_pixel_icon-' . str_replace( 'wpb_', '', $atts['icon'] );
}
$haystack = array(
'rounded',
'square',
'round',
'outlined',
'square_outlined',
);
if ( isset( $atts['style'] ) && in_array( $atts['style'], $haystack, true ) ) {
switch ( $atts['style'] ) {
case 'rounded':
$atts['style'] = 'flat';
$atts['shape'] = 'rounded';
break;
case 'square':
$atts['style'] = 'flat';
$atts['shape'] = 'square';
break;
case 'round':
$atts['style'] = 'flat';
$atts['shape'] = 'round';
break;
case 'outlined':
$atts['style'] = 'outline';
break;
case 'square_outlined':
$atts['style'] = 'outline';
$atts['shape'] = 'square';
break;
}
}
return $atts;
}
/**
* @param $title
*
* @return string
* @since 4.5
*/
protected function outputTitle( $title ) {
$icon = $this->settings( 'icon' );
return '<h4 class="wpb_element_title"><span class="vc_general vc_element-icon vc_btn3-icon' . ( ! empty( $icon ) ? ' ' . $icon : '' ) . '"></span></h4>';
}
}

View File

@@ -0,0 +1,22 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* WPBakery WPBakery Page Builder shortcodes
*
* @package WPBakeryPageBuilder
*
*/
class WPBakeryShortCode_Vc_Button extends WPBakeryShortCode {
/**
* @param $title
* @return string
*/
protected function outputTitle( $title ) {
$icon = $this->settings( 'icon' );
return '<h4 class="wpb_element_title"><span class="vc_general vc_element-icon' . ( ! empty( $icon ) ? ' ' . esc_attr( $icon ) : '' ) . '"></span></h4>';
}
}

View File

@@ -0,0 +1,22 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* WPBakery WPBakery Page Builder shortcodes
*
* @package WPBakeryPageBuilder
*
*/
class WPBakeryShortCode_Vc_Button2 extends WPBakeryShortCode {
/**
* @param $title
* @return string
*/
protected function outputTitle( $title ) {
$icon = $this->settings( 'icon' );
return '<h4 class="wpb_element_title"><span class="vc_general vc_element-icon' . ( ! empty( $icon ) ? ' ' . esc_attr( $icon ) : '' ) . '"></span></h4>';
}
}

View File

@@ -0,0 +1,12 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
require_once vc_path_dir( 'SHORTCODES_DIR', 'vc-column.php' );
/**
* Class WPBakeryShortCode_Vc_Column_Inner
*/
class WPBakeryShortCode_Vc_Column_Inner extends WPBakeryShortCode_Vc_Column {
}

View File

@@ -0,0 +1,17 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Class WPBakeryShortCode_Vc_Column_Text
*/
class WPBakeryShortCode_Vc_Column_Text extends WPBakeryShortCode {
/**
* @param $title
* @return string
*/
protected function outputTitle( $title ) {
return '';
}
}

View File

@@ -0,0 +1,290 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* WPBakery WPBakery Page Builder shortcodes
*
* @package WPBakeryPageBuilder
*
*/
class WPBakeryShortCode_VC_Column extends WPBakeryShortCode {
/**
* @var string
*/
public $nonDraggableClass = 'vc-non-draggable-column';
/**
* @param $settings
*/
public function __construct( $settings ) {
parent::__construct( $settings );
$this->shortcodeScripts();
}
/**
*
*/
protected function shortcodeScripts() {
wp_register_script( 'vc_jquery_skrollr_js', vc_asset_url( 'lib/bower/skrollr/dist/skrollr.min.js' ), array( 'jquery' ), WPB_VC_VERSION, true );
wp_register_script( 'vc_youtube_iframe_api_js', 'https://www.youtube.com/iframe_api', array(), WPB_VC_VERSION, true );
}
/**
* @param $controls
* @param string $extended_css
*
* @return string
* @throws \Exception
*/
public function getColumnControls( $controls, $extended_css = '' ) {
$output = '<div class="vc_controls vc_control-column vc_controls-visible' . ( ! empty( $extended_css ) ? " {$extended_css}" : '' ) . '">';
$controls_end = '</div>';
if ( ' bottom-controls' === $extended_css ) {
$control_title = __( 'Append to this column', 'js_composer' );
} else {
$control_title = __( 'Prepend to this column', 'js_composer' );
}
if ( vc_user_access()->part( 'shortcodes' )->checkStateAny( true, 'custom', null )->get() ) {
$controls_add = '<a class="vc_control column_add vc_column-add" data-vc-control="add" href="#" title="' . $control_title . '"><i class="vc-composer-icon vc-c-icon-add"></i></a>';
} else {
$controls_add = '';
}
$controls_edit = '<a class="vc_control column_edit vc_column-edit" data-vc-control="edit" href="#" title="' . __( 'Edit this column', 'js_composer' ) . '"><i class="vc-composer-icon vc-c-icon-mode_edit"></i></a>';
$controls_delete = '<a class="vc_control column_delete vc_column-delete" data-vc-control="delete" href="#" title="' . __( 'Delete this column', 'js_composer' ) . '"><i class="vc-composer-icon vc-c-icon-delete_empty"></i></a>';
$editAccess = vc_user_access_check_shortcode_edit( $this->shortcode );
$allAccess = vc_user_access_check_shortcode_all( $this->shortcode );
if ( is_array( $controls ) && ! empty( $controls ) ) {
foreach ( $controls as $control ) {
if ( 'add' === $control || ( $editAccess && 'edit' === $control ) || $allAccess ) {
$method_name = vc_camel_case( 'output-editor-control-' . $control );
if ( method_exists( $this, $method_name ) ) {
$output .= $this->$method_name();
} else {
$control_var = 'controls_' . $control;
if ( isset( ${$control_var} ) ) {
$output .= ${$control_var};
}
}
}
}
return $output . $controls_end;
} elseif ( is_string( $controls ) && 'full' === $controls ) {
if ( $allAccess ) {
return $output . $controls_add . $controls_edit . $controls_delete . $controls_end;
} elseif ( $editAccess ) {
return $output . $controls_add . $controls_edit . $controls_end;
}
return $output . $controls_add . $controls_end;
} elseif ( is_string( $controls ) ) {
$control_var = 'controls_' . $controls;
if ( 'add' === $controls || ( $editAccess && 'edit' === $controls || $allAccess ) && isset( ${$control_var} ) ) {
return $output . ${$control_var} . $controls_end;
}
return $output . $controls_end;
}
if ( $allAccess ) {
return $output . $controls_add . $controls_edit . $controls_delete . $controls_end;
} elseif ( $editAccess ) {
return $output . $controls_add . $controls_edit . $controls_end;
}
return $output . $controls_add . $controls_end;
}
/**
* @param $param
* @param $value
*
* @return string
*/
public function singleParamHtmlHolder( $param, $value ) {
$output = '';
// Compatibility fixes.
$old_names = array(
'yellow_message',
'blue_message',
'green_message',
'button_green',
'button_grey',
'button_yellow',
'button_blue',
'button_red',
'button_orange',
);
$new_names = array(
'alert-block',
'alert-info',
'alert-success',
'btn-success',
'btn',
'btn-info',
'btn-primary',
'btn-danger',
'btn-warning',
);
$value = str_ireplace( $old_names, $new_names, $value );
$param_name = isset( $param['param_name'] ) ? $param['param_name'] : '';
$type = isset( $param['type'] ) ? $param['type'] : '';
$class = isset( $param['class'] ) ? $param['class'] : '';
if ( isset( $param['holder'] ) && 'hidden' !== $param['holder'] ) {
$output .= '<' . $param['holder'] . ' class="wpb_vc_param_value ' . $param_name . ' ' . $type . ' ' . $class . '" name="' . $param_name . '">' . $value . '</' . $param['holder'] . '>';
}
return $output;
}
/**
* @param $atts
* @param null $content
*
* @return string
*/
public function contentAdmin( $atts, $content = null ) {
$width = '';
$atts = vc_map_get_attributes( $this->getShortcode(), $atts );
// @codingStandardsIgnoreLine
extract( $atts );
$this->atts = $atts;
$output = '';
$column_controls = $this->getColumnControls( $this->settings( 'controls' ) );
$column_controls_bottom = $this->getColumnControls( 'add', 'bottom-controls' );
if ( 'column_14' === $width || '1/4' === $width ) {
$width = array( 'vc_col-sm-3' );
} elseif ( 'column_14-14-14-14' === $width ) {
$width = array(
'vc_col-sm-3',
'vc_col-sm-3',
'vc_col-sm-3',
'vc_col-sm-3',
);
} elseif ( 'column_13' === $width || '1/3' === $width ) {
$width = array( 'vc_col-sm-4' );
} elseif ( 'column_13-23' === $width ) {
$width = array(
'vc_col-sm-4',
'vc_col-sm-8',
);
} elseif ( 'column_13-13-13' === $width ) {
$width = array(
'vc_col-sm-4',
'vc_col-sm-4',
'vc_col-sm-4',
);
} elseif ( 'column_12' === $width || '1/2' === $width ) {
$width = array( 'vc_col-sm-6' );
} elseif ( 'column_12-12' === $width ) {
$width = array(
'vc_col-sm-6',
'vc_col-sm-6',
);
} elseif ( 'column_23' === $width || '2/3' === $width ) {
$width = array( 'vc_col-sm-8' );
} elseif ( 'column_34' === $width || '3/4' === $width ) {
$width = array( 'vc_col-sm-9' );
} elseif ( 'column_16' === $width || '1/6' === $width ) {
$width = array( 'vc_col-sm-2' );
} elseif ( ' column_56' === $width || ' 5/6' === $width ) {
$width = array( 'vc_col-sm-10' );
} else {
$width = array( '' );
}
$count = count( $width );
for ( $i = 0; $i < $count; $i ++ ) {
$output .= '<div ' . $this->mainHtmlBlockParams( $width, $i ) . '>';
$output .= str_replace( '%column_size%', wpb_translateColumnWidthToFractional( $width[ $i ] ), $column_controls );
$output .= '<div class="wpb_element_wrapper">';
$output .= '<div ' . $this->containerHtmlBlockParams( $width, $i ) . '>';
$output .= do_shortcode( shortcode_unautop( $content ) );
$output .= '</div>';
if ( isset( $this->settings['params'] ) ) {
$inner = '';
foreach ( $this->settings['params'] as $param ) {
$param_value = isset( ${$param['param_name']} ) ? ${$param['param_name']} : '';
if ( is_array( $param_value ) ) {
// Get first element from the array
reset( $param_value );
$first_key = key( $param_value );
$param_value = $param_value[ $first_key ];
}
$inner .= $this->singleParamHtmlHolder( $param, $param_value );
}
$output .= $inner;
}
$output .= '</div>';
$output .= str_replace( '%column_size%', wpb_translateColumnWidthToFractional( $width[ $i ] ), $column_controls_bottom );
$output .= '</div>';
}
return $output;
}
/**
* @return string
*/
public function customAdminBlockParams() {
return '';
}
/**
* @param $width
* @param $i
*
* @return string
* @throws \Exception
*/
public function mainHtmlBlockParams( $width, $i ) {
$sortable = ( vc_user_access_check_shortcode_all( $this->shortcode ) ? 'wpb_sortable' : $this->nonDraggableClass );
return 'data-element_type="' . $this->settings['base'] . '" data-vc-column-width="' . wpb_vc_get_column_width_indent( $width[ $i ] ) . '" class="wpb_' . $this->settings['base'] . ' ' . $sortable . '' . ( ! empty( $this->settings['class'] ) ? ' ' . $this->settings['class'] : '' ) . ' ' . $this->templateWidth() . ' wpb_content_holder"' . $this->customAdminBlockParams();
}
/**
* @param $width
* @param $i
*
* @return string
*/
public function containerHtmlBlockParams( $width, $i ) {
return 'class="wpb_column_container vc_container_for_children"';
}
/**
* @param string $content
*
* @return string
*/
public function template( $content = '' ) {
return $this->contentAdmin( $this->atts );
}
/**
* @return string
*/
protected function templateWidth() {
return '<%= window.vc_convert_column_size(params.width) %>';
}
/**
* @param string $font_color
*
* @return string
*/
public function buildStyle( $font_color = '' ) {
$style = '';
if ( ! empty( $font_color ) ) {
$style .= vc_get_css_color( 'color', $font_color );
}
return empty( $style ) ? $style : ' style="' . esc_attr( $style ) . '"';
}
}

View File

@@ -0,0 +1,13 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* WPBakery WPBakery Page Builder shortcodes
*
* @package WPBakeryPageBuilder
*
*/
class WPBakeryShortCode_Vc_Cta_Button extends WPBakeryShortCode {
}

View File

@@ -0,0 +1,13 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* WPBakery WPBakery Page Builder shortcodes
*
* @package WPBakeryPageBuilder
*
*/
class WPBakeryShortCode_Vc_Cta_Button2 extends WPBakeryShortCode {
}

View File

@@ -0,0 +1,179 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* WPBakery WPBakery Page Builder shortcodes
*
* @package WPBakeryPageBuilder
* @since 4.5
*/
/**
* @since 4.5
* Class WPBakeryShortCode_Vc_Cta
*/
class WPBakeryShortCode_Vc_Cta extends WPBakeryShortCode {
protected $template_vars = array();
/**
* @param $atts
* @param $content
* @throws \Exception
*/
public function buildTemplate( $atts, $content ) {
$output = array();
$inline_css = array();
$main_wrapper_classes = array( 'vc_cta3' );
$container_classes = array();
if ( ! empty( $atts['el_class'] ) ) {
$main_wrapper_classes[] = $atts['el_class'];
}
if ( ! empty( $atts['style'] ) ) {
$main_wrapper_classes[] = 'vc_cta3-style-' . $atts['style'];
}
if ( ! empty( $atts['shape'] ) ) {
$main_wrapper_classes[] = 'vc_cta3-shape-' . $atts['shape'];
}
if ( ! empty( $atts['txt_align'] ) ) {
$main_wrapper_classes[] = 'vc_cta3-align-' . $atts['txt_align'];
}
if ( ! empty( $atts['color'] ) && ! ( isset( $atts['style'] ) && 'custom' === $atts['style'] ) ) {
$main_wrapper_classes[] = 'vc_cta3-color-' . $atts['color'];
}
if ( isset( $atts['style'] ) && 'custom' === $atts['style'] ) {
if ( ! empty( $atts['custom_background'] ) ) {
$inline_css[] = vc_get_css_color( 'background-color', $atts['custom_background'] );
}
}
if ( ! empty( $atts['i_on_border'] ) ) {
$main_wrapper_classes[] = 'vc_cta3-icons-on-border';
}
if ( ! empty( $atts['i_size'] ) ) {
$main_wrapper_classes[] = 'vc_cta3-icon-size-' . $atts['i_size'];
}
if ( ! empty( $atts['i_background_style'] ) ) {
$main_wrapper_classes[] = 'vc_cta3-icons-in-box';
}
if ( ! empty( $atts['el_width'] ) ) {
$container_classes[] = 'vc_cta3-size-' . $atts['el_width'];
}
if ( ! empty( $atts['add_icon'] ) ) {
$output[ 'icons-' . $atts['add_icon'] ] = $this->getVcIcon( $atts );
$main_wrapper_classes[] = 'vc_cta3-icons-' . $atts['add_icon'];
}
if ( ! empty( $atts['add_button'] ) ) {
$output[ 'actions-' . $atts['add_button'] ] = $this->getButton( $atts );
$main_wrapper_classes[] = 'vc_cta3-actions-' . $atts['add_button'];
}
if ( ! empty( $atts['css_animation'] ) ) {
$main_wrapper_classes[] = $this->getCSSAnimation( $atts['css_animation'] );
}
if ( ! empty( $atts['css'] ) ) {
$main_wrapper_classes[] = vc_shortcode_custom_css_class( $atts['css'] );
}
$output['content'] = wpb_js_remove_wpautop( $content, true );
$output['heading1'] = $this->getHeading( 'h2', $atts );
$output['heading2'] = $this->getHeading( 'h4', $atts );
$output['css-class'] = $main_wrapper_classes;
$output['container-class'] = $container_classes;
$output['inline-css'] = $inline_css;
$this->template_vars = $output;
}
/**
* @param $tag
* @param $atts
* @return string
* @throws \Exception
*/
public function getHeading( $tag, $atts ) {
if ( isset( $atts[ $tag ] ) && '' !== trim( $atts[ $tag ] ) ) {
if ( isset( $atts[ 'use_custom_fonts_' . $tag ] ) && 'true' === $atts[ 'use_custom_fonts_' . $tag ] ) {
$custom_heading = visual_composer()->getShortCode( 'vc_custom_heading' );
$data = vc_map_integrate_parse_atts( $this->shortcode, 'vc_custom_heading', $atts, $tag . '_' );
$data['font_container'] = implode( '|', array_filter( array(
'tag:' . $tag,
$data['font_container'],
) ) );
$data['text'] = $atts[ $tag ]; // provide text to shortcode
return $custom_heading->render( array_filter( $data ) );
} else {
$inline_css = array();
$inline_css_string = '';
if ( isset( $atts['style'] ) && 'custom' === $atts['style'] ) {
if ( ! empty( $atts['custom_text'] ) ) {
$inline_css[] = vc_get_css_color( 'color', $atts['custom_text'] );
}
}
if ( ! empty( $inline_css ) ) {
$inline_css_string = ' style="' . implode( '', $inline_css ) . '"';
}
return '<' . $tag . $inline_css_string . '>' . $atts[ $tag ] . '</' . $tag . '>';
}
}
return '';
}
/**
* @param $atts
* @return string
* @throws \Exception
*/
public function getButton( $atts ) {
$data = vc_map_integrate_parse_atts( $this->shortcode, 'vc_btn', $atts, 'btn_' );
if ( $data ) {
$btn = visual_composer()->getShortCode( 'vc_btn' );
if ( is_object( $btn ) ) {
return '<div class="vc_cta3-actions">' . $btn->render( array_filter( $data ) ) . '</div>';
}
}
return '';
}
/**
* @param $atts
* @return string
* @throws \Exception
*/
public function getVcIcon( $atts ) {
if ( empty( $atts['i_type'] ) ) {
$atts['i_type'] = 'fontawesome';
}
$data = vc_map_integrate_parse_atts( $this->shortcode, 'vc_icon', $atts, 'i_' );
if ( $data ) {
$icon = visual_composer()->getShortCode( 'vc_icon' );
if ( is_object( $icon ) ) {
return '<div class="vc_cta3-icons">' . $icon->render( array_filter( $data ) ) . '</div>';
}
}
return '';
}
/**
* @param $string
* @return mixed|string
*/
public function getTemplateVariable( $string ) {
if ( is_array( $this->template_vars ) && isset( $this->template_vars[ $string ] ) ) {
return $this->template_vars[ $string ];
}
return '';
}
}

View File

@@ -0,0 +1,13 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* WPBakery WPBakery Page Builder shortcodes
*
* @package WPBakeryPageBuilder
*
*/
class WPBakeryShortCode_Vc_Custom_Field extends WPBakeryShortCode {
}

View File

@@ -0,0 +1,159 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Class WPBakeryShortCode_Vc_Custom_heading
* @since 4.3
*/
class WPBakeryShortCode_Vc_Custom_Heading extends WPBakeryShortCode {
/**
* Defines fields names for google_fonts, font_container and etc
* @since 4.4
* @var array
*/
protected $fields = array(
'google_fonts' => 'google_fonts',
'font_container' => 'font_container',
'el_class' => 'el_class',
'css' => 'css',
'text' => 'text',
);
/**
* Used to get field name in vc_map function for google_fonts, font_container and etc..
*
* @param $key
*
* @return bool
* @since 4.4
*/
protected function getField( $key ) {
return isset( $this->fields[ $key ] ) ? $this->fields[ $key ] : false;
}
/**
* Get param value by providing key
*
* @param $key
*
* @return array|bool
* @throws \Exception
* @since 4.4
*/
protected function getParamData( $key ) {
return WPBMap::getParam( $this->shortcode, $this->getField( $key ) );
}
/**
* Parses shortcode attributes and set defaults based on vc_map function relative to shortcode and fields names
*
* @param $atts
*
* @return array
* @throws \Exception
* @since 4.3
*/
public function getAttributes( $atts ) {
/**
* Shortcode attributes
* @var $text
* @var $google_fonts
* @var $font_container
* @var $el_class
* @var $link
* @var $css
*/
$atts = vc_map_get_attributes( $this->getShortcode(), $atts );
extract( $atts );
/**
* Get default values from VC_MAP.
*/
$google_fonts_field = $this->getParamData( 'google_fonts' );
$font_container_field = $this->getParamData( 'font_container' );
$el_class = $this->getExtraClass( $el_class );
$font_container_obj = new Vc_Font_Container();
$google_fonts_obj = new Vc_Google_Fonts();
$font_container_field_settings = isset( $font_container_field['settings'], $font_container_field['settings']['fields'] ) ? $font_container_field['settings']['fields'] : array();
$google_fonts_field_settings = isset( $google_fonts_field['settings'], $google_fonts_field['settings']['fields'] ) ? $google_fonts_field['settings']['fields'] : array();
$font_container_data = $font_container_obj->_vc_font_container_parse_attributes( $font_container_field_settings, $font_container );
$google_fonts_data = strlen( $google_fonts ) > 0 ? $google_fonts_obj->_vc_google_fonts_parse_attributes( $google_fonts_field_settings, $google_fonts ) : '';
return array(
'text' => isset( $text ) ? $text : '',
'google_fonts' => $google_fonts,
'font_container' => $font_container,
'el_class' => $el_class,
'css' => isset( $css ) ? $css : '',
'link' => ( 0 === strpos( $link, '|' ) ) ? false : $link,
'font_container_data' => $font_container_data,
'google_fonts_data' => $google_fonts_data,
);
}
/**
* Parses google_fonts_data and font_container_data to get needed css styles to markup
*
* @param $el_class
* @param $css
* @param $google_fonts_data
* @param $font_container_data
* @param $atts
*
* @return array
* @since 4.3
*/
public function getStyles( $el_class, $css, $google_fonts_data, $font_container_data, $atts ) {
$styles = array();
if ( ! empty( $font_container_data ) && isset( $font_container_data['values'] ) ) {
foreach ( $font_container_data['values'] as $key => $value ) {
if ( 'tag' !== $key && strlen( $value ) ) {
if ( preg_match( '/description/', $key ) ) {
continue;
}
if ( 'font_size' === $key || 'line_height' === $key ) {
$value = preg_replace( '/\s+/', '', $value );
}
if ( 'font_size' === $key ) {
$pattern = '/^(\d*(?:\.\d+)?)\s*(px|\%|in|cm|mm|em|rem|ex|pt|pc|vw|vh|vmin|vmax)?$/';
// allowed metrics: http://www.w3schools.com/cssref/css_units.asp
preg_match( $pattern, $value, $matches );
$value = isset( $matches[1] ) ? (float) $matches[1] : (float) $value;
$unit = isset( $matches[2] ) ? $matches[2] : 'px';
$value = $value . $unit;
}
if ( strlen( $value ) > 0 ) {
$styles[] = str_replace( '_', '-', $key ) . ': ' . $value;
}
}
}
}
if ( ( ! isset( $atts['use_theme_fonts'] ) || 'yes' !== $atts['use_theme_fonts'] ) && ! empty( $google_fonts_data ) && isset( $google_fonts_data['values'], $google_fonts_data['values']['font_family'], $google_fonts_data['values']['font_style'] ) ) {
$google_fonts_family = explode( ':', $google_fonts_data['values']['font_family'] );
$styles[] = 'font-family:' . $google_fonts_family[0];
$google_fonts_styles = explode( ':', $google_fonts_data['values']['font_style'] );
$styles[] = 'font-weight:' . $google_fonts_styles[1];
$styles[] = 'font-style:' . $google_fonts_styles[2];
}
/**
* Filter 'VC_SHORTCODE_CUSTOM_CSS_FILTER_TAG' to change vc_custom_heading class
*
* @param string - filter_name
* @param string - element_class
* @param string - shortcode_name
* @param array - shortcode_attributes
*
* @since 4.3
*/
$css_class = apply_filters( VC_SHORTCODE_CUSTOM_CSS_FILTER_TAG, 'vc_custom_heading ' . $el_class . vc_shortcode_custom_css_class( $css, ' ' ), $this->settings['base'], $atts );
return array(
'css_class' => trim( preg_replace( '/\s+/', ' ', $css_class ) ),
'styles' => $styles,
);
}
}

View File

@@ -0,0 +1,10 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Class WPBakeryShortCode_Vc_Empty_space
*/
class WPBakeryShortCode_Vc_Empty_Space extends WPBakeryShortCode {
}

View File

@@ -0,0 +1,42 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Class WPBakeryShortCode_Vc_Facebook
*/
class WPBakeryShortCode_Vc_Facebook extends WPBakeryShortCode {
/**
* @param $atts
* @param null $content
* @return string
* @throws \Exception
*/
protected function contentInline( $atts, $content = null ) {
/**
* Shortcode attributes
* @var $atts
* @var $type
* @var $el_class
* @var $css
* @var $css_animation
* Shortcode class
* @var WPBakeryShortCode_Vc_Facebook $this
*/
$type = $css = $el_class = '';
$atts = vc_map_get_attributes( $this->getShortcode(), $atts );
extract( $atts );
$url = get_permalink();
$css = isset( $atts['css'] ) ? $atts['css'] : '';
$el_class = isset( $atts['el_class'] ) ? $atts['el_class'] : '';
$class_to_filter = 'wpb_googleplus vc_social-placeholder wpb_content_element vc_socialtype-' . $type;
$class_to_filter .= vc_shortcode_custom_css_class( $css, ' ' ) . $this->getExtraClass( $el_class ) . $this->getCSSAnimation( $css_animation );
$css_class = apply_filters( VC_SHORTCODE_CUSTOM_CSS_FILTER_TAG, $class_to_filter, $this->settings['base'], $atts );
return '<a href="' . esc_url( $url ) . '" class="' . esc_attr( $css_class ) . '"></a>';
}
}

View File

@@ -0,0 +1,62 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Class WPBakeryShortCode_Vc_flickr
*/
class WPBakeryShortCode_Vc_Flickr extends WPBakeryShortCode {
/**
* @param $atts
* @param null $content
* @return string
* @throws \Exception
*/
protected function contentInline( $atts, $content = null ) {
/**
* Shortcode attributes
* @var $atts
* @var $el_class
* @var $title
* @var $flickr_id
* @var $count
* @var $type
* @var $display
* @var $css
* @var $css_animation
* Shortcode class
* @var WPBakeryShortCode_Vc_flickr $this
*/
$title = '';
$flickr_id = '';
$css_animation = '';
$count = '';
$type = '';
$display = '';
$atts = vc_map_get_attributes( $this->getShortcode(), $atts );
extract( $atts );
$css = isset( $atts['css'] ) ? $atts['css'] : '';
$el_class = isset( $atts['el_class'] ) ? $atts['el_class'] : '';
$class_to_filter = 'wpb_flickr_widget wpb_content_element';
$class_to_filter .= vc_shortcode_custom_css_class( $css, ' ' ) . $this->getExtraClass( $el_class ) . $this->getCSSAnimation( $css_animation );
$css_class = apply_filters( VC_SHORTCODE_CUSTOM_CSS_FILTER_TAG, $class_to_filter, $this->settings['base'], $atts );
$params = array(
'title' => $title,
'extraclass' => 'wpb_flickr_heading',
);
$output = sprintf( '
<div class="%s">
<div class="wpb_wrapper">
%s
<div class="vc_flickr-inline-placeholder" data-link="https://www.flickr.com/badge_code_v2.gne?count=%s&amp;display=%s&amp;size=s&amp;layout=x&amp;source=%s&amp;%s=%s"></div>
<p class="flickr_stream_wrap"><a class="wpb_follow_btn wpb_flickr_stream" href="https://www.flickr.com/photos/%s">%s</a></p>
</div>
</div>', $css_class, wpb_widget_title( $params ), $count, $display, $type, $type, $flickr_id, $flickr_id, esc_html__( 'View stream on flickr', 'js_composer' ) );
return $output;
}
}

View File

@@ -0,0 +1,79 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Class WPBakeryShortCode_Vc_gallery
*/
class WPBakeryShortCode_Vc_Gallery extends WPBakeryShortCode {
/**
* WPBakeryShortCode_Vc_gallery constructor.
* @param $settings
*/
public function __construct( $settings ) {
parent::__construct( $settings );
$this->shortcodeScripts();
}
public function shortcodeScripts() {
wp_register_script( 'vc_grid-js-imagesloaded', vc_asset_url( 'lib/bower/imagesloaded/imagesloaded.pkgd.min.js' ), array( 'jquery' ), WPB_VC_VERSION, true );
}
/**
* @param $param
* @param $value
* @return string
*/
public function singleParamHtmlHolder( $param, $value ) {
$output = '';
// Compatibility fixes
$old_names = array(
'yellow_message',
'blue_message',
'green_message',
'button_green',
'button_grey',
'button_yellow',
'button_blue',
'button_red',
'button_orange',
);
$new_names = array(
'alert-block',
'alert-info',
'alert-success',
'btn-success',
'btn',
'btn-info',
'btn-primary',
'btn-danger',
'btn-warning',
);
$value = str_ireplace( $old_names, $new_names, $value );
$param_name = isset( $param['param_name'] ) ? $param['param_name'] : '';
$type = isset( $param['type'] ) ? $param['type'] : '';
$class = isset( $param['class'] ) ? $param['class'] : '';
if ( isset( $param['holder'] ) && 'hidden' !== $param['holder'] ) {
$output .= '<' . $param['holder'] . ' class="wpb_vc_param_value ' . $param_name . ' ' . $type . ' ' . $class . '" name="' . $param_name . '">' . $value . '</' . $param['holder'] . '>';
}
if ( 'images' === $param_name ) {
$images_ids = empty( $value ) ? array() : explode( ',', trim( $value ) );
$output .= '<ul class="attachment-thumbnails' . ( empty( $images_ids ) ? ' image-exists' : '' ) . '" data-name="' . $param_name . '">';
foreach ( $images_ids as $image ) {
$img = wpb_getImageBySize( array(
'attach_id' => (int) $image,
'thumb_size' => 'thumbnail',
) );
$output .= ( $img ? '<li>' . $img['thumbnail'] . '</li>' : '<li><img width="150" height="150" test="' . $image . '" src="' . esc_url( vc_asset_url( 'vc/blank.gif' ) ) . '" class="attachment-thumbnail" alt="" title="" /></li>' );
}
$output .= '</ul>';
$output .= '<a href="#" class="column_edit_trigger' . ( ! empty( $images_ids ) ? ' image-exists' : '' ) . '">' . esc_html__( 'Add images', 'js_composer' ) . '</a>';
}
return $output;
}
}

View File

@@ -0,0 +1,56 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
require_once vc_path_dir( 'SHORTCODES_DIR', 'vc-gitem.php' );
/**
* Class WPBakeryShortCode_Vc_Gitem_Animated_Block
*/
class WPBakeryShortCode_Vc_Gitem_Animated_Block extends WPBakeryShortCode_Vc_Gitem {
protected static $animations = array();
/**
* @return string
*/
public function itemGrid() {
$output = '';
$output .= '<div class="vc_gitem-animated-block-content-controls">' . '<ul class="vc_gitem-tabs vc_clearfix" data-vc-gitem-animated-block="tabs">' . '</ul>' . '</div>';
$output .= '' . '<div class="vc_gitem-zone-tab vc_clearfix" data-vc-gitem-animated-block="add-a"></div>' . '<div class="vc_gitem-zone-tab vc_clearfix" data-vc-gitem-animated-block="add-b"></div>';
return $output;
}
/**
* @param $width
* @param $i
* @return string
*/
public function containerHtmlBlockParams( $width, $i ) {
return 'class="vc_gitem-animated-block-content"';
}
/**
* @return array
*/
public static function animations() {
return array(
esc_html__( 'Single block (no animation)', 'js_composer' ) => '',
esc_html__( 'Double block (no animation)', 'js_composer' ) => 'none',
esc_html__( 'Fade in', 'js_composer' ) => 'fadeIn',
esc_html__( 'Scale in', 'js_composer' ) => 'scaleIn',
esc_html__( 'Scale in with rotation', 'js_composer' ) => 'scaleRotateIn',
esc_html__( 'Blur out', 'js_composer' ) => 'blurOut',
esc_html__( 'Blur scale out', 'js_composer' ) => 'blurScaleOut',
esc_html__( 'Slide in from left', 'js_composer' ) => 'slideInRight',
esc_html__( 'Slide in from right', 'js_composer' ) => 'slideInLeft',
esc_html__( 'Slide bottom', 'js_composer' ) => 'slideBottom',
esc_html__( 'Slide top', 'js_composer' ) => 'slideTop',
esc_html__( 'Vertical flip in with fade', 'js_composer' ) => 'flipFadeIn',
esc_html__( 'Horizontal flip in with fade', 'js_composer' ) => 'flipHorizontalFadeIn',
esc_html__( 'Go top', 'js_composer' ) => 'goTop20',
esc_html__( 'Go bottom', 'js_composer' ) => 'goBottom20',
);
}
}

View File

@@ -0,0 +1,52 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
require_once vc_path_dir( 'SHORTCODES_DIR', 'vc-column.php' );
/**
* Class WPBakeryShortCode_Vc_Gitem_Col
*/
class WPBakeryShortCode_Vc_Gitem_Col extends WPBakeryShortCode_Vc_Column {
public $nonDraggableClass = 'vc-non-draggable-column';
/**
* @param $width
* @param $i
* @return string
* @throws \Exception
*/
public function mainHtmlBlockParams( $width, $i ) {
$sortable = ( vc_user_access_check_shortcode_all( $this->shortcode ) ? ' wpb_sortable ' : ' ' . $this->nonDraggableClass . ' ' );
return 'data-element_type="' . $this->settings['base'] . '" data-vc-column-width="' . wpb_vc_get_column_width_indent( $width[ $i ] ) . '" class="wpb_vc_column wpb_' . $this->settings['base'] . $sortable . $this->templateWidth() . ' wpb_content_holder"' . $this->customAdminBlockParams();
}
/**
* @return string
*/
public function outputEditorControlAlign() {
$alignment = array(
array(
'name' => 'left',
'label' => esc_html__( 'Left', 'js_composer' ),
),
array(
'name' => 'center',
'label' => esc_html__( 'Center', 'js_composer' ),
),
array(
'name' => 'right',
'label' => esc_html__( 'Right', 'js_composer' ),
),
);
$output = '<span class="vc_control vc_control-align"><span class="vc_control-wrap">';
foreach ( $alignment as $data ) {
$attr = esc_attr( $data['name'] );
$output .= sprintf( '<a href="#" data-vc-control-btn="align" data-vc-align="%s" class="vc_control vc_control-align-%s" title="%s"><i class="vc_icon vc_icon-align-%s"></i></a>', esc_attr( $attr ), $attr, esc_html( $data['label'] ), $attr );
}
return $output . '</span></span>';
}
}

View File

@@ -0,0 +1,22 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
require_once vc_path_dir( 'SHORTCODES_DIR', 'vc-custom-heading.php' );
/**
* Class WPBakeryShortCode_Vc_Gitem_Image
*/
class WPBakeryShortCode_Vc_Gitem_Image extends WPBakeryShortCode_Vc_Gitem_Post_Data {
/**
* Get data_source attribute value
*
* @param array $atts - list of shortcode attributes
*
* @return string
*/
public function getDataSource( array $atts ) {
return 'post_image';
}
}

View File

@@ -0,0 +1,18 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
require_once vc_path_dir( 'SHORTCODES_DIR', 'vc-gitem-post-data.php' );
/**
* Class WPBakeryShortCode_Vc_Gitem_Post_Author
*/
class WPBakeryShortCode_Vc_Gitem_Post_Author extends WPBakeryShortCode_Vc_Gitem_Post_Data {
/**
* @return mixed|string
*/
protected function getFileName() {
return 'vc_gitem_post_author';
}
}

View File

@@ -0,0 +1,18 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
require_once vc_path_dir( 'SHORTCODES_DIR', 'vc-gitem-post-data.php' );
/**
* Class WPBakeryShortCode_Vc_Gitem_Post_Categories
*/
class WPBakeryShortCode_Vc_Gitem_Post_Categories extends WPBakeryShortCode_Vc_Gitem_Post_Data {
/**
* @return mixed|string
*/
protected function getFileName() {
return 'vc_gitem_post_categories';
}
}

View File

@@ -0,0 +1,45 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
require_once vc_path_dir( 'SHORTCODES_DIR', 'vc-custom-heading.php' );
/**
* Class WPBakeryShortCode_Vc_Gitem_Post_Data
*/
class WPBakeryShortCode_Vc_Gitem_Post_Data extends WPBakeryShortCode_Vc_Custom_heading {
/**
* Get data_source attribute value
*
* @param array $atts - list of shortcode attributes
*
* @return string
*/
public function getDataSource( array $atts ) {
return isset( $atts['data_source'] ) ? $atts['data_source'] : 'post_title';
}
/**
* @param $atts
* @return array
* @throws \Exception
*/
public function getAttributes( $atts ) {
$atts = vc_map_get_attributes( $this->getShortcode(), $atts );
if ( isset( $atts['block_container'] ) && strlen( $atts['block_container'] ) > 0 ) {
if ( ! isset( $atts['font_container'] ) ) {
$atts['font_container'] = $atts['block_container'];
} else {
// merging two params into font_container
$atts['font_container'] .= '|' . $atts['block_container'];
}
}
$atts = parent::getAttributes( $atts );
if ( ! isset( $this->atts['use_custom_fonts'] ) || 'yes' !== $this->atts['use_custom_fonts'] ) {
$atts['google_fonts_data'] = array();
}
return $atts;
}
}

View File

@@ -0,0 +1,29 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
require_once vc_path_dir( 'SHORTCODES_DIR', 'vc-gitem-post-data.php' );
/**
* Class WPBakeryShortCode_Vc_Gitem_Post_Date
*/
class WPBakeryShortCode_Vc_Gitem_Post_Date extends WPBakeryShortCode_Vc_Gitem_Post_Data {
/**
* @return mixed|string
*/
protected function getFileName() {
return 'vc_gitem_post_data';
}
/**
* Get data_source attribute value
*
* @param array $atts - list of shortcode attributes
*
* @return string
*/
public function getDataSource( array $atts ) {
return isset( $atts['time'] ) && 'yes' === $atts['time'] ? 'post_datetime' : 'post_date';
}
}

View File

@@ -0,0 +1,29 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
require_once vc_path_dir( 'SHORTCODES_DIR', 'vc-gitem-post-data.php' );
/**
* Class WPBakeryShortCode_Vc_Gitem_Post_Excerpt
*/
class WPBakeryShortCode_Vc_Gitem_Post_Excerpt extends WPBakeryShortCode_Vc_Gitem_Post_Data {
/**
* @return mixed|string
*/
protected function getFileName() {
return 'vc_gitem_post_data';
}
/**
* Get data_source attribute value
*
* @param array $atts - list of shortcode attributes
*
* @return string
*/
public function getDataSource( array $atts ) {
return 'post_excerpt';
}
}

View File

@@ -0,0 +1,10 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Class WPBakeryShortCode_Vc_Gitem_Post_Meta
*/
class WPBakeryShortCode_Vc_Gitem_Post_Meta extends WPBakeryShortCode {
}

View File

@@ -0,0 +1,29 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
require_once vc_path_dir( 'SHORTCODES_DIR', 'vc-gitem-post-data.php' );
/**
* Class WPBakeryShortCode_Vc_Gitem_Post_title
*/
class WPBakeryShortCode_Vc_Gitem_Post_Title extends WPBakeryShortCode_Vc_Gitem_Post_Data {
/**
* @return mixed|string
*/
protected function getFileName() {
return 'vc_gitem_post_data';
}
/**
* Get data_source attribute value
*
* @param array $atts - list of shortcode attributes
*
* @return string
*/
public function getDataSource( array $atts ) {
return 'post_title';
}
}

View File

@@ -0,0 +1,25 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
require_once vc_path_dir( 'SHORTCODES_DIR', 'vc-row.php' );
/**
* Class WPBakeryShortCode_Vc_Gitem_Row
*/
class WPBakeryShortCode_Vc_Gitem_Row extends WPBakeryShortCode_Vc_Row {
/**
* @return string
*/
public function getLayoutsControl() {
global $vc_row_layouts;
$controls_layout = '<span class="vc_row_layouts vc_control">';
foreach ( array_slice( $vc_row_layouts, 0, 4 ) as $layout ) {
$controls_layout .= '<a class="vc_control-set-column set_columns" data-cells="' . $layout['cells'] . '" data-cells-mask="' . $layout['mask'] . '" title="' . $layout['title'] . '"><i class="vc-composer-icon vc-c-icon-' . $layout['icon_class'] . '"></i></a> ';
}
$controls_layout .= '</span>';
return $controls_layout;
}
}

View File

@@ -0,0 +1,20 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
require_once vc_path_dir( 'SHORTCODES_DIR', 'vc-gitem-zone.php' );
/**
* Class WPBakeryShortCode_Vc_Gitem_Zone_A
*/
class WPBakeryShortCode_Vc_Gitem_Zone_A extends WPBakeryShortCode_Vc_Gitem_Zone {
public $zone_name = 'a';
/**
* @return mixed|string
*/
protected function getFileName() {
return 'vc_gitem_zone';
}
}

View File

@@ -0,0 +1,20 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
require_once vc_path_dir( 'SHORTCODES_DIR', 'vc-gitem-zone.php' );
/**
* Class WPBakeryShortCode_Vc_Gitem_Zone_B
*/
class WPBakeryShortCode_Vc_Gitem_Zone_B extends WPBakeryShortCode_Vc_Gitem_Zone {
public $zone_name = 'b';
/**
* @return mixed|string
*/
protected function getFileName() {
return 'vc_gitem_zone';
}
}

View File

@@ -0,0 +1,13 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
require_once vc_path_dir( 'SHORTCODES_DIR', 'vc-gitem-zone.php' );
/**
* Class WPBakeryShortCode_Vc_Gitem_Zone_C
*/
class WPBakeryShortCode_Vc_Gitem_Zone_C extends WPBakeryShortCode_Vc_Gitem_Zone {
public $zone_name = 'c';
}

View File

@@ -0,0 +1,11 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Class WPBakeryShortCode_Vc_Gitem_Zone
*/
class WPBakeryShortCode_Vc_Gitem_Zone extends WPBakeryShortCodesContainer {
public $zone_name = '';
}

View File

@@ -0,0 +1,122 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Class WPBakeryShortCode_Vc_Gitem
*/
class WPBakeryShortCode_Vc_Gitem extends WPBakeryShortCodesContainer {
/**
* @param $atts
* @param null $content
* @return string
* @throws \Exception
*/
public function contentAdmin( $atts, $content = null ) {
/**
* @var string @el_class - comes
*/
extract( shortcode_atts( $this->predefined_atts, $atts ) );
$output = '';
$column_controls = $this->getControls( $this->settings( 'controls' ) );
$output .= '<div ' . $this->mainHtmlBlockParams( '12', '' ) . '>';
$output .= $column_controls;
$output .= '<div ' . $this->containerHtmlBlockParams( '12', '' ) . '>';
$output .= $this->itemGrid();
$output .= do_shortcode( shortcode_unautop( $content ) );
$output .= '</div>';
if ( isset( $this->settings['params'] ) ) {
$inner = '';
foreach ( $this->settings['params'] as $param ) {
$param_value = isset( ${$param['param_name']} ) ? ${$param['param_name']} : '';
if ( is_array( $param_value ) ) {
// Get first element from the array
reset( $param_value );
$first_key = key( $param_value );
$param_value = $param_value[ $first_key ];
}
$inner .= $this->singleParamHtmlHolder( $param, $param_value );
}
$output .= $inner;
}
$output .= '</div>';
$output .= '</div>';
return $output;
}
/**
* @param $width
* @param $i
* @return string
* @throws \Exception
*/
public function mainHtmlBlockParams( $width, $i ) {
$sortable = ( vc_user_access_check_shortcode_all( $this->shortcode ) ? 'wpb_sortable' : $this->nonDraggableClass );
return 'data-element_type="' . $this->settings['base'] . '" class="' . $this->settings['base'] . '-shortcode ' . $sortable . ' wpb_content_holder vc_shortcodes_container"' . $this->customAdminBlockParams();
}
/**
* @return string
*/
public function itemGrid() {
$output = '<div class="vc_row"><div class="vc_col-xs-4 vc_col-xs-offset-4"><div class="vc_gitem-add-c-col" data-vc-gitem="add-c" data-vc-position="top"></div></div></div><div class="vc_row"><div class="vc_col-xs-4 vc_gitem-add-c-left"><div class="vc_gitem-add-c-col" data-vc-gitem="add-c" data-vc-position="left"></div></div><div class="vc_col-xs-4 vc_gitem-ab-zone" data-vc-gitem="add-ab"></div><div class="vc_col-xs-4 vc_gitem-add-c-right"><div class="vc_gitem-add-c-col" data-vc-gitem="add-c" data-vc-position="right"></div></div></div><div class="vc_row"><div class="vc_col-xs-4 vc_col-xs-offset-4 vc_gitem-add-c-bottom"><div class="vc_gitem-add-c-col" data-vc-gitem="add-c" data-vc-position="bottom"></div></div></div>';
return $output;
}
/**
* @param $width
* @param $i
* @return string
*/
public function containerHtmlBlockParams( $width, $i ) {
return 'class="vc_gitem-content"';
}
/**
* Get rendered controls
*
* @param array $controls
*
* @return string
* @throws \Exception
*/
public function getControls( $controls ) {
if ( ! is_array( $controls ) || empty( $controls ) ) {
return '';
}
$buttons = array();
$editAccess = vc_user_access_check_shortcode_edit( $this->shortcode );
$allAccess = vc_user_access_check_shortcode_all( $this->shortcode );
foreach ( $controls as $control ) {
switch ( $control ) {
case 'add':
if ( $allAccess ) {
$buttons[] = '<a class="vc_control-btn vc_control-btn-add" href="#" title="' . esc_attr__( 'Add to this grid item', 'js_composer' ) . '" data-vc-control="add"><i class="vc_icon"></i></a>';
}
break;
case 'edit':
if ( $editAccess ) {
$buttons[] = '<a class="vc_control-btn vc_control-btn-edit" href="#" title="' . esc_attr__( 'Edit this grid item', 'js_composer' ) . '" data-vc-control="edit"><i class="vc_icon"></i></a>';
}
break;
case 'delete':
if ( $allAccess ) {
$buttons[] = '<a class="vc_control-btn vc_control-btn-delete" href="#" title="' . esc_attr__( 'Delete this grid item ', 'js_composer' ) . '" data-vc-control="delete"><i class="vc_icon"></i></a>';
}
break;
}
}
$html = '<div class="vc_controls vc_controls-dark vc_controls-visible">' . implode( ' ', $buttons ) . '</div>';
return $html;
}
}

View File

@@ -0,0 +1,10 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Class WPBakeryShortCode_Vc_Gmaps
*/
class WPBakeryShortCode_Vc_Gmaps extends WPBakeryShortCode {
}

View File

@@ -0,0 +1,47 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Class WPBakeryShortCode_Vc_GooglePlus
*/
class WPBakeryShortCode_Vc_GooglePlus extends WPBakeryShortCode {
/**
* @param $atts
* @param null $content
* @return string
* @throws \Exception
*/
protected function contentInline( $atts, $content = null ) {
/**
* Shortcode attributes
* @var $atts
* @var $type
* @var $annotation
* @var $widget_width
* @var $css
* @var $css_animation
* Shortcode class
* @var WPBakeryShortCode_Vc_GooglePlus $this
*/
$type = $annotation = $widget_width = $css = $css_animation = '';
$atts = vc_map_get_attributes( $this->getShortcode(), $atts );
extract( $atts );
if ( strlen( $type ) === 0 ) {
$type = 'standard';
}
if ( strlen( $annotation ) === 0 ) {
$annotation = 'bubble';
}
$css = isset( $atts['css'] ) ? $atts['css'] : '';
$el_class = isset( $atts['el_class'] ) ? $atts['el_class'] : '';
$class_to_filter = 'wpb_googleplus vc_social-placeholder wpb_content_element vc_socialtype-' . $type;
$class_to_filter .= vc_shortcode_custom_css_class( $css, ' ' ) . $this->getExtraClass( $el_class ) . $this->getCSSAnimation( $css_animation );
$css_class = apply_filters( VC_SHORTCODE_CUSTOM_CSS_FILTER_TAG, $class_to_filter, $this->settings['base'], $atts );
return '<div class="' . esc_attr( $css_class ) . '"></div>';
}
}

View File

@@ -0,0 +1,17 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Class WPBakeryShortCode_Vc_Gutenberg
*/
class WPBakeryShortCode_Vc_Gutenberg extends WPBakeryShortCode {
/**
* @param $title
* @return string
*/
protected function outputTitle( $title ) {
return '';
}
}

View File

@@ -0,0 +1,65 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Class WPBakeryShortCode_Vc_Hoverbox
*/
class WPBakeryShortCode_Vc_Hoverbox extends WPBakeryShortCode {
/**
* @param $tag
* @param $atts
* @param $align
* @return string
* @throws \Exception
*/
public function getHeading( $tag, $atts, $align ) {
if ( isset( $atts[ $tag ] ) && '' !== trim( $atts[ $tag ] ) ) {
if ( isset( $atts[ 'use_custom_fonts_' . $tag ] ) && 'true' === $atts[ 'use_custom_fonts_' . $tag ] ) {
$custom_heading = visual_composer()->getShortCode( 'vc_custom_heading' );
$data = vc_map_integrate_parse_atts( $this->shortcode, 'vc_custom_heading', $atts, $tag . '_' );
$data['font_container'] = implode( '|', array_filter( array(
'tag:h2',
'text_align:' . esc_attr( $align ),
$data['font_container'],
) ) );
$data['text'] = $atts[ $tag ]; // provide text to shortcode
return $custom_heading->render( array_filter( $data ) );
} else {
$inline_css = array();
$inline_css_string = '';
if ( isset( $atts['style'] ) && 'custom' === $atts['style'] ) {
if ( ! empty( $atts['custom_text'] ) ) {
$inline_css[] = vc_get_css_color( 'color', $atts['custom_text'] );
}
}
if ( $align ) {
$inline_css[] = 'text-align:' . esc_attr( $align );
}
if ( ! empty( $inline_css ) ) {
$inline_css_string = ' style="' . implode( '', $inline_css ) . '"';
}
return '<h2' . $inline_css_string . '>' . $atts[ $tag ] . '</h2>';
}
}
return '';
}
/**
* @param $atts
* @return string
* @throws \Exception
*/
public function renderButton( $atts ) {
$button_atts = vc_map_integrate_parse_atts( $this->shortcode, 'vc_btn', $atts, 'hover_btn_' );
$button = visual_composer()->getShortCode( 'vc_btn' );
return $button->render( array_filter( $button_atts ) );
}
}

View File

@@ -0,0 +1,11 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Class WPBakeryShortCode_Vc_Icon
* @since 4.4
*/
class WPBakeryShortCode_Vc_Icon extends WPBakeryShortCode {
}

View File

@@ -0,0 +1,64 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
require_once vc_path_dir( 'SHORTCODES_DIR', 'vc-gallery.php' );
/**
* Class WPBakeryShortCode_Vc_images_carousel
*/
class WPBakeryShortCode_Vc_Images_Carousel extends WPBakeryShortCode_Vc_Gallery {
protected static $carousel_index = 1;
/**
* WPBakeryShortCode_Vc_images_carousel constructor.
* @param $settings
*/
public function __construct( $settings ) {
parent::__construct( $settings );
$this->jsCssScripts();
}
public function jsCssScripts() {
wp_register_script( 'vc_transition_bootstrap_js', vc_asset_url( 'lib/vc_carousel/js/transition.min.js' ), array(), WPB_VC_VERSION, true );
wp_register_script( 'vc_carousel_js', vc_asset_url( 'lib/vc_carousel/js/vc_carousel.min.js' ), array( 'vc_transition_bootstrap_js' ), WPB_VC_VERSION, true );
wp_register_style( 'vc_carousel_css', vc_asset_url( 'lib/vc_carousel/css/vc_carousel.min.css' ), array(), WPB_VC_VERSION );
}
/**
* @return string
*/
public static function getCarouselIndex() {
return ( self::$carousel_index ++ ) . '-' . time();
}
/**
* @param $size
* @return string
*/
protected function getSliderWidth( $size ) {
global $_wp_additional_image_sizes;
$width = '100%';
if ( in_array( $size, get_intermediate_image_sizes(), true ) ) {
if ( in_array( $size, array(
'thumbnail',
'medium',
'large',
), true ) ) {
$width = get_option( $size . '_size_w' ) . 'px';
} else {
if ( isset( $_wp_additional_image_sizes ) && isset( $_wp_additional_image_sizes[ $size ] ) ) {
$width = $_wp_additional_image_sizes[ $size ]['width'] . 'px';
}
}
} else {
preg_match_all( '/\d+/', $size, $matches );
if ( count( $matches[0] ) > 1 ) {
$width = $matches[0][0] . 'px';
}
}
return $width;
}
}

View File

@@ -0,0 +1,28 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Class WPBakeryShortCode_Vc_Line_Chart
*/
class WPBakeryShortCode_Vc_Line_Chart extends WPBakeryShortCode {
/**
* WPBakeryShortCode_Vc_Line_Chart constructor.
* @param $settings
*/
public function __construct( $settings ) {
parent::__construct( $settings );
$this->jsScripts();
}
public function jsScripts() {
wp_register_script( 'vc_waypoints', vc_asset_url( 'lib/vc_waypoints/vc-waypoints.min.js' ), array( 'jquery' ), WPB_VC_VERSION, true );
wp_register_script( 'ChartJS', vc_asset_url( 'lib/bower/chartjs/Chart.min.js' ), array(), WPB_VC_VERSION, true );
wp_register_script( 'vc_line_chart', vc_asset_url( 'lib/vc_line_chart/vc_line_chart.min.js' ), array(
'jquery',
'vc_waypoints',
'ChartJS',
), WPB_VC_VERSION, true );
}
}

View File

@@ -0,0 +1,63 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
require_once vc_path_dir( 'SHORTCODES_DIR', 'vc-basic-grid.php' );
/**
* Class WPBakeryShortCode_Vc_Masonry_Grid
*/
class WPBakeryShortCode_Vc_Masonry_Grid extends WPBakeryShortCode_Vc_Basic_Grid {
/**
* @return mixed|string
*/
protected function getFileName() {
return 'vc_basic_grid';
}
public function shortcodeScripts() {
parent::shortcodeScripts();
wp_register_script( 'vc_masonry', vc_asset_url( 'lib/bower/masonry/dist/masonry.pkgd.min.js' ), array(), WPB_VC_VERSION, true );
}
public function enqueueScripts() {
wp_enqueue_script( 'vc_masonry' );
parent::enqueueScripts();
}
public function buildGridSettings() {
parent::buildGridSettings();
$this->grid_settings['style'] .= '-masonry';
}
/**
* @param $grid_style
* @param $settings
* @param $content
* @return string
*/
protected function contentAllMasonry( $grid_style, $settings, $content ) {
return parent::contentAll( $grid_style, $settings, $content );
}
/**
* @param $grid_style
* @param $settings
* @param $content
* @return string
*/
protected function contentLazyMasonry( $grid_style, $settings, $content ) {
return parent::contentLazy( $grid_style, $settings, $content );
}
/**
* @param $grid_style
* @param $settings
* @param $content
* @return string
*/
protected function contentLoadMoreMasonry( $grid_style, $settings, $content ) {
return parent::contentLoadMore( $grid_style, $settings, $content );
}
}

View File

@@ -0,0 +1,58 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
require_once vc_path_dir( 'SHORTCODES_DIR', 'vc-media-grid.php' );
/**
* Class WPBakeryShortCode_Vc_Masonry_Media_Grid
*/
class WPBakeryShortCode_Vc_Masonry_Media_Grid extends WPBakeryShortCode_Vc_Media_Grid {
public function shortcodeScripts() {
parent::shortcodeScripts();
wp_register_script( 'vc_masonry', vc_asset_url( 'lib/bower/masonry/dist/masonry.pkgd.min.js' ), array(), WPB_VC_VERSION, true );
}
public function enqueueScripts() {
wp_enqueue_script( 'vc_masonry' );
parent::enqueueScripts();
}
public function buildGridSettings() {
parent::buildGridSettings();
$this->grid_settings['style'] .= '-masonry';
}
/**
* @param $grid_style
* @param $settings
* @param $content
* @return string
*/
protected function contentAllMasonry( $grid_style, $settings, $content ) {
return parent::contentAll( $grid_style, $settings, $content );
}
/**
* @param $grid_style
* @param $settings
* @param $content
* @return string
*/
protected function contentLazyMasonry( $grid_style, $settings, $content ) {
return parent::contentLazy( $grid_style, $settings, $content );
}
/**
* @param $grid_style
* @param $settings
* @param $content
* @return string
*/
protected function contentLoadMoreMasonry( $grid_style, $settings, $content ) {
return parent::contentLoadMore( $grid_style, $settings, $content );
}
}

View File

@@ -0,0 +1,133 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
require_once vc_path_dir( 'SHORTCODES_DIR', 'vc-basic-grid.php' );
/**
* Class WPBakeryShortCode_Vc_Media_Grid
*/
class WPBakeryShortCode_Vc_Media_Grid extends WPBakeryShortCode_Vc_Basic_Grid {
/**
* WPBakeryShortCode_Vc_Media_Grid constructor.
* @param $settings
*/
public function __construct( $settings ) {
parent::__construct( $settings );
add_filter( $this->shortcode . '_items_list', array(
$this,
'setItemsIfEmpty',
) );
}
/**
* @return mixed|string
*/
protected function getFileName() {
return 'vc_basic_grid';
}
/**
* @param $max_items
*/
protected function setPagingAll( $max_items ) {
$this->atts['items_per_page'] = $this->atts['query_items_per_page'] = apply_filters( 'vc_basic_grid_items_per_page_all_max_items', self::$default_max_items );
}
/**
* @param $atts
* @return array
*/
public function buildQuery( $atts ) {
if ( empty( $atts['include'] ) ) {
$atts['include'] = - 1;
}
$settings = array(
'include' => $atts['include'],
'posts_per_page' => apply_filters( 'vc_basic_grid_max_items', self::$default_max_items ),
'offset' => 0,
'post_type' => 'attachment',
'orderby' => 'post__in',
);
return $settings;
}
/**
* @param $items
* @return string
*/
public function setItemsIfEmpty( $items ) {
if ( empty( $items ) ) {
require_once vc_path_dir( 'PARAMS_DIR', 'vc_grid_item/class-vc-grid-item.php' );
$grid_item = new Vc_Grid_Item();
$grid_item->setGridAttributes( $this->atts );
$grid_item->shortcodes();
$item = '[vc_gitem]<img src="' . esc_url( vc_asset_url( 'vc/vc_gitem_image.png' ) ) . '">[/vc_gitem]';
$grid_item->parseTemplate( $item );
$items = str_repeat( $grid_item->renderItem( get_post( (int) vc_request_param( 'vc_post_id' ) ) ), 3 );
}
return $items;
}
/**
* @param $param
* @param $value
* @return string
*/
public function singleParamHtmlHolder( $param, $value ) {
$output = '';
// Compatibility fixes
// TODO: check $old_names & &new_names. Leftover from copypasting?
$old_names = array(
'yellow_message',
'blue_message',
'green_message',
'button_green',
'button_grey',
'button_yellow',
'button_blue',
'button_red',
'button_orange',
);
$new_names = array(
'alert-block',
'alert-info',
'alert-success',
'btn-success',
'btn',
'btn-info',
'btn-primary',
'btn-danger',
'btn-warning',
);
$value = str_ireplace( $old_names, $new_names, $value );
$param_name = isset( $param['param_name'] ) ? $param['param_name'] : '';
$type = isset( $param['type'] ) ? $param['type'] : '';
$class = isset( $param['class'] ) ? $param['class'] : '';
if ( isset( $param['holder'] ) && 'hidden' !== $param['holder'] ) {
$output .= '<' . $param['holder'] . ' class="wpb_vc_param_value ' . $param_name . ' ' . $type . ' ' . $class . '" name="' . $param_name . '">' . $value . '</' . $param['holder'] . '>';
}
if ( 'include' === $param_name ) {
$images_ids = empty( $value ) ? array() : explode( ',', trim( $value ) );
$output .= '<ul class="attachment-thumbnails' . ( empty( $images_ids ) ? ' image-exists' : '' ) . '" data-name="' . $param_name . '">';
foreach ( $images_ids as $image ) {
$img = wpb_getImageBySize( array(
'attach_id' => (int) $image,
'thumb_size' => 'thumbnail',
) );
$output .= ( $img ? '<li>' . $img['thumbnail'] . '</li>' : '<li><img width="150" height="150" src="' . esc_url( vc_asset_url( 'vc/blank.gif' ) ) . '" class="attachment-thumbnail" alt="" title="" /></li>' );
}
$output .= '</ul>';
$output .= '<a href="#" class="column_edit_trigger' . ( ! empty( $images_ids ) ? ' image-exists' : '' ) . '">' . esc_html__( 'Add images', 'js_composer' ) . '</a>';
}
return $output;
}
}

View File

@@ -0,0 +1,39 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Class WPBakeryShortCode_Vc_Message
*/
class WPBakeryShortCode_Vc_Message extends WPBakeryShortCode {
/**
* @param $atts
* @return mixed
*/
public static function convertAttributesToMessageBox2( $atts ) {
if ( isset( $atts['style'] ) ) {
if ( '3d' === $atts['style'] ) {
$atts['message_box_style'] = '3d';
$atts['style'] = 'rounded';
} elseif ( 'outlined' === $atts['style'] ) {
$atts['message_box_style'] = 'outline';
$atts['style'] = 'rounded';
} elseif ( 'square_outlined' === $atts['style'] ) {
$atts['message_box_style'] = 'outline';
$atts['style'] = 'square';
}
}
return $atts;
}
/**
* @param $title
* @return string
*/
public function outputTitle( $title ) {
return '';
}
}

View File

@@ -0,0 +1,60 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Class WPBakeryShortCode_Vc_Pie
*/
class WPBakeryShortCode_Vc_Pie extends WPBakeryShortCode {
/**
* WPBakeryShortCode_Vc_Pie constructor.
* @param $settings
*/
public function __construct( $settings ) {
parent::__construct( $settings );
$this->jsScripts();
}
public function jsScripts() {
wp_register_script( 'vc_waypoints', vc_asset_url( 'lib/vc_waypoints/vc-waypoints.min.js' ), array( 'jquery' ), WPB_VC_VERSION, true );
wp_register_script( 'progressCircle', vc_asset_url( 'lib/bower/progress-circle/ProgressCircle.min.js' ), array(), WPB_VC_VERSION, true );
wp_register_script( 'vc_pie', vc_asset_url( 'lib/vc_chart/jquery.vc_chart.min.js' ), array(
'jquery',
'vc_waypoints',
'progressCircle',
), WPB_VC_VERSION, true );
}
/**
* Convert old color names to new ones for BC
*
* @param array $atts
*
* @return array
*/
public static function convertOldColorsToNew( $atts ) {
$map = array(
'btn-primary' => '#0088cc',
'btn-success' => '#6ab165',
'btn-warning' => '#ff9900',
'btn-inverse' => '#555555',
'btn-danger' => '#ff675b',
'btn-info' => '#58b9da',
'primary' => '#0088cc',
'success' => '#6ab165',
'warning' => '#ff9900',
'inverse' => '#555555',
'danger' => '#ff675b',
'info' => '#58b9da',
'default' => '#f7f7f7',
);
if ( isset( $atts['color'] ) && isset( $map[ $atts['color'] ] ) ) {
$atts['custom_color'] = $map[ $atts['color'] ];
$atts['color'] = 'custom';
}
return $atts;
}
}

View File

@@ -0,0 +1,40 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Class WPBakeryShortCode_Vc_Pinterest
*/
class WPBakeryShortCode_Vc_Pinterest extends WPBakeryShortCode {
/**
* @param $atts
* @param null $content
* @return string
* @throws \Exception
*/
protected function contentInline( $atts, $content = null ) {
/**
* Shortcode attributes
* @var $atts
* @var $type
* @var $annotation // TODO: check why annotation doesn't set before
* @var $css
* @var $css_animation
* Shortcode class
* @var WPBakeryShortCode_Vc_Pinterest $this
*/
$type = $annotation = $css = $css_animation = '';
$atts = vc_map_get_attributes( $this->getShortcode(), $atts );
extract( $atts );
$css = isset( $atts['css'] ) ? $atts['css'] : '';
$el_class = isset( $atts['el_class'] ) ? $atts['el_class'] : '';
$class_to_filter = 'wpb_googleplus vc_social-placeholder wpb_content_element vc_socialtype-' . $type;
$class_to_filter .= vc_shortcode_custom_css_class( $css, ' ' ) . $this->getExtraClass( $el_class ) . $this->getCSSAnimation( $css_animation );
$css_class = apply_filters( VC_SHORTCODE_CUSTOM_CSS_FILTER_TAG, $class_to_filter, $this->settings['base'], $atts );
return '<div class="' . esc_attr( $css_class ) . '"></div>';
}
}

View File

@@ -0,0 +1,10 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Class WPBakeryShortCode_Vc_Posts_slider
*/
class WPBakeryShortCode_Vc_Posts_Slider extends WPBakeryShortCode {
}

View File

@@ -0,0 +1,42 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Class WPBakeryShortCode_Vc_Progress_Bar
*/
class WPBakeryShortCode_Vc_Progress_Bar extends WPBakeryShortCode {
/**
* @param $atts
* @return mixed
*/
public static function convertAttributesToNewProgressBar( $atts ) {
if ( isset( $atts['values'] ) && strlen( $atts['values'] ) > 0 ) {
$values = vc_param_group_parse_atts( $atts['values'] );
if ( ! is_array( $values ) ) {
$temp = explode( ',', $atts['values'] );
$paramValues = array();
foreach ( $temp as $value ) {
$data = explode( '|', $value );
$colorIndex = 2;
$newLine = array();
$newLine['value'] = isset( $data[0] ) ? $data[0] : 0;
$newLine['label'] = isset( $data[1] ) ? $data[1] : '';
if ( isset( $data[1] ) && preg_match( '/^\d{1,3}\%$/', $data[1] ) ) {
$colorIndex ++;
$newLine['value'] = (float) str_replace( '%', '', $data[1] );
$newLine['label'] = isset( $data[2] ) ? $data[2] : '';
}
if ( isset( $data[ $colorIndex ] ) ) {
$newLine['customcolor'] = $data[ $colorIndex ];
}
$paramValues[] = $newLine;
}
$atts['values'] = rawurlencode( wp_json_encode( $paramValues ) );
}
}
return $atts;
}
}

View File

@@ -0,0 +1,59 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
*/
class WPBakeryShortCode_Vc_Raw_Html extends WPBakeryShortCode {
/**
* @param $param
* @param $value
* @return string
*/
public function singleParamHtmlHolder( $param, $value ) {
$output = '';
// Compatibility fixes
// TODO: check $old_names & &new_names. Leftover from copypasting?
$old_names = array(
'yellow_message',
'blue_message',
'green_message',
'button_green',
'button_grey',
'button_yellow',
'button_blue',
'button_red',
'button_orange',
);
$new_names = array(
'alert-block',
'alert-info',
'alert-success',
'btn-success',
'btn',
'btn-info',
'btn-primary',
'btn-danger',
'btn-warning',
);
$value = str_ireplace( $old_names, $new_names, $value );
$param_name = isset( $param['param_name'] ) ? $param['param_name'] : '';
$type = isset( $param['type'] ) ? $param['type'] : '';
$class = isset( $param['class'] ) ? $param['class'] : '';
if ( isset( $param['holder'] ) && 'hidden' !== $param['holder'] ) {
if ( 'textarea_raw_html' === $param['type'] ) {
// @codingStandardsIgnoreLine
$output .= sprintf( '<%s class="wpb_vc_param_value %s %s %s" name="%s">%s</%s><input type="hidden" name="%s_code" class="%s_code" value="%s" />', $param['holder'], $param_name, $type, $class, $param_name, htmlentities( rawurldecode( base64_decode( wp_strip_all_tags( $value ) ) ), ENT_COMPAT, 'UTF-8' ), $param['holder'], $param_name, $param_name, wp_strip_all_tags( $value ) );
} else {
$output .= '<' . $param['holder'] . ' class="wpb_vc_param_value ' . $param_name . ' ' . $type . ' ' . $class . '" name="' . $param_name . '">' . $value . '</' . $param['holder'] . '>';
}
}
return $output;
}
}

Some files were not shown because too many files have changed in this diff Show More