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,222 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
// Part BC: Post types
// =========================
/**
* @param $state
* @return bool|string
*/
function vc_bc_access_rule_48_post_type_get_state( $state ) {
if ( null === $state ) {
$content_types = vc_settings()->get( 'content_types' );
if ( empty( $content_types ) ) {
$state = true;
} else {
$state = 'custom';
}
}
return $state;
}
/**
* @param $value
* @param $role
* @param $rule
* @return bool
* @throws \Exception
*/
function vc_bc_access_rule_48_post_type_rule( $value, $role, $rule ) {
if ( ! $role ) {
return $value;
}
global $vc_bc_access_rule_48_editor_post_types;
$part = vc_role_access()->who( $role->name )->part( 'post_types' );
if ( ! isset( $part->getRole()->capabilities[ $part->getStateKey() ] ) ) {
if ( is_null( $vc_bc_access_rule_48_editor_post_types ) ) {
$pt_array = vc_settings()->get( 'content_types' );
$vc_bc_access_rule_48_editor_post_types = $pt_array ? $pt_array : vc_default_editor_post_types();
}
return in_array( $rule, $vc_bc_access_rule_48_editor_post_types, true );
}
return $value;
}
// Part BC: shortcodes
// =========================
/**
* @param $state
* @param $role
* @return bool|string
*/
function vc_bc_access_rule_48_shortcodes_get_state( $state, $role ) {
if ( ! $role ) {
return $state;
}
if ( null === $state ) {
$group_access_settings = vc_settings()->get( 'groups_access_rules' );
if ( ! isset( $group_access_settings[ $role->name ]['shortcodes'] ) ) {
$state = true;
} else {
$state = 'custom';
}
}
return $state;
}
/**
* @param $value
* @param $role
* @param $rule
* @return bool
* @throws \Exception
*/
function vc_bc_access_rule_48_shortcodes_rule( $value, $role, $rule ) {
if ( ! $role ) {
return $value;
}
if ( ! vc_bc_access_get_shortcodes_state_is_set( $role ) ) {
if ( preg_match( '/_edit$/', $rule ) ) {
return false;
}
$group_access_settings = vc_settings()->get( 'groups_access_rules' );
if ( isset( $group_access_settings[ $role->name ]['shortcodes'] ) && ! empty( $group_access_settings[ $role->name ]['shortcodes'] ) ) {
$rule = preg_replace( '/_all$/', '', $rule );
return 'vc_row' === $rule || ( isset( $group_access_settings[ $role->name ]['shortcodes'][ $rule ] ) && 1 === (int) $group_access_settings[ $role->name ]['shortcodes'][ $rule ] );
} else {
return true;
}
}
return $value;
}
/**
* Check is state set
*
* @param $role
*
* @return bool
* @throws \Exception
*/
function vc_bc_access_get_shortcodes_state_is_set( $role ) {
if ( ! $role ) {
return false;
}
$part = vc_role_access()->who( $role->name )->part( 'shortcodes' );
return isset( $part->getRole()->capabilities[ $part->getStateKey() ] );
}
// Part BC: backened editor
// ===========================
/**
* @param $state
* @param $role
* @return bool|string
*/
function vc_bc_access_rule_48_backend_editor_get_state( $state, $role ) {
if ( ! $role ) {
return $state;
}
if ( null === $state ) {
$group_access_settings = vc_settings()->get( 'groups_access_rules' );
if ( ! isset( $group_access_settings[ $role->name ]['show'] ) || 'all' === $group_access_settings[ $role->name ]['show'] ) {
$state = true;
} elseif ( 'no' === $group_access_settings[ $role->name ]['show'] ) {
$state = false;
} else {
$state = 'default';
}
}
return $state;
}
/**
* @param $state
* @param $role
* @return bool
*/
function vc_bc_access_rule_48_frontend_editor_get_state( $state, $role ) {
if ( ! $role ) {
return $state;
}
if ( null === $state ) {
$group_access_settings = vc_settings()->get( 'groups_access_rules' );
if ( isset( $group_access_settings[ $role->name ]['show'] ) && 'no' === $group_access_settings[ $role->name ]['show'] ) {
$state = false;
} else {
$state = true;
}
}
return $state;
}
/**
* @param $value
* @param $role
* @return bool
* @throws \Exception
*/
function vc_bc_access_rule_48_backend_editor_can_disabled_ce_editor_rule( $value, $role ) {
if ( ! $role ) {
return $value;
}
$part = vc_role_access()->who( $role->name )->part( 'backend_editor' );
if ( ! isset( $part->getRole()->capabilities[ $part->getStateKey() ] ) ) {
$group_access_settings = vc_settings()->get( 'groups_access_rules' );
return isset( $group_access_settings[ $role->name ]['show'] ) && 'only' === $group_access_settings[ $role->name ]['show'];
}
return $value;
}
/**
* @param $role
* @return mixed
* @throws \Exception
*/
function vc_bc_access_rule_48_backend_editor_add_cap_disabled_ce_editor( $role ) {
if ( ! $role ) {
return $role;
}
$part = vc_role_access()->who( $role->name )->part( 'backend_editor' );
if ( ! isset( $part->getRole()->capabilities[ $part->getStateKey() ] ) ) {
$group_access_settings = vc_settings()->get( 'groups_access_rules' );
if ( isset( $group_access_settings[ $role->name ]['show'] ) && 'only' === $group_access_settings[ $role->name ]['show'] ) {
$role->capabilities[ $part->getStateKey() . '/disabled_ce_editor' ] = true;
}
}
return $role;
}
function vc_bc_access_rule_48() {
add_filter( 'vc_role_access_with_post_types_get_state', 'vc_bc_access_rule_48_post_type_get_state' );
add_filter( 'vc_role_access_with_post_types_can', 'vc_bc_access_rule_48_post_type_rule', 10, 3 );
add_filter( 'vc_role_access_with_shortcodes_get_state', 'vc_bc_access_rule_48_shortcodes_get_state', 10, 3 );
add_filter( 'vc_role_access_with_shortcodes_can', 'vc_bc_access_rule_48_shortcodes_rule', 10, 3 );
add_filter( 'vc_role_access_with_backend_editor_get_state', 'vc_bc_access_rule_48_backend_editor_get_state', 10, 3 );
add_filter( 'vc_role_access_with_backend_editor_can_disabled_ce_editor', 'vc_bc_access_rule_48_backend_editor_can_disabled_ce_editor_rule', 10, 2 );
add_filter( 'vc_role_access_with_frontend_editor_get_state', 'vc_bc_access_rule_48_frontend_editor_get_state', 10, 3 );
add_filter( 'vc_role_access_all_caps_role', 'vc_bc_access_rule_48_backend_editor_add_cap_disabled_ce_editor' );
}
// BC function for shortcode
add_action( 'vc_before_init', 'vc_bc_access_rule_48' );

View File

@@ -0,0 +1,22 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
add_action( 'vc_activation_hook', 'vc_bc_multisite_options', 9 );
/**
* @param $networkWide
*/
function vc_bc_multisite_options( $networkWide ) {
global $current_site;
if ( ! is_multisite() || empty( $current_site ) || ! $networkWide || get_site_option( 'vc_bc_options_called', false ) || get_site_option( 'wpb_js_js_composer_purchase_code', false ) ) {
return;
}
// Now we need to check BC with license keys
$is_main_blog_activated = get_blog_option( (int) $current_site->id, 'wpb_js_js_composer_purchase_code' );
if ( $is_main_blog_activated ) {
update_site_option( 'wpb_js_js_composer_purchase_code', $is_main_blog_activated );
}
update_site_option( 'vc_bc_options_called', true );
}

View File

@@ -0,0 +1,424 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Collection of static methods for work with settings presets
*
* @since 4.8
*/
class Vc_Settings_Preset {
/**
* Get default preset id for specific shortcode
*
* @since 4.7
*
* @param string $shortcode_name
*
* @return mixed int|null
*/
public static function getDefaultSettingsPresetId( $shortcode_name = null ) {
if ( ! $shortcode_name ) {
return null;
}
$args = array(
'post_type' => 'vc_settings_preset',
'post_mime_type' => self::constructShortcodeMimeType( $shortcode_name ),
'posts_per_page' => - 1,
'meta_key' => '_vc_default',
'meta_value' => true,
);
$posts = get_posts( $args );
if ( $posts ) {
$default_id = $posts[0]->ID;
} else {
// check for vendor presets
$default_id = vc_vendor_preset()->getDefaultId( $shortcode_name );
}
return $default_id;
}
/**
* Set existing preset as default
*
* If this is vendor preset, clone it and set new one as default
*
* @param int $id If falsy, no default will be set
* @param string $shortcode_name
*
* @return boolean
*
* @since 4.7
*/
public static function setAsDefaultSettingsPreset( $id, $shortcode_name ) {
$post_id = self::getDefaultSettingsPresetId( $shortcode_name );
if ( $post_id ) {
delete_post_meta( $post_id, '_vc_default' );
}
if ( $id ) {
if ( is_numeric( $id ) ) {
// user preset
update_post_meta( $id, '_vc_default', true );
} else {
// vendor preset
$preset = vc_vendor_preset()->get( $id );
if ( ! $preset || $shortcode_name !== $preset['shortcode'] ) {
return false;
}
self::saveSettingsPreset( $preset['shortcode'], $preset['title'], wp_json_encode( $preset['params'] ), true );
}
}
return true;
}
/**
* Get mime type for specific shortcode
*
* @since 4.7
*
* @param $shortcode_name
*
* @return string
*/
public static function constructShortcodeMimeType( $shortcode_name ) {
return 'vc-settings-preset/' . str_replace( '_', '-', $shortcode_name );
}
/**
* Get shortcode name from post's mime type
*
* @since 4.7
*
* @param string $post_mime_type
*
* @return string
*/
public static function extractShortcodeMimeType( $post_mime_type ) {
$chunks = explode( '/', $post_mime_type );
if ( 2 !== count( $chunks ) ) {
return '';
}
return str_replace( '-', '_', $chunks[1] );
}
/**
* Get all presets
*
* @since 5.2
*
* @return array E.g. array(preset_id => value, preset_id => value, ...)
*/
public static function listAllPresets() {
$list = array();
$args = array(
'post_type' => 'vc_settings_preset',
'posts_per_page' => - 1,
);
// user presets
$posts = get_posts( $args );
foreach ( $posts as $post ) {
$shortcode_name = self::extractShortcodeMimeType( $post->post_mime_type );
$list[ $post->ID ] = (array) json_decode( $post->post_content );
}
// vendor presets
$presets = self::listDefaultVendorSettingsPresets();
foreach ( $presets as $shortcode => $params ) {
if ( ! isset( $list[ $shortcode ] ) ) {
$list[ $shortcode ] = $params;
}
}
return $list;
}
/**
* Get all default presets
*
* @since 4.7
*
* @return array E.g. array(shortcode_name => value, shortcode_name => value, ...)
*/
public static function listDefaultSettingsPresets() {
$list = array();
$args = array(
'post_type' => 'vc_settings_preset',
'posts_per_page' => - 1,
'meta_key' => '_vc_default',
'meta_value' => true,
);
// user presets
$posts = get_posts( $args );
foreach ( $posts as $post ) {
$shortcode_name = self::extractShortcodeMimeType( $post->post_mime_type );
$list[ $shortcode_name ] = (array) json_decode( $post->post_content );
}
// vendor presets
$presets = self::listDefaultVendorSettingsPresets();
foreach ( $presets as $shortcode => $params ) {
if ( ! isset( $list[ $shortcode ] ) ) {
$list[ $shortcode ] = $params;
}
}
return $list;
}
/**
* Get all default vendor presets
*
* @since 4.8
*
* @return array E.g. array(shortcode_name => value, shortcode_name => value, ...)
*/
public static function listDefaultVendorSettingsPresets() {
$list = array();
$presets = vc_vendor_preset()->getDefaults();
foreach ( $presets as $id => $preset ) {
$list[ $preset['shortcode'] ] = $preset['params'];
}
return $list;
}
/**
* Save shortcode preset
*
* @since 4.7
*
* @param string $shortcode_name
* @param string $title
* @param string $content
* @param boolean $is_default
*
* @return mixed int|false Post ID
*/
public static function saveSettingsPreset( $shortcode_name, $title, $content, $is_default = false ) {
$post_id = wp_insert_post( array(
'post_title' => $title,
'post_content' => $content,
'post_status' => 'publish',
'post_type' => 'vc_settings_preset',
'post_mime_type' => self::constructShortcodeMimeType( $shortcode_name ),
), false );
if ( $post_id && $is_default ) {
self::setAsDefaultSettingsPreset( $post_id, $shortcode_name );
}
return $post_id;
}
/**
* Get list of all presets for specific shortcode
*
* @since 4.7
*
* @param string $shortcode_name
*
* @return array E.g. array(id1 => title1, id2 => title2, ...)
*/
public static function listSettingsPresets( $shortcode_name = null ) {
$list = array();
if ( ! $shortcode_name ) {
return $list;
}
$args = array(
'post_type' => 'vc_settings_preset',
'orderby' => array( 'post_date' => 'DESC' ),
'posts_per_page' => - 1,
'post_mime_type' => self::constructShortcodeMimeType( $shortcode_name ),
);
$posts = get_posts( $args );
foreach ( $posts as $post ) {
$list[ $post->ID ] = $post->post_title;
}
return $list;
}
/**
* Get list of all vendor presets for specific shortcode
*
* @since 4.8
*
* @param string $shortcode_name
*
* @return array E.g. array(id1 => title1, id2 => title2, ...)
*/
public static function listVendorSettingsPresets( $shortcode_name = null ) {
$list = array();
if ( ! $shortcode_name ) {
return $list;
}
$presets = vc_vendor_preset()->getAll( $shortcode_name );
foreach ( $presets as $id => $preset ) {
$list[ $id ] = $preset['title'];
}
return $list;
}
/**
* Get specific shortcode preset
*
* @since 4.7
*
* @param mixed $id Can be int (user preset) or string (vendor preset)
* @param bool $array If true, return array instead of string
*
* @return mixed string?array Post content
*/
public static function getSettingsPreset( $id, $array = false ) {
if ( is_numeric( $id ) ) {
// user preset
$post = get_post( $id );
if ( ! $post ) {
return false;
}
$params = $array ? (array) json_decode( $post->post_content ) : $post->post_content;
} else {
// vendor preset
$preset = vc_vendor_preset()->get( $id );
if ( ! $preset ) {
return false;
}
$params = $preset['params'];
}
return $params;
}
/**
* Delete shortcode preset
*
* @since 4.7
*
* @param int $post_id Post must be of type 'vc_settings_preset'
*
* @return bool
*/
public static function deleteSettingsPreset( $post_id ) {
$post = get_post( $post_id );
if ( ! $post || 'vc_settings_preset' !== $post->post_type ) {
return false;
}
return (bool) wp_delete_post( $post_id, true );
}
/**
* Return rendered popup menu
*
* @since 4.7
*
* @param string $shortcode_name
*
* @return string
*/
public static function getRenderedSettingsPresetPopup( $shortcode_name ) {
$list_vendor_presets = self::listVendorSettingsPresets( $shortcode_name );
$list_presets = self::listSettingsPresets( $shortcode_name );
$default_id = self::getDefaultSettingsPresetId( $shortcode_name );
if ( ! $default_id ) {
$default_id = vc_vendor_preset()->getDefaultId( $shortcode_name );
}
ob_start();
vc_include_template( apply_filters( 'vc_render_settings_preset_popup', 'editors/partials/settings_presets_popup.tpl.php' ), array(
'list_presets' => array(
$list_presets,
$list_vendor_presets,
),
'default_id' => $default_id,
'shortcode_name' => $shortcode_name,
) );
$html = ob_get_clean();
return $html;
}
/**
* @param $shortcodes
*
* @return array
* @throws \Exception
*/
public static function addVcPresetsToShortcodes( $shortcodes ) {
if ( vc_user_access()->part( 'presets' )->can()->get() ) {
$shortcodesAndPresets = array();
foreach ( $shortcodes as $shortcode ) {
$presets = self::listSettingsPresets( $shortcode['base'] );
$shortcodesAndPresets[ $shortcode['base'] ] = $shortcode;
if ( ! empty( $presets ) ) {
foreach ( $presets as $presetId => $preset ) {
$shortcodesAndPresets[ $presetId ] = array(
'name' => $preset,
'base' => $shortcode['base'],
'description' => $shortcode['description'],
'presetId' => $presetId,
'_category_ids' => array( '_my_elements_' ),
);
if ( isset( $shortcode['icon'] ) ) {
$shortcodesAndPresets[ $presetId ]['icon'] = $shortcode['icon'];
}
}
}
}
return $shortcodesAndPresets;
}
return $shortcodes;
}
/**
* @param $category
*
* @return array
*/
public static function addPresetCategory( $category ) {
$presetCategory = (array) '_my_elements_';
$category = array_merge( $presetCategory, $category );
return $category;
}
}

View File

@@ -0,0 +1,144 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Singleton to hold all vendor presets
*
* @since 4.8
*/
class Vc_Vendor_Preset {
private static $instance;
private static $presets = array();
/**
* @return \Vc_Vendor_Preset
*/
public static function getInstance() {
if ( ! self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
protected function __construct() {
}
/**
* Add vendor preset to collection
*
* @param string $title
* @param string $shortcode
* @param array $params
* @param bool $default
*
* @return bool
* @since 4.8
*
*/
public function add( $title, $shortcode, $params, $default = false ) {
if ( ! $title || ! is_string( $title ) || ! $shortcode || ! is_string( $shortcode ) || ! $params || ! is_array( $params ) ) {
return false;
}
$preset = array(
'shortcode' => $shortcode,
'default' => $default,
'params' => $params,
'title' => $title,
);
// @codingStandardsIgnoreLine
$id = md5( serialize( $preset ) );
self::$presets[ $id ] = $preset;
return true;
}
/**
* Get specific vendor preset
*
* @param string $id
*
* @return mixed array|false
* @since 4.8
*
*/
public function get( $id ) {
if ( isset( self::$presets[ $id ] ) ) {
return self::$presets[ $id ];
}
return false;
}
/**
* Get all vendor presets for specific shortcode
*
* @param string $shortcode
*
* @return array
* @since 4.8
*
*/
public function getAll( $shortcode ) {
$list = array();
foreach ( self::$presets as $id => $preset ) {
if ( $shortcode === $preset['shortcode'] ) {
$list[ $id ] = $preset;
}
}
return $list;
}
/**
* Get all default vendor presets
*
* Include only one default preset per shortcode
*
* @return array
* @since 4.8
*
*/
public function getDefaults() {
$list = array();
$added = array();
foreach ( self::$presets as $id => $preset ) {
if ( $preset['default'] && ! in_array( $preset['shortcode'], $added, true ) ) {
$added[] = $preset['shortcode'];
$list[ $id ] = $preset;
}
}
return $list;
}
/**
* Get ID of default preset for specific shortcode
*
* If multiple presets are default, return first
*
* @param string $shortcode
*
* @return string|null
* @since 4.8
*
*/
public function getDefaultId( $shortcode ) {
foreach ( self::$presets as $id => $preset ) {
if ( $shortcode === $preset['shortcode'] && $preset['default'] ) {
return $id;
}
}
return null;
}
}

View File

@@ -0,0 +1,43 @@
{
"params/hidden.php": "",
"params/vc_grid_item.php": "",
"vendors/acf.php": "",
"vendors/cf7.php": "",
"vendors/gravity_forms.php": "",
"vendors/jwplayer.php": "",
"vendors/layerslider.php": "",
"vendors/mqtranslate.php": "",
"vendors/ninja_forms.php": "",
"vendors/qtranslate.php": "",
"vendors/qtranslate-x.php": "",
"vendors/revslider.php": "",
"vendors/woocommerce.php": "",
"vendors/yoast_seo.php": "",
"vendors/wpml.php": "",
"vendors/gutenberg.php": "",
"hook-vc-grid.php": "Logic for shortcode vc_grid",
"hook-vc-iconpicker-param.php": "Logic for shortcode param iconpicker",
"hook-vc-message.php": "Logic for shortcode vc_message",
"hook-vc-progress-bar.php": "Logic for shortcode vc_progress_bar",
"hook-vc-wp-text.php": "Logic for shortcode vc_wp_text fix",
"hook-vc-pie.php": "Logic for shortcode vc_pie",
"vc-grid-item-editor.php": "Create new post type vc_grid_item or Grid item",
"ui-vc-pointers.php": "Integrating With WordPress UI: Admin Pointers",
"vc-pages/automapper.php": "",
"vc-pages/page-custom-css.php": "Vc Special pages.",
"vc-pages/page-design-options.php": "Vc Special pages.",
"vc-pages/page-role-manager.php": "Vc Special pages.",
"vc-pages/pages.php": "Vc Special pages.",
"vc-pages/settings-tabs.php": "Vc Special pages.",
"vc-pages/welcome-screen.php": "Vc Special pages.",
"vc-pointers-backend-editor.php": "Backend editor VC Pointers",
"vc-pointers-frontend-editor.php": "Frontend editor VC Pointers",
"vc-image-filters.php": "PHP class for photo effects like Instagram",
"vc-settings-presets.php": "Logic for settings presets",
"vc-single-image.php": "add bc for single image",
"params-to-init.php": "add required init params",
"bc-access-rules-4.8.php": "BC for roles via filters >= VC 4.8",
"post-type-default-template.php": "Load default templates",
"bc-multisite-options.php": "BC for multisite options",
"vc-undoredo.php": "Undo Redo logic"
}

View File

@@ -0,0 +1,182 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Class Vc_Hooks_Vc_Grid
* @since 4.4
*/
class Vc_Hooks_Vc_Grid {
protected $grid_id_unique_name = 'vc_gid'; // if you change this also change in vc-basic-grid.php
/**
* Initializing hooks for grid element,
* Add actions to save appended shortcodes to post meta (for rendering in preview with shortcode id)
* And add action to hook request for grid data, to output it.
* @since 4.4
*/
public function load() {
// Hook for set post settings meta with shortcodes data
/**
* @since 4.4.3
*/
add_filter( 'vc_hooks_vc_post_settings', array(
$this,
'gridSavePostSettingsId',
), 10, 3 );
/**
* Used to output shortcode data for ajax request. called on any page request.
*/
add_action( 'wp_ajax_vc_get_vc_grid_data', array(
$this,
'getGridDataForAjax',
) );
add_action( 'wp_ajax_nopriv_vc_get_vc_grid_data', array(
$this,
'getGridDataForAjax',
) );
}
/**
* @return string
* @since 4.4.3
*/
private function getShortcodeRegexForId() {
return '\\[' // Opening bracket
. '(\\[?)' // 1: Optional second opening bracket for escaping shortcodes: [[tag]]
. '([\\w\-_]+)' // 2: Shortcode name
. '(?![\\w\-])' // Not followed by word character or hyphen
. '(' // 3: Unroll the loop: Inside the opening shortcode tag
. '[^\\]\\/]*' // Not a closing bracket or forward slash
. '(?:' . '\\/(?!\\])' // A forward slash not followed by a closing bracket
. '[^\\]\\/]*' // Not a closing bracket or forward slash
. ')*?'
. '(?:' . '(' . $this->grid_id_unique_name // 4: GridId must exist
. '[^\\]\\/]*' // Not a closing bracket or forward slash
. ')+' . ')'
. ')' . '(?:' . '(\\/)' // 5: Self closing tag ...
. '\\]' // ... and closing bracket
. '|' . '\\]' // Closing bracket
. '(?:' . '(' // 6: Unroll the loop: Optionally, anything between the opening and closing shortcode tags
. '[^\\[]*+' // Not an opening bracket
. '(?:' . '\\[(?!\\/\\2\\])' // An opening bracket not followed by the closing shortcode tag
. '[^\\[]*+' // Not an opening bracket
. ')*+' . ')' . '\\[\\/\\2\\]' // Closing shortcode tag
. ')?' . ')' . '(\\]?)'; // 7: Optional second closing brocket for escaping shortcodes: [[tag]]
}
/**
* @param array $settings
* @param $post_id
* @param $post
*
* @return array
* @since 4.4.3
*
*/
public function gridSavePostSettingsId( array $settings, $post_id, $post ) {
$pattern = $this->getShortcodeRegexForId();
$content = stripslashes( $post->post_content );
preg_match_all( "/$pattern/", $content, $found ); // fetch only needed shortcodes
if ( is_array( $found ) && ! empty( $found[0] ) ) {
$to_save = array();
if ( isset( $found[1] ) && is_array( $found[1] ) ) {
foreach ( $found[1] as $key => $parse_able ) {
if ( empty( $parse_able ) || '[' !== $parse_able ) {
$id_pattern = '/' . $this->grid_id_unique_name . '\:([\w\-_]+)/';
$id_value = $found[4][ $key ];
preg_match( $id_pattern, $id_value, $id_matches );
if ( ! empty( $id_matches ) ) {
$id_to_save = $id_matches[1];
// why we need to check if shortcode is parse able?
// 1: if it is escaped it must not be displayed (parsed)
// 2: so if 1 is true it must not be saved in database meta
$shortcode_tag = $found[2][ $key ];
$shortcode_atts_string = $found[3][ $key ];
/** @var array $atts */
$atts = shortcode_parse_atts( $shortcode_atts_string );
$content = $found[6][ $key ];
$data = array(
'tag' => $shortcode_tag,
'atts' => $atts,
'content' => $content,
);
$to_save[ $id_to_save ] = $data;
}
}
}
}
if ( ! empty( $to_save ) ) {
$settings['vc_grid_id'] = array( 'shortcodes' => $to_save );
}
}
return $settings;
}
/**
* @throws \Exception
* @since 4.4
*
* @output/@return string - grid data for ajax request.
*/
public function getGridDataForAjax() {
$tag = str_replace( '.', '', vc_request_param( 'tag' ) );
$allowed = apply_filters( 'vc_grid_get_grid_data_access', vc_verify_public_nonce() && $tag, $tag );
if ( $allowed ) {
$shortcode_fishbone = visual_composer()->getShortCode( $tag );
if ( is_object( $shortcode_fishbone ) && vc_get_shortcode( $tag ) ) {
/** @var WPBakeryShortcode_Vc_Basic_Grid $vc_grid */
$vc_grid = $shortcode_fishbone->shortcodeClass();
if ( method_exists( $vc_grid, 'isObjectPageable' ) && $vc_grid->isObjectPageable() && method_exists( $vc_grid, 'renderAjax' ) ) {
// @codingStandardsIgnoreLine
wp_die( $vc_grid->renderAjax( vc_request_param( 'data' ) ) );
}
}
}
}
}
/**
* @since 4.4
* @var Vc_Hooks_Vc_Grid $hook
*/
$hook = new Vc_Hooks_Vc_Grid();
// when WPBakery Page Builder initialized let's trigger Vc_Grid hooks.
add_action( 'vc_after_init', array(
$hook,
'load',
) );
if ( 'vc_edit_form' === vc_post_param( 'action' ) ) {
VcShortcodeAutoloader::getInstance()->includeClass( 'WPBakeryShortCode_Vc_Basic_Grid' );
add_filter( 'vc_edit_form_fields_attributes_vc_basic_grid', array(
'WPBakeryShortCode_Vc_Basic_Grid',
'convertButton2ToButton3',
) );
add_filter( 'vc_edit_form_fields_attributes_vc_media_grid', array(
'WPBakeryShortCode_Vc_Basic_Grid',
'convertButton2ToButton3',
) );
add_filter( 'vc_edit_form_fields_attributes_vc_masonry_grid', array(
'WPBakeryShortCode_Vc_Basic_Grid',
'convertButton2ToButton3',
) );
add_filter( 'vc_edit_form_fields_attributes_vc_masonry_media_grid', array(
'WPBakeryShortCode_Vc_Basic_Grid',
'convertButton2ToButton3',
) );
}

View File

@@ -0,0 +1,88 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/***
* @since 4.4
* Hook Vc-Iconpicker-Param.php
*
* Adds actions and filters for iconpicker param.
* Used to:
* - register/enqueue icons fonts for admin pages
* - register/enqueue js for iconpicker param
* - register/enqueue css for iconpicker param
*/
// @see Vc_Base::frontCss, used to append actions when frontCss(frontend editor/and real view mode) method called
// This action registers all styles(fonts) to be enqueue later
add_action( 'vc_base_register_front_css', 'vc_iconpicker_base_register_css' );
// @see Vc_Base::registerAdminCss, used to append action when registerAdminCss(backend editor) method called
// This action registers all styles(fonts) to be enqueue later
add_action( 'vc_base_register_admin_css', 'vc_iconpicker_base_register_css' );
// @see Vc_Base::registerAdminJavascript, used to append action when registerAdminJavascript(backend/frontend editor) method called
// This action will register needed js file, and also you can use it for localizing js.
add_action( 'vc_base_register_admin_js', 'vc_iconpicker_base_register_js' );
// @see Vc_Backend_Editor::printScriptsMessages (wp-content/plugins/js_composer/include/classes/editors/class-vc-backend-editor.php),
// used to enqueue needed js/css files when backend editor is rendering
add_action( 'vc_backend_editor_enqueue_js_css', 'vc_iconpicker_editor_jscss' );
// @see Vc_Frontend_Editor::enqueueAdmin (wp-content/plugins/js_composer/include/classes/editors/class-vc-frontend-editor.php),
// used to enqueue needed js/css files when frontend editor is rendering
add_action( 'vc_frontend_editor_enqueue_js_css', 'vc_iconpicker_editor_jscss' );
/**
* This action registers all styles(fonts) to be enqueue later
* @see filter 'vc_base_register_front_css' - preview/frontend-editor
* filter 'vc_base_register_admin_css' - backend editor
*
* @since 4.4
*/
function vc_iconpicker_base_register_css() {
// Vc Icon picker fonts:
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_typicons', vc_asset_url( 'css/lib/typicons/src/font/typicons.min.css' ), false, WPB_VC_VERSION );
wp_register_style( 'vc_openiconic', vc_asset_url( 'css/lib/vc-open-iconic/vc_openiconic.min.css' ), false, WPB_VC_VERSION );
wp_register_style( 'vc_linecons', vc_asset_url( 'css/lib/vc-linecons/vc_linecons_icons.min.css' ), false, WPB_VC_VERSION );
wp_register_style( 'vc_entypo', vc_asset_url( 'css/lib/vc-entypo/vc_entypo.min.css' ), false, WPB_VC_VERSION );
wp_register_style( 'vc_monosocialiconsfont', vc_asset_url( 'css/lib/monosocialiconsfont/monosocialiconsfont.min.css' ), false, WPB_VC_VERSION );
wp_register_style( 'vc_material', vc_asset_url( 'css/lib/vc-material/vc_material.min.css' ), false, WPB_VC_VERSION );
// Theme
wp_register_style( 'vc-icon-picker-main-css', vc_asset_url( 'lib/bower/vcIconPicker/css/jquery.fonticonpicker.min.css' ), false, WPB_VC_VERSION );
wp_register_style( 'vc-icon-picker-main-css-theme', vc_asset_url( 'lib/bower/vcIconPicker/themes/grey-theme/jquery.fonticonpicker.vcgrey.min.css' ), false, WPB_VC_VERSION );
}
/**
* Register admin js for iconpicker functionality
*
* @since 4.4
*/
function vc_iconpicker_base_register_js() {
wp_register_script( 'vc-icon-picker', vc_asset_url( 'lib/bower/vcIconPicker/jquery.fonticonpicker.min.js' ), array( 'jquery' ), WPB_VC_VERSION, true );
}
/**
* Enqueue ALL fonts/styles for Editor(admin) mode. (to allow easy change icons)
* - To append your icons fonts add action:
* vc_backend_editor_enqueue_jscss and vc_frontend_editor_enqueue_jscss
*
* @since 4.4
*/
function vc_iconpicker_editor_jscss() {
// Enqueue js and theme css files
wp_enqueue_script( 'vc-icon-picker' );
wp_enqueue_style( 'vc-icon-picker-main-css' );
wp_enqueue_style( 'vc-icon-picker-main-css-theme' );
// Fonts
wp_enqueue_style( 'vc_font_awesome_5' );
wp_enqueue_style( 'vc_openiconic' );
wp_enqueue_style( 'vc_typicons' );
wp_enqueue_style( 'vc_entypo' );
wp_enqueue_style( 'vc_linecons' );
wp_enqueue_style( 'vc_monosocialiconsfont' );
wp_enqueue_style( 'vc_material' );
}

View File

@@ -0,0 +1,13 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
if ( 'vc_edit_form' === vc_post_param( 'action' ) ) {
VcShortcodeAutoloader::getInstance()->includeClass( 'WPBakeryShortCode_Vc_Message' );
add_filter( 'vc_edit_form_fields_attributes_vc_message', array(
'WPBakeryShortCode_Vc_Message',
'convertAttributesToMessageBox2',
) );
}

View File

@@ -0,0 +1,12 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
if ( 'vc_edit_form' === vc_post_param( 'action' ) ) {
VcShortcodeAutoloader::getInstance()->includeClass( 'WPBakeryShortCode_Vc_Pie' );
add_filter( 'vc_edit_form_fields_attributes_vc_pie', array(
'WPBakeryShortCode_Vc_Pie',
'convertOldColorsToNew',
) );
}

View File

@@ -0,0 +1,13 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
if ( 'vc_edit_form' === vc_post_param( 'action' ) ) {
VcShortcodeAutoloader::getInstance()->includeClass( 'WPBakeryShortCode_Vc_Progress_Bar' );
add_filter( 'vc_edit_form_fields_attributes_vc_progress_bar', array(
'WPBakeryShortCode_Vc_Progress_Bar',
'convertAttributesToNewProgressBar',
) );
}

View File

@@ -0,0 +1,13 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
if ( 'vc_edit_form' === vc_post_param( 'action' ) ) {
VcShortcodeAutoloader::getInstance()->includeClass( 'WPBakeryShortCode_Vc_Wp_Text' );
add_filter( 'vc_edit_form_fields_attributes_vc_wp_text', array(
'WPBakeryShortCode_Vc_Wp_Text',
'convertTextAttributeToContent',
) );
}

View File

@@ -0,0 +1,79 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
add_filter( 'vc_edit_form_fields_optional_params', 'vc_edit_for_fields_add_optional_params' );
if ( 'vc_edit_form' === vc_post_param( 'action' ) ) {
add_action( 'vc_edit_form_fields_after_render', 'vc_output_required_params_to_init' );
add_filter( 'vc_edit_form_fields_optional_params', 'vc_edit_for_fields_add_optional_params' );
}
/**
* @param $params
* @return array
*/
function vc_edit_for_fields_add_optional_params( $params ) {
$arr = array(
'hidden',
'textfield',
'dropdown',
'checkbox',
'posttypes',
'taxonomies',
'taxomonies',
'exploded_textarea',
'textarea_raw_html',
'textarea_safe',
'textarea',
'attach_images',
'attach_image',
'widgetised_sidebars',
'colorpicker',
'loop',
'vc_link',
'sorted_list',
'tab_id',
'href',
'custom_markup',
'animation_style',
'iconpicker',
'el_id',
'vc_grid_item',
'google_fonts',
);
$params = array_values( array_unique( array_merge( $params, $arr ) ) );
return $params;
}
function vc_output_required_params_to_init() {
$params = WpbakeryShortcodeParams::getRequiredInitParams();
$js_array = array();
foreach ( $params as $param ) {
$js_array[] = '"' . $param . '"';
}
$data = '
if ( window.vc ) {
window.vc.required_params_to_init = [' . implode( ',', $js_array ) . '];
}';
$custom_tag = 'script';
$output = '<' . $custom_tag . '>' . $data . '</' . $custom_tag . '>';
echo $output;
}
add_action( 'wp_ajax_wpb_gallery_html', 'vc_gallery_html' );
function vc_gallery_html() {
vc_user_access()->checkAdminNonce()->validateDie()->wpAny( 'edit_posts', 'edit_pages' )->validateDie();
$images = vc_post_param( 'content' );
if ( ! empty( $images ) ) {
wp_send_json_success( vc_field_attached_images( explode( ',', $images ) ) );
}
die();
}

View File

@@ -0,0 +1,14 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* required hooks for hidden field.
* @since 4.5
*/
require_once vc_path_dir( 'PARAMS_DIR', 'hidden/hidden.php' );
vc_add_shortcode_param( 'hidden', 'vc_hidden_form_field' );
add_filter( 'vc_edit_form_fields_render_field_hidden_before', 'vc_edit_form_fields_render_field_hidden_before' );
add_filter( 'vc_edit_form_fields_render_field_hidden_after', 'vc_edit_form_fields_render_field_hidden_after' );

View File

@@ -0,0 +1,175 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* @param $settings
* @param $value
* @return string
*/
function vc_vc_grid_item_form_field( $settings, $value ) {
require_once vc_path_dir( 'PARAMS_DIR', 'vc_grid_item/editor/class-vc-grid-item-editor.php' );
require_once vc_path_dir( 'PARAMS_DIR', 'vc_grid_item/class-vc-grid-item.php' );
$output = '<div data-vc-grid-element="container">' . '<select data-vc-grid-element="value" type="hidden" name="' . esc_attr( $settings['param_name'] ) . '" class="wpb_vc_param_value wpb-select ' . esc_attr( $settings['param_name'] ) . ' ' . esc_attr( $settings['type'] ) . '_field" ' . '>';
$vc_grid_item_templates = Vc_Grid_Item::predefinedTemplates();
if ( is_array( $vc_grid_item_templates ) ) {
foreach ( $vc_grid_item_templates as $key => $data ) {
$output .= '<option data-vc-link="' . esc_url( admin_url( 'post-new.php?post_type=vc_grid_item&vc_gitem_template=' . $key ) ) . '" value="' . esc_attr( $key ) . '"' . ( $key === $value ? ' selected="true"' : '' ) . '>' . esc_html( $data['name'] ) . '</option>';
}
}
$grid_item_posts = get_posts( array(
'posts_per_page' => '-1',
'orderby' => 'post_title',
'post_type' => Vc_Grid_Item_Editor::postType(),
) );
foreach ( $grid_item_posts as $post ) {
$output .= '<option data-vc-link="' . esc_url( get_edit_post_link( $post->ID ) ) . '"value="' . esc_attr( $post->ID ) . '"' . ( (string) $post->ID === $value ? ' selected="true"' : '' ) . '>' . esc_html( $post->post_title ) . '</option>';
}
$output .= '</select></div>';
return $output;
}
function vc_load_vc_grid_item_param() {
vc_add_shortcode_param( 'vc_grid_item', 'vc_vc_grid_item_form_field' );
}
add_action( 'vc_load_default_params', 'vc_load_vc_grid_item_param' );
/**
* @param $target
* @return string
*/
function vc_gitem_post_data_get_link_target_frontend_editor( $target ) {
return ' target="_blank"';
}
/**
* @param $rel
* @return string
*/
function vc_gitem_post_data_get_link_rel_frontend_editor( $rel ) {
return ' rel="' . esc_attr( $rel ) . '"';
}
/**
* @param $atts
* @param string $default_class
* @param string $title
* @return string
*/
function vc_gitem_create_link( $atts, $default_class = '', $title = '' ) {
$link = '';
$target = '';
$rel = '';
$title_attr = '';
$css_class = 'vc_gitem-link' . ( strlen( $default_class ) > 0 ? ' ' . $default_class : '' );
if ( isset( $atts['link'] ) ) {
if ( 'custom' === $atts['link'] && ! empty( $atts['url'] ) ) {
$link = vc_build_link( $atts['url'] );
if ( strlen( $link['target'] ) ) {
$target = ' target="' . esc_attr( $link['target'] ) . '"';
}
if ( strlen( $link['rel'] ) ) {
$rel = ' rel="' . esc_attr( $link['rel'] ) . '"';
}
if ( strlen( $link['title'] ) ) {
$title = $link['title'];
}
$link = 'a href="' . esc_url( $link['url'] ) . '" class="' . esc_attr( $css_class ) . '"';
} elseif ( 'post_link' === $atts['link'] ) {
$link = 'a href="{{ post_link_url }}" class="' . esc_attr( $css_class ) . '"';
if ( ! strlen( $title ) ) {
$title = '{{ post_title }}';
}
} elseif ( 'post_author' === $atts['link'] ) {
$link = 'a href="{{ post_author_href }}" class="' . esc_attr( $css_class ) . '"';
if ( ! strlen( $title ) ) {
$title = '{{ post_author }}';
}
} elseif ( 'image' === $atts['link'] ) {
$link = 'a{{ post_image_url_href }} class="' . esc_attr( $css_class ) . '"';
} elseif ( 'image_lightbox' === $atts['link'] ) {
$link = 'a{{ post_image_url_attr_prettyphoto:' . $css_class . ' }}';
}
}
if ( strlen( $title ) > 0 ) {
$title_attr = ' title="' . esc_attr( $title ) . '"';
}
return apply_filters( 'vc_gitem_post_data_get_link_link', $link, $atts, $css_class ) . apply_filters( 'vc_gitem_post_data_get_link_target', $target, $atts ) . apply_filters( 'vc_gitem_post_data_get_link_rel', $rel, $atts ) . apply_filters( 'vc_gitem_post_data_get_link_title', $title_attr, $atts );
}
/**
* @param $atts
* @param $post
* @param string $default_class
* @param string $title
* @return string
*/
function vc_gitem_create_link_real( $atts, $post, $default_class = '', $title = '' ) {
$link = '';
$target = '';
$rel = '';
$title_attr = '';
$link_css_class = 'vc_gitem-link';
if ( isset( $atts['link'] ) ) {
$link_css_class = 'vc_gitem-link' . ( strlen( $default_class ) > 0 ? ' ' . $default_class : '' );
if ( strlen( $atts['el_class'] ) > 0 ) {
$link_css_class .= ' ' . $atts['el_class'];
}
$link_css_class = trim( preg_replace( '/\s+/', ' ', $link_css_class ) );
if ( 'custom' === $atts['link'] && ! empty( $atts['url'] ) ) {
$link = vc_build_link( $atts['url'] );
if ( strlen( $link['target'] ) ) {
$target = ' target="' . esc_attr( $link['target'] ) . '"';
}
if ( strlen( $link['rel'] ) ) {
$rel = ' rel="' . esc_attr( $link['rel'] ) . '"';
}
if ( strlen( $link['title'] ) ) {
$title = $link['title'];
}
$link = 'a href="' . esc_url( $link['url'] ) . '" class="' . esc_attr( $link_css_class ) . '"';
} elseif ( 'post_link' === $atts['link'] ) {
$link = 'a href="' . esc_url( get_permalink( $post->ID ) ) . '" class="' . esc_attr( $link_css_class ) . '"';
if ( ! strlen( $title ) ) {
$title = the_title( '', '', false );
}
} elseif ( 'image' === $atts['link'] ) {
$href_link = vc_gitem_template_attribute_post_image_url( '', array(
'post' => $post,
'data' => '',
) );
$link = 'a href="' . esc_url( $href_link ) . '" class="' . esc_attr( $link_css_class ) . '"';
} elseif ( 'image_lightbox' === $atts['link'] ) {
$link = 'a' . vc_gitem_template_attribute_post_image_url_attr_prettyphoto( '', array(
'post' => $post,
'data' => esc_attr( $link_css_class ),
) );
}
}
if ( strlen( $title ) > 0 ) {
$title_attr = ' title="' . esc_attr( $title ) . '"';
}
return apply_filters( 'vc_gitem_post_data_get_link_real_link', $link, $atts, $post, $link_css_class ) . apply_filters( 'vc_gitem_post_data_get_link_real_target', $target, $atts, $post ) . apply_filters( 'vc_gitem_post_data_get_link_real_rel', $rel, $atts, $post ) . apply_filters( 'vc_gitem_post_data_get_link_real_title', $title_attr, $atts );
}
/**
* @param $link
* @return string
*/
function vc_gitem_post_data_get_link_link_frontend_editor( $link ) {
return empty( $link ) ? 'a' : $link;
}
if ( vc_is_page_editable() ) {
add_filter( 'vc_gitem_post_data_get_link_link', 'vc_gitem_post_data_get_link_link_frontend_editor' );
add_filter( 'vc_gitem_post_data_get_link_real_link', 'vc_gitem_post_data_get_link_link_frontend_editor' );
add_filter( 'vc_gitem_post_data_get_link_target', 'vc_gitem_post_data_get_link_target_frontend_editor' );
add_filter( 'vc_gitem_post_data_get_link_rel', 'vc_gitem_post_data_get_link_rel_frontend_editor' );
add_filter( 'vc_gitem_post_data_get_link_real_target', 'vc_gitem_post_data_get_link_target_frontend_editor' );
add_filter( 'vc_gitem_post_data_get_link_real_rel', 'vc_gitem_post_data_get_link_rel_frontend_editor' );
}

View File

@@ -0,0 +1,243 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Return true value for filter 'wpb_vc_js_status_filter'.
* It allows to start backend editor on load.
* @return string
* @since 4.12
*
*/
function vc_set_default_content_for_post_type_wpb_vc_js_status_filter() {
return 'true';
}
/**
* Set default content by post type in editor.
*
* Data for post type templates stored in settings.
*
* @param $post_content
* @param $post
* @return null
* @throws \Exception
* @since 4.12
*
*/
function vc_set_default_content_for_post_type( $post_content, $post ) {
if ( ! empty( $post_content ) || ! vc_backend_editor()->isValidPostType( $post->post_type ) ) {
return $post_content;
}
$template_settings = new Vc_Setting_Post_Type_Default_Template_Field( 'general', 'default_template_post_type' );
$new_post_content = $template_settings->getTemplateByPostType( $post->post_type );
if ( null !== $new_post_content ) {
add_filter( 'wpb_vc_js_status_filter', 'vc_set_default_content_for_post_type_wpb_vc_js_status_filter' );
return $new_post_content;
}
return $post_content;
}
/**
* Default template for post types manager
*
* Class Vc_Setting_Post_Type_Default_Template_Field
*
* @since 4.12
*/
class Vc_Setting_Post_Type_Default_Template_Field {
protected $tab;
protected $key;
protected $post_types = false;
/**
* Vc_Setting_Post_Type_Default_Template_Field constructor.
* @param $tab
* @param $key
*/
public function __construct( $tab, $key ) {
$this->tab = $tab;
$this->key = $key;
add_action( 'vc_settings_tab-general', array(
$this,
'addField',
) );
}
/**
* @return string
*/
protected function getFieldName() {
return esc_html__( 'Default template for post types', 'js_composer' );
}
/**
* @return string
*/
protected function getFieldKey() {
require_once vc_path_dir( 'SETTINGS_DIR', 'class-vc-settings.php' );
return Vc_Settings::getFieldPrefix() . $this->key;
}
/**
* @param $type
* @return bool
*/
protected function isValidPostType( $type ) {
return post_type_exists( $type );
}
/**
* @return array|bool
*/
protected function getPostTypes() {
if ( false === $this->post_types ) {
require_once vc_path_dir( 'SETTINGS_DIR', 'class-vc-roles.php' );
$vc_roles = new Vc_Roles();
$this->post_types = $vc_roles->getPostTypes();
}
return $this->post_types;
}
/**
* @return array
*/
protected function getTemplates() {
return $this->getTemplatesEditor()->getAllTemplates();
}
/**
* @return bool|\Vc_Templates_Panel_Editor
*/
protected function getTemplatesEditor() {
return visual_composer()->templatesPanelEditor();
}
/**
* Get settings data for default templates
*
* @return array|mixed
*/
protected function get() {
require_once vc_path_dir( 'SETTINGS_DIR', 'class-vc-settings.php' );
$value = Vc_Settings::get( $this->key );
return $value ? $value : array();
}
/**
* Get template's shortcodes string
*
* @param $template_data
* @return string|null
*/
protected function getTemplate( $template_data ) {
$template = null;
$template_settings = preg_split( '/\:\:/', $template_data );
$template_id = $template_settings[1];
$template_type = $template_settings[0];
if ( ! isset( $template_id, $template_type ) || '' === $template_id || '' === $template_type ) {
return $template;
}
WPBMap::addAllMappedShortcodes();
if ( 'my_templates' === $template_type ) {
$saved_templates = get_option( $this->getTemplatesEditor()->getOptionName() );
$content = trim( $saved_templates[ $template_id ]['template'] );
$content = str_replace( '\"', '"', $content );
$pattern = get_shortcode_regex();
$template = preg_replace_callback( "/{$pattern}/s", 'vc_convert_shortcode', $content );
} else {
if ( 'default_templates' === $template_type ) {
$template_data = $this->getTemplatesEditor()->getDefaultTemplate( (int) $template_id );
if ( isset( $template_data['content'] ) ) {
$template = $template_data['content'];
}
} else {
$template_preview = apply_filters( 'vc_templates_render_backend_template_preview', $template_id, $template_type );
if ( (string) $template_preview !== (string) $template_id ) {
$template = $template_preview;
}
}
}
return $template;
}
/**
* @param $type
* @return string|null
*/
public function getTemplateByPostType( $type ) {
$value = $this->get();
return isset( $value[ $type ] ) ? $this->getTemplate( $value[ $type ] ) : null;
}
/**
* @param $settings
* @return mixed
*/
public function sanitize( $settings ) {
foreach ( $settings as $type => $template ) {
if ( empty( $template ) ) {
unset( $settings[ $type ] );
} elseif ( ! $this->isValidPostType( $type ) || ! $this->getTemplate( $template ) ) {
add_settings_error( $this->getFieldKey(), 1, esc_html__( 'Invalid template or post type.', 'js_composer' ), 'error' );
return $settings;
}
}
return $settings;
}
public function render() {
vc_include_template( 'pages/vc-settings/default-template-post-type.tpl.php', array(
'post_types' => $this->getPostTypes(),
'templates' => $this->getTemplates(),
'title' => $this->getFieldName(),
'value' => $this->get(),
'field_key' => $this->getFieldKey(),
) );
}
/**
* Add field settings page
*
* Method called by vc hook vc_settings_tab-general.
*/
public function addField() {
vc_settings()->addField( $this->tab, $this->getFieldName(), $this->key, array(
$this,
'sanitize',
), array(
$this,
'render',
) );
}
}
/**
* Start only for admin part with hooks
*/
if ( is_admin() ) {
/**
* Initialize Vc_Setting_Post_Type_Default_Template_Field
* Called by admin_init hook
*/
function vc_settings_post_type_default_template_field_init() {
new Vc_Setting_Post_Type_Default_Template_Field( 'general', 'default_template_post_type' );
}
add_filter( 'default_content', 'vc_set_default_content_for_post_type', 100, 2 );
add_action( 'admin_init', 'vc_settings_post_type_default_template_field_init', 8 );
}

View File

@@ -0,0 +1,102 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
global $vc_default_pointers, $vc_pointers;
$vc_default_pointers = (array) apply_filters( 'vc_pointers_list', array(
'vc_grid_item',
'vc_pointers_backend_editor',
'vc_pointers_frontend_editor',
) );
if ( is_admin() ) {
add_action( 'admin_enqueue_scripts', 'vc_pointer_load', 1000 );
}
function vc_pointer_load() {
global $vc_pointers;
// Don't run on WP < 3.3
if ( get_bloginfo( 'version' ) < '3.3' ) {
return;
}
$screen = get_current_screen();
$screen_id = $screen->id;
// Get pointers for this screen
$pointers = apply_filters( 'vc-ui-pointers', array() );
$pointers = apply_filters( 'vc_ui-pointers-' . $screen_id, $pointers );
if ( ! $pointers || ! is_array( $pointers ) ) {
return;
}
// Get dismissed pointers
$dismissed = explode( ',', (string) get_user_meta( get_current_user_id(), 'dismissed_wp_pointers', true ) );
$vc_pointers = array( 'pointers' => array() );
// Check pointers and remove dismissed ones.
foreach ( $pointers as $pointer_id => $pointer ) {
// Sanity check
if ( in_array( $pointer_id, $dismissed, true ) || empty( $pointer ) || empty( $pointer_id ) || empty( $pointer['name'] ) ) {
continue;
}
$pointer['pointer_id'] = $pointer_id;
// Add the pointer to $valid_pointers array
$vc_pointers['pointers'][] = $pointer;
}
// No valid pointers? Stop here.
if ( empty( $vc_pointers['pointers'] ) ) {
return;
}
wp_enqueue_style( 'wp-pointer' );
wp_enqueue_script( 'wp-pointer' );
// messages
$vc_pointers['texts'] = array(
'finish' => esc_html__( 'Finish', 'js_composer' ),
'next' => esc_html__( 'Next', 'js_composer' ),
'prev' => esc_html__( 'Prev', 'js_composer' ),
);
// Add pointer options to script.
wp_localize_script( 'wp-pointer', 'vcPointer', $vc_pointers );
}
/**
* Remove Vc pointers keys to show Tour markers again.
* @sine 4.5
*/
function vc_pointer_reset() {
global $vc_default_pointers;
vc_user_access()->checkAdminNonce()->validateDie()->wpAny( 'manage_options' )->validateDie()->part( 'settings' )->can( 'vc-general-tab' )->validateDie();
$pointers = (array) apply_filters( 'vc_pointers_list', $vc_default_pointers );
$prev_meta_value = get_user_meta( get_current_user_id(), 'dismissed_wp_pointers', true );
$dismissed = explode( ',', (string) $prev_meta_value );
if ( count( $dismissed ) > 0 && count( $pointers ) ) {
$meta_value = implode( ',', array_diff( $dismissed, $pointers ) );
update_user_meta( get_current_user_id(), 'dismissed_wp_pointers', $meta_value, $prev_meta_value );
}
wp_send_json( array( 'success' => true ) );
}
/**
* Reset tour guid
* @return bool
*/
function vc_pointers_is_dismissed() {
global $vc_default_pointers;
$pointers = (array) apply_filters( 'vc_pointers_list', $vc_default_pointers );
$prev_meta_value = get_user_meta( get_current_user_id(), 'dismissed_wp_pointers', true );
$dismissed = explode( ',', (string) $prev_meta_value );
return count( array_diff( $dismissed, $pointers ) ) < count( $dismissed );
}
add_action( 'wp_ajax_vc_pointer_reset', 'vc_pointer_reset' );

View File

@@ -0,0 +1,298 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
global $vc_grid_item_editor;
/**
* Creates new post type for grid_editor.
*
* @since 4.4
*/
function vc_grid_item_editor_create_post_type() {
if ( is_admin() ) {
require_once vc_path_dir( 'PARAMS_DIR', 'vc_grid_item/editor/class-vc-grid-item-editor.php' );
Vc_Grid_Item_Editor::createPostType();
add_action( 'vc_menu_page_build', 'vc_gitem_add_submenu_page' );
// TODO: add check vendor is active
add_filter( 'vc_vendor_qtranslate_enqueue_js_backend', 'vc_vendor_qtranslate_enqueue_js_backend_grid_editor' );
}
}
/**
* @since 4.5
*/
function vc_vendor_qtranslate_enqueue_js_backend_grid_editor() {
return true;
}
/**
* Set required objects to render editor for grid item
*
* @since 4.4
*/
function vc_grid_item_editor_init() {
global $vc_grid_item_editor;
require_once vc_path_dir( 'PARAMS_DIR', 'vc_grid_item/editor/class-vc-grid-item-editor.php' );
require_once vc_path_dir( 'PARAMS_DIR', 'vc_grid_item/class-wpb-map-grid-item.php' );
$vc_grid_item_editor = new Vc_Grid_Item_Editor();
$vc_grid_item_editor->addMetaBox();
add_action( 'wp_ajax_vc_grid_item_editor_load_template_preview', array(
&$vc_grid_item_editor,
'renderTemplatePreview',
) );
$vc_grid_item_editor->addHooksSettings();
}
/**
* Render preview for grid item
* @since 4.4
*/
function vc_grid_item_render_preview() {
vc_user_access()->checkAdminNonce()->validateDie()->wpAny( array(
'edit_post',
(int) vc_request_param( 'post_id' ),
) )->validateDie()->part( 'grid_builder' )->can()->validateDie();
require_once vc_path_dir( 'PARAMS_DIR', 'vc_grid_item/class-vc-grid-item.php' );
$grid_item = new Vc_Grid_Item();
$grid_item->mapShortcodes();
require_once vc_path_dir( 'PARAMS_DIR', 'vc_grid_item/editor/class-vc-grid-item-preview.php' );
$vcGridPreview = new Vc_Grid_Item_Preview();
add_filter( 'vc_gitem_template_attribute_post_image_background_image_css_value', array(
$vcGridPreview,
'addCssBackgroundImage',
) );
add_filter( 'vc_gitem_template_attribute_post_image_url_value', array(
$vcGridPreview,
'addImageUrl',
) );
add_filter( 'vc_gitem_template_attribute_post_image_html', array(
$vcGridPreview,
'addImage',
) );
add_filter( 'vc_gitem_attribute_featured_image_img', array(
$vcGridPreview,
'addPlaceholderImage',
) );
add_filter( 'vc_gitem_post_data_get_link_real_link', array(
$vcGridPreview,
'disableRealContentLink',
), 10, 4 );
add_filter( 'vc_gitem_post_data_get_link_link', array(
$vcGridPreview,
'disableContentLink',
), 10, 3 );
add_filter( 'vc_gitem_zone_image_block_link', array(
$vcGridPreview,
'disableGitemZoneLink',
) );
$vcGridPreview->render();
die();
}
/**
* Map grid element shortcodes.
*
* @since 4.5
*/
function vc_grid_item_map_shortcodes() {
require_once vc_path_dir( 'PARAMS_DIR', 'vc_grid_item/class-vc-grid-item.php' );
$grid_item = new Vc_Grid_Item();
$grid_item->mapShortcodes();
vc_mapper()->setCheckForAccess( false );
}
/**
* Get current post type
*
* @return null|string
*/
function vc_grid_item_get_post_type() {
$post_type = null;
if ( vc_request_param( 'post_type' ) ) {
$post_type = vc_request_param( 'post_type' );
} elseif ( vc_request_param( 'post' ) ) {
$post = get_post( vc_request_param( 'post' ) );
$post_type = $post instanceof WP_Post && $post->post_type ? $post->post_type : null;
}
return $post_type;
}
/**
* Check and Map grid element shortcodes if required.
* @since 4.5
*/
function vc_grid_item_editor_shortcodes() {
require_once vc_path_dir( 'PARAMS_DIR', 'vc_grid_item/editor/class-vc-grid-item-editor.php' );
// TODO: remove this because mapping can be based on post_type
if ( ( 'true' === vc_request_param( 'vc_grid_item_editor' ) || ( is_admin() && vc_grid_item_get_post_type() === Vc_Grid_Item_Editor::postType() ) && vc_user_access()
->wpAny( 'edit_posts', 'edit_pages' )->part( 'grid_builder' )->can()->get() ) ) {
global $vc_grid_item_editor;
add_action( 'vc_user_access_check-shortcode_edit', array(
&$vc_grid_item_editor,
'accessCheckShortcodeEdit',
), 10, 2 );
add_action( 'vc_user_access_check-shortcode_all', array(
&$vc_grid_item_editor,
'accessCheckShortcodeAll',
), 10, 2 );
vc_grid_item_map_shortcodes();
}
}
/**
* add action in admin for vc grid item editor manager
*/
add_action( 'init', 'vc_grid_item_editor_create_post_type' );
add_action( 'admin_init', 'vc_grid_item_editor_init' );
add_action( 'vc_after_init', 'vc_grid_item_editor_shortcodes' );
/**
* Call preview as ajax request is called.
*/
add_action( 'wp_ajax_vc_gitem_preview', 'vc_grid_item_render_preview', 5 );
/**
* Add WP ui pointers in grid element editor.
*/
if ( is_admin() ) {
add_filter( 'vc_ui-pointers-vc_grid_item', 'vc_grid_item_register_pointer' );
}
/**
* @param $pointers
* @return mixed
*/
function vc_grid_item_register_pointer( $pointers ) {
$screen = get_current_screen();
if ( 'add' === $screen->action ) {
$pointers['vc_grid_item'] = array(
'name' => 'vcPointersController',
'messages' => array(
array(
'target' => '#vc_templates-editor-button',
'options' => array(
'content' => sprintf( '<h3> %s </h3> <p> %s </p>', esc_html__( 'Start Here!', 'js_composer' ), esc_html__( 'Start easy - use predefined template as a starting point and modify it.', 'js_composer' ) ),
'position' => array(
'edge' => 'left',
'align' => 'center',
),
),
),
array(
'target' => '[data-vc-navbar-control="animation"]',
'options' => array(
'content' => sprintf( '<h3> %s </h3> <p> %s </p>', esc_html__( 'Use Animations', 'js_composer' ), esc_html__( 'Select animation preset for grid element. "Hover" state will be added next to the "Normal" state tab.', 'js_composer' ) ),
'position' => array(
'edge' => 'right',
'align' => 'center',
),
),
),
array(
'target' => '.vc_gitem_animated_block-shortcode',
'options' => array(
'content' => sprintf( '<h3> %s </h3> <p> %s </p>', esc_html__( 'Style Design Options', 'js_composer' ), esc_html__( 'Edit "Normal" state to set "Featured image" as a background, control zone sizing proportions and other design options (Height mode: Select "Original" to scale image without cropping).', 'js_composer' ) ),
'position' => array(
'edge' => 'bottom',
'align' => 'center',
),
),
),
array(
'target' => '[data-vc-gitem="add-c"][data-vc-position="top"]',
'options' => array(
'content' => sprintf( '<h3> %s </h3> <p> %s </p>', esc_html__( 'Extend Element', 'js_composer' ), esc_html__( 'Additional content zone can be added to grid element edges (Note: This zone can not be animated).', 'js_composer' ) ) . '<p><img src="' . esc_url( vc_asset_url( 'vc/gb_additional_content.png' ) ) . '" alt="" /></p>',
'position' => array(
'edge' => 'right',
'align' => 'center',
),
),
),
array(
'target' => '#wpadminbar',
'options' => array(
'content' => sprintf( '<h3> %s </h3> %s', esc_html__( 'Watch Video Tutorial', 'js_composer' ), '<p>' . esc_html__( 'Have a look how easy it is to work with grid element builder.', 'js_composer' ) . '</p>' . '<iframe width="500" height="281" src="https://www.youtube.com/embed/sBvEiIL6Blo" frameborder="0" allowfullscreen></iframe>' ),
'position' => array(
'edge' => 'top',
'align' => 'center',
),
'pointerClass' => 'vc_gitem-animated-block-pointer-video',
'pointerWidth' => '530',
),
),
),
);
}
return $pointers;
}
/**
* @return array|mixed|void
*/
function vc_gitem_content_shortcodes() {
require_once vc_path_dir( 'PARAMS_DIR', 'vc_grid_item/class-vc-grid-item.php' );
$grid_item = new Vc_Grid_Item();
$invalid_shortcodes = apply_filters( 'vc_gitem_zone_grid_item_not_content_shortcodes', array(
'vc_gitem',
'vc_gitem_animated_block',
'vc_gitem_zone',
'vc_gitem_zone_a',
'vc_gitem_zone_b',
'vc_gitem_zone_c',
'vc_gitem_row',
'vc_gitem_col',
) );
return array_diff( array_keys( $grid_item->shortcodes() ), $invalid_shortcodes );
}
/**
* @param $content
* @return false|int
*/
function vc_gitem_has_content( $content ) {
$tags = vc_gitem_content_shortcodes();
$regexp = vc_get_shortcode_regex( implode( '|', $tags ) );
return preg_match( '/' . $regexp . '/', $content );
}
/**
* Add sub page to WPBakery Page Builder pages
*
* @since 4.5
*/
function vc_gitem_add_submenu_page() {
if ( vc_user_access()->part( 'grid_builder' )->can()->get() ) {
$labels = Vc_Grid_Item_Editor::getPostTypesLabels();
add_submenu_page( VC_PAGE_MAIN_SLUG, $labels['name'], $labels['name'], 'edit_posts', 'edit.php?post_type=' . rawurlencode( Vc_Grid_Item_Editor::postType() ), '' );
}
}
/**
* Highlight Vc submenu.
* @since 4.5
*/
function vc_gitem_menu_highlight() {
global $parent_file, $submenu_file, $post_type;
require_once vc_path_dir( 'PARAMS_DIR', 'vc_grid_item/editor/class-vc-grid-item-editor.php' );
if ( Vc_Grid_Item_Editor::postType() === $post_type && defined( 'VC_PAGE_MAIN_SLUG' ) ) {
$parent_file = VC_PAGE_MAIN_SLUG;
$submenu_file = 'edit.php?post_type=' . rawurlencode( Vc_Grid_Item_Editor::postType() );
}
}
add_action( 'admin_head', 'vc_gitem_menu_highlight' );
function vc_gitem_set_mapper_check_access() {
if ( vc_user_access()->checkAdminNonce()->wpAny( 'edit_posts', 'edit_pages' )->part( 'grid_builder' )->can()->get() && 'true' === vc_post_param( 'vc_grid_item_editor' ) ) {
vc_mapper()->setCheckForAccess( false );
}
}
add_action( 'wp_ajax_vc_edit_form', 'vc_gitem_set_mapper_check_access' );

View File

@@ -0,0 +1,358 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
add_filter( 'attachment_fields_to_edit', 'vc_attachment_filter_field', 10, 2 );
add_filter( 'media_meta', 'vc_attachment_filter_media_meta', 10, 2 );
add_action( 'wp_ajax_vc_media_editor_add_image', 'vc_media_editor_add_image' );
add_action( 'wp_ajax_vc_media_editor_preview_image', 'vc_media_editor_preview_image' );
/**
* @return array
*/
function vc_get_filters() {
return array(
'antique' => esc_html__( 'Antique', 'js_composer' ),
'blackwhite' => esc_html__( 'Black & White', 'js_composer' ),
'boost' => esc_html__( 'Boost', 'js_composer' ),
'concentrate' => esc_html__( 'Concentrate', 'js_composer' ),
'country' => esc_html__( 'Country', 'js_composer' ),
'darken' => esc_html__( 'Darken', 'js_composer' ),
'dream' => esc_html__( 'Dream', 'js_composer' ),
'everglow' => esc_html__( 'Everglow', 'js_composer' ),
'forest' => esc_html__( 'Forest', 'js_composer' ),
'freshblue' => esc_html__( 'Fresh Blue', 'js_composer' ),
'frozen' => esc_html__( 'Frozen', 'js_composer' ),
'hermajesty' => esc_html__( 'Her Majesty', 'js_composer' ),
'light' => esc_html__( 'Light', 'js_composer' ),
'orangepeel' => esc_html__( 'Orange Peel', 'js_composer' ),
'rain' => esc_html__( 'Rain', 'js_composer' ),
'retro' => esc_html__( 'Retro', 'js_composer' ),
'sepia' => esc_html__( 'Sepia', 'js_composer' ),
'summer' => esc_html__( 'Summer', 'js_composer' ),
'tender' => esc_html__( 'Tender', 'js_composer' ),
'vintage' => esc_html__( 'Vintage', 'js_composer' ),
'washed' => esc_html__( 'Washed', 'js_composer' ),
);
}
/**
* Add Image Filter field to media uploader
*
* @param array $form_fields , fields to include in attachment form
* @param object $post , attachment record in database
*
* @return array $form_fields, modified form fields
*/
function vc_attachment_filter_field( $form_fields, $post ) {
// don't add filter field, if image already has filter applied
if ( get_post_meta( $post->ID, 'vc-applied-image-filter', true ) ) {
return $form_fields;
}
$options = vc_get_filters();
$html_options = '<option value="">' . esc_html__( 'None', 'js_composer' ) . '</option>';
foreach ( $options as $value => $title ) {
$html_options .= '<option value="' . esc_attr( $value ) . '">' . esc_html( $title ) . '</option>';
}
$form_fields['vc-image-filter'] = array(
'label' => '',
'input' => 'html',
'html' => '
<div style="display:none">
<span class="vc-filter-label">' . esc_html__( 'Image filter', 'js_composer' ) . '</span>
<select name="attachments[' . esc_attr( $post->ID ) . '][vc-image-filter]" id="attachments-' . esc_attr( $post->ID ) . '-vc-image-filter" data-vc-preview-image-filter="' . esc_attr( $post->ID ) . '">
' . $html_options . '
</select>
</div>',
'value' => get_post_meta( $post->ID, 'vc_image_filter', true ),
'helps' => '',
);
return $form_fields;
}
/**
* Apply filters to specified images
*
* If image(s) has filter specified via filters _POST param:
* 1) copy it
* 2) apply specified filter
* 3) return new image id
*
* Required _POST params:
* - array ids: array of attachment ids
*
* Optional _POST params:
* - array filters: mapped array of ids and filters to apply
*
*/
function vc_media_editor_add_image() {
vc_user_access()->checkAdminNonce()->validateDie()->wpAny( 'upload_files' )->validateDie();
require_once vc_path_dir( 'HELPERS_DIR', 'class-vc-image-filter.php' );
$response = array(
'success' => true,
'data' => array(
'ids' => array(),
),
);
$filters = (array) vc_post_param( 'filters', array() );
$ids = (array) vc_post_param( 'ids', array() );
if ( ! $ids ) {
wp_send_json( $response );
}
// default action is wp_handle_upload, which forces wp to check upload with is_uploaded_file()
// override action to anything else to skip security checks
$action = 'vc_handle_upload_imitation';
$file_key = 0;
$post_id = 0;
$post_data = array();
$overrides = array( 'action' => $action );
$_POST = array( 'action' => $action );
foreach ( $ids as $key => $attachment_id ) {
if ( ! empty( $filters[ $attachment_id ] ) ) {
$filter_name = $filters[ $attachment_id ];
} else {
continue;
}
$source_path = get_attached_file( $attachment_id );
if ( empty( $source_path ) ) {
continue;
}
$temp_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . basename( $source_path );
if ( ! copy( $source_path, $temp_path ) ) {
continue;
}
$extension = strtolower( pathinfo( $temp_path, PATHINFO_EXTENSION ) );
$mime_type = '';
switch ( $extension ) {
case 'jpeg':
case 'jpg':
$image = imagecreatefromjpeg( $temp_path );
$mime_type = 'image/jpeg';
break;
case 'png':
$image = imagecreatefrompng( $temp_path );
$mime_type = 'image/png';
break;
case 'gif':
$image = imagecreatefromgif( $temp_path );
$mime_type = 'image/gif';
break;
default:
$image = false;
}
if ( ! $image ) {
continue;
}
$Filter = new vcImageFilter( $image );
$Filter->$filter_name();
if ( ! vc_save_gd_resource( $Filter->getImage(), $temp_path ) ) {
continue;
}
$new_filename = basename( $temp_path, '.' . $extension ) . '-' . $filter_name . '.' . $extension;
$_FILES = array(
array(
'name' => $new_filename,
'type' => $mime_type,
'tmp_name' => $temp_path,
'error' => UPLOAD_ERR_OK,
'size' => filesize( $temp_path ),
),
);
$new_attachment_id = media_handle_upload( $file_key, $post_id, $post_data, $overrides );
if ( ! $new_attachment_id || is_wp_error( $new_attachment_id ) ) {
continue;
}
update_post_meta( $new_attachment_id, 'vc-applied-image-filter', $filter_name );
$ids[ $key ] = $new_attachment_id;
}
$response['data']['ids'] = $ids;
wp_send_json( $response );
}
/**
* Generate filter preview
*
* Preview url is generated as data uri (base64)
*
* Required _POST params:
* - string filter: filter name
* - int attachment_id: attachment id
*
* @return void Results are sent out as json
* @throws \Exception
*/
function vc_media_editor_preview_image() {
vc_user_access()->checkAdminNonce()->validateDie()->wpAny( 'upload_files' )->validateDie();
require_once vc_path_dir( 'HELPERS_DIR', 'class-vc-image-filter.php' );
$response = array(
'success' => true,
'data' => array(
'src' => '',
),
);
$filter_name = vc_post_param( 'filter', '' );
$attachment_id = vc_post_param( 'attachment_id', false );
$preferred_size = vc_post_param( 'preferred_size', 'medium' );
if ( ! $filter_name || ! $attachment_id ) {
wp_send_json( $response );
}
$attachment_path = get_attached_file( $attachment_id );
$attachment_details = wp_prepare_attachment_for_js( $attachment_id );
if ( ! isset( $attachment_details['sizes'][ $preferred_size ] ) ) {
$preferred_size = 'thumbnail';
}
$attachment_url = wp_get_attachment_image_src( $attachment_id, $preferred_size );
if ( empty( $attachment_path ) || empty( $attachment_url[0] ) ) {
wp_send_json( $response );
}
$source_path = dirname( $attachment_path ) . '/' . basename( $attachment_url[0] );
$image = vc_get_gd_resource( $source_path );
if ( ! $image ) {
wp_send_json( $response );
}
$Filter = new vcImageFilter( $image );
$Filter->$filter_name();
$extension = strtolower( pathinfo( $source_path, PATHINFO_EXTENSION ) );
ob_start();
switch ( $extension ) {
case 'jpeg':
case 'jpg':
imagejpeg( $Filter->getImage() );
break;
case 'png':
imagepng( $Filter->getImage() );
break;
case 'gif':
imagegif( $Filter->getImage() );
break;
}
$data = ob_get_clean();
// @codingStandardsIgnoreLine
$response['data']['src'] = 'data:image/' . $extension . ';base64,' . base64_encode( $data );
wp_send_json( $response );
}
/**
* Read file from disk as GD resource
*
* @param string $file
*
* @return bool|resource
*/
function vc_get_gd_resource( $file ) {
$extension = strtolower( pathinfo( $file, PATHINFO_EXTENSION ) );
switch ( $extension ) {
case 'jpeg':
case 'jpg':
return imagecreatefromjpeg( $file );
case 'png':
return imagecreatefrompng( $file );
case 'gif':
return imagecreatefromgif( $file );
}
return false;
}
/**
* Save GD resource to file
*
* @param resource $resource
* @param string $file
*
* @return bool
*/
function vc_save_gd_resource( $resource, $file ) {
$extension = strtolower( pathinfo( $file, PATHINFO_EXTENSION ) );
switch ( $extension ) {
case 'jpeg':
case 'jpg':
return imagejpeg( $resource, $file );
case 'png':
return imagepng( $resource, $file );
case 'gif':
return imagegif( $resource, $file );
}
return false;
}
/**
* Add "Filter: ..." meta field to attachment details box
*
* @param array $media_meta , meta to include in attachment form
* @param object $post , attachment record in database
*
* @return array|string
*/
function vc_attachment_filter_media_meta( $media_meta, $post ) {
$filter_name = get_post_meta( $post->ID, 'vc-applied-image-filter', true );
if ( ! $filter_name ) {
return $media_meta;
}
$filters = vc_get_filters();
if ( ! isset( $filters[ $filter_name ] ) ) {
return $media_meta;
}
$media_meta .= esc_html__( 'Filter:', 'js_composer' ) . ' ' . $filters[ $filter_name ];
return $media_meta;
}

View File

@@ -0,0 +1,29 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Build and enqueue js/css for automapper settings tab.
* @since 4.5
*/
function vc_automapper_init() {
if ( vc_user_access()->wpAny( 'manage_options' )->part( 'settings' )->can( 'vc-automapper-tab' )->get() ) {
vc_automapper()->addAjaxActions();
}
}
/**
* Returns automapper template.
*
* @return string
* @since 4.5
*/
function vc_page_automapper_build() {
return 'pages/vc-settings/vc-automapper.php';
}
// TODO: move to separate file in autoload
add_filter( 'vc_settings-render-tab-vc-automapper', 'vc_page_automapper_build' );
is_admin() && ( strpos( vc_request_param( 'action' ), 'vc_automapper' ) !== false || 'vc-automapper' === vc_get_param( 'page' ) ) && add_action( 'admin_init', 'vc_automapper_init' );

View File

@@ -0,0 +1,10 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
function vc_page_settings_custom_css_load() {
wp_enqueue_script( 'ace-editor', vc_asset_url( 'lib/bower/ace-builds/src-min-noconflict/ace.js' ), array( 'jquery' ), WPB_VC_VERSION, true );
}
add_action( 'vc-settings-render-tab-vc-custom_css', 'vc_page_settings_custom_css_load' );

View File

@@ -0,0 +1,140 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Used to check for current less version during page open
*
* @since 4.5
*/
add_action( 'vc_before_init', 'vc_check_for_custom_css_build' );
/**
* Function check is system has custom build of css
* and check it version in comparison with current VC version
*
* @since 4.5
*/
function vc_check_for_custom_css_build() {
$version = vc_settings()->getCustomCssVersion();
if ( vc_user_access()->wpAny( 'manage_options' )->part( 'settings' )->can( 'vc-color-tab' )
->get() && vc_settings()->useCustomCss() && ( ! $version || version_compare( WPB_VC_VERSION, $version, '<>' ) ) ) {
add_action( 'admin_notices', 'vc_custom_css_admin_notice' );
}
}
/**
* Display admin notice depending on current page
*
* @since 4.5
*/
function vc_custom_css_admin_notice() {
global $current_screen;
vc_settings()->set( 'compiled_js_composer_less', '' );
$class = 'notice notice-warning vc_settings-custom-design-notice';
$message_important = esc_html__( 'Important notice', 'js_composer' );
if ( is_object( $current_screen ) && isset( $current_screen->id ) && 'visual-composer_page_vc-color' === $current_screen->id ) {
$message = esc_html__( 'You have an outdated version of WPBakery Page Builder Design Options. It is required to review and save it.', 'js_composer' );
echo '<div class="' . esc_attr( $class ) . '"><p><strong>' . esc_html( $message_important ) . '</strong>: ' . esc_html( $message ) . '</p></div>';
} else {
$message = esc_html__( 'You have an outdated version of WPBakery Page Builder Design Options. It is required to review and save it.', 'js_composer' );
$btnClass = 'button button-primary button-large vc_button-settings-less';
echo '<div class="' . esc_attr( $class ) . '"><p><strong>' . esc_html( $message_important ) . '</strong>: ' . esc_html( $message ) . '</p>' . '<p>';
echo '<a ' . implode( ' ', array(
'href="' . esc_url( admin_url( 'admin.php?page=vc-color' ) ) . '"',
'class="' . esc_attr( $btnClass ) . '"',
'id="vc_less-save-button"',
'style="vertical-align: baseline;"',
// needed to fix ":active bug"
) ) . '>';
echo esc_html__( 'Open Design Options', 'js_composer' ) . '</a>';
echo '</p></div>';
}
}
/**
* @param $submitButtonAttributes
* @return mixed
*/
function vc_page_settings_tab_color_submit_attributes( $submitButtonAttributes ) {
$submitButtonAttributes['data-vc-less-path'] = vc_str_remove_protocol( vc_asset_url( 'less/js_composer.less' ) );
$submitButtonAttributes['data-vc-less-root'] = vc_str_remove_protocol( vc_asset_url( 'less' ) );
$submitButtonAttributes['data-vc-less-variables'] = wp_json_encode( apply_filters( 'vc_settings-less-variables', array(
// Main accent color:
'vc_grey' => array(
'key' => 'wpb_js_vc_color',
'default' => vc_settings()->getDefault( 'vc_color' ),
),
// Hover color
'vc_grey_hover' => array(
'key' => 'wpb_js_vc_color_hover',
'default' => vc_settings()->getDefault( 'vc_color_hover' ),
),
'vc_image_slider_link_active' => 'wpb_js_vc_color_hover',
// Call to action background color
'vc_call_to_action_bg' => 'wpb_js_vc_color_call_to_action_bg',
'vc_call_to_action_2_bg' => 'wpb_js_vc_color_call_to_action_bg',
'vc_call_to_action_border' => array(
'key' => 'wpb_js_vc_color_call_to_action_border',
// darken 5%
'default_key' => 'wpb_js_vc_color',
'modify_output' => array(
array(
'plain' => array(
'darken({{ value }}, 5%)',
),
),
),
),
// Google maps background color
'vc_google_maps_bg' => 'wpb_js_vc_color_google_maps_bg',
// Post slider caption background color
'vc_post_slider_caption_bg' => 'wpb_js_vc_color_post_slider_caption_bg',
// Progress bar background color
'vc_progress_bar_bg' => 'wpb_js_vc_color_progress_bar_bg',
// Separator border color
'vc_separator_border' => 'wpb_js_vc_color_separator_border',
// Tabs navigation background color
'vc_tab_bg' => 'wpb_js_vc_color_tab_bg',
// Active tab background color
'vc_tab_bg_active' => 'wpb_js_vc_color_tab_bg_active',
// Elements bottom margin
'vc_element_margin_bottom' => array(
'key' => 'wpb_js_margin',
'default' => vc_settings()->getDefault( 'margin' ),
),
// Grid gutter width
'grid-gutter-width' => array(
'key' => 'wpb_js_gutter',
'default' => vc_settings()->getDefault( 'gutter' ),
'modify_output' => array(
array(
'plain' => array(
'{{ value }}px',
),
),
),
),
'screen-sm-min' => array(
'key' => 'wpb_js_responsive_max',
'default' => vc_settings()->getDefault( 'responsive_max' ),
'modify_output' => array(
array(
'plain' => array(
'{{ value }}px',
),
),
),
),
) ) );
return $submitButtonAttributes;
}
function vc_page_settings_desing_options_load() {
add_filter( 'vc_settings-tab-submit-button-attributes-color', 'vc_page_settings_tab_color_submit_attributes' );
wp_enqueue_script( 'vc_less_js', vc_asset_url( 'lib/bower/lessjs/dist/less.min.js' ), array(), WPB_VC_VERSION, true );
}
add_action( 'vc-settings-render-tab-vc-color', 'vc_page_settings_desing_options_load' );

View File

@@ -0,0 +1,57 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* @param $tabs
* @return array
*/
function vc_settings_tabs_vc_roles( $tabs ) {
// inster after vc-general tab
if ( array_key_exists( 'vc-general', $tabs ) ) {
$new = array();
foreach ( $tabs as $key => $value ) {
$new[ $key ] = $value;
if ( 'vc-general' === $key ) {
$new['vc-roles'] = esc_html__( 'Role Manager', 'js_composer' );
}
}
$tabs = $new;
} else {
$tabs['vc-roles'] = esc_html__( 'Roles Manager', 'js_composer' );
}
return $tabs;
}
if ( ! is_network_admin() ) {
add_filter( 'vc_settings_tabs', 'vc_settings_tabs_vc_roles' );
}
/**
* @return string
*/
function vc_settings_render_tab_vc_roles() {
return 'pages/vc-settings/tab-vc-roles.php';
}
add_filter( 'vc_settings-render-tab-vc-roles', 'vc_settings_render_tab_vc_roles' );
function vc_roles_settings_save() {
if ( check_admin_referer( 'vc_settings-roles-action', 'vc_nonce_field' ) && current_user_can( 'manage_options' ) ) {
require_once vc_path_dir( 'SETTINGS_DIR', 'class-vc-roles.php' );
$vc_roles = new Vc_Roles();
$data = $vc_roles->save( vc_request_param( 'vc_roles', array() ) );
echo wp_json_encode( $data );
die();
}
}
add_action( 'wp_ajax_vc_roles_settings_save', 'vc_roles_settings_save' );
if ( 'vc-roles' === vc_get_param( 'page' ) ) {
function vc_settings_render_tab_vc_roles_scripts() {
wp_register_script( 'vc_accordion_script', vc_asset_url( 'lib/vc_accordion/vc-accordion.min.js' ), array( 'jquery' ), WPB_VC_VERSION, true );
}
add_action( 'admin_init', 'vc_settings_render_tab_vc_roles_scripts' );
}

View File

@@ -0,0 +1,68 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* @since 4.5
*/
function vc_page_css_enqueue() {
wp_enqueue_style( 'vc_page-css', vc_asset_url( 'css/js_composer_settings.min.css' ), array(), WPB_VC_VERSION );
}
/**
* Build group page objects.
*
* @param $slug
* @param $title
* @param $tab
*
* @return Vc_Pages_Group
* @since 4.5
*
*/
function vc_pages_group_build( $slug, $title, $tab = '' ) {
$vc_page_welcome_tabs = vc_get_page_welcome_tabs();
require_once vc_path_dir( 'CORE_DIR', 'class-vc-page.php' );
require_once vc_path_dir( 'CORE_DIR', 'class-vc-pages-group.php' );
// Create page.
if ( ! strlen( $tab ) ) {
$tab = $slug;
}
$page = new Vc_Page();
$page->setSlug( $tab )->setTitle( $title )->setTemplatePath( 'pages/' . $slug . '/' . $tab . '.php' );
// Create page group to stick with other in template.
$pages_group = new Vc_Pages_Group();
$pages_group->setSlug( $slug )->setPages( $vc_page_welcome_tabs )->setActivePage( $page )->setTemplatePath( 'pages/vc-welcome/index.php' );
return $pages_group;
}
/**
* @since 4.5
*/
function vc_menu_page_build() {
if ( vc_user_access()->wpAny( 'manage_options' )->part( 'settings' )->can( 'vc-general-tab' )->get() ) {
define( 'VC_PAGE_MAIN_SLUG', 'vc-general' );
} else {
define( 'VC_PAGE_MAIN_SLUG', 'vc-welcome' );
}
add_menu_page( esc_html__( 'WPBakery Page Builder', 'js_composer' ), esc_html__( 'WPBakery Page Builder', 'js_composer' ), 'edit_posts', VC_PAGE_MAIN_SLUG, null, vc_asset_url( 'vc/logo/wpb-logo-white_32.svg' ), 76 );
do_action( 'vc_menu_page_build' );
}
function vc_network_menu_page_build() {
if ( ! vc_is_network_plugin() ) {
return;
}
if ( vc_user_access()->wpAny( 'manage_options' )->part( 'settings' )->can( 'vc-general-tab' )->get() && ! is_main_site() ) {
define( 'VC_PAGE_MAIN_SLUG', 'vc-general' );
} else {
define( 'VC_PAGE_MAIN_SLUG', 'vc-welcome' );
}
add_menu_page( esc_html__( 'WPBakery Page Builder', 'js_composer' ), esc_html__( 'WPBakery Page Builder', 'js_composer' ), 'exist', VC_PAGE_MAIN_SLUG, null, vc_asset_url( 'vc/logo/wpb-logo-white_32.svg' ), 76 );
do_action( 'vc_network_menu_page_build' );
}
add_action( 'admin_menu', 'vc_menu_page_build' );
add_action( 'network_admin_menu', 'vc_network_menu_page_build' );

View File

@@ -0,0 +1,43 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
function vc_page_settings_render() {
$page = vc_get_param( 'page' );
do_action( 'vc_page_settings_render-' . $page );
vc_settings()->renderTab( $page );
}
function vc_page_settings_build() {
if ( ! vc_user_access()->wpAny( 'manage_options' )->get() ) {
return;
}
$tabs = vc_settings()->getTabs();
foreach ( $tabs as $slug => $title ) {
$has_access = vc_user_access()->part( 'settings' )->can( $slug . '-tab' )->get();
if ( $has_access ) {
$page = add_submenu_page( VC_PAGE_MAIN_SLUG, $title, $title, 'manage_options', $slug, 'vc_page_settings_render' );
add_action( 'load-' . $page, array(
vc_settings(),
'adminLoad',
) );
}
}
do_action( 'vc_page_settings_build' );
}
function vc_page_settings_admin_init() {
vc_settings()->initAdmin();
}
add_action( 'vc_menu_page_build', 'vc_page_settings_build' );
add_action( 'vc_network_menu_page_build', 'vc_page_settings_build' );
add_action( 'admin_init', 'vc_page_settings_admin_init' );
add_action( 'vc-settings-render-tab-vc-roles', 'vc_settings_enqueue_js' );
function vc_settings_enqueue_js() {
// enqueue accordion in vc-roles page only
wp_enqueue_script( 'vc_accordion_script' );
}

View File

@@ -0,0 +1,103 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Get welcome pages main slug.
*
* @return mixed|string
* @since 4.5
*/
function vc_page_welcome_slug() {
$vc_page_welcome_tabs = vc_get_page_welcome_tabs();
return isset( $vc_page_welcome_tabs ) ? key( $vc_page_welcome_tabs ) : '';
}
/**
* Build vc-welcome page block which will be shown after Vc installation.
*
* vc_filter: vc_page_welcome_render_capabilities
*
* @since 4.5
*/
function vc_page_welcome_render() {
$vc_page_welcome_tabs = vc_get_page_welcome_tabs();
$slug = vc_page_welcome_slug();
$tab_slug = vc_get_param( 'tab', $slug );
// If tab slug in the list please render;
if ( ! empty( $tab_slug ) && isset( $vc_page_welcome_tabs[ $tab_slug ] ) ) {
$pages_group = vc_pages_group_build( $slug, $vc_page_welcome_tabs[ $tab_slug ], $tab_slug );
$pages_group->render();
}
}
function vc_page_welcome_add_sub_page() {
// Add submenu page
$page = add_submenu_page( VC_PAGE_MAIN_SLUG, esc_html__( 'About', 'js_composer' ), esc_html__( 'About', 'js_composer' ), 'edit_posts', vc_page_welcome_slug(), 'vc_page_welcome_render' );
// Css for perfect styling.
add_action( 'admin_print_styles-' . $page, 'vc_page_css_enqueue' );
}
function vc_welcome_menu_hooks() {
$settings_tab_enabled = vc_user_access()->wpAny( 'manage_options' )->part( 'settings' )->can( 'vc-general-tab' )->get();
add_action( 'vc_menu_page_build', 'vc_page_welcome_add_sub_page', $settings_tab_enabled ? 11 : 1 );
}
function vc_welcome_menu_hooks_network() {
if ( ! vc_is_network_plugin() ) {
return;
}
$settings_tab_enabled = vc_user_access()->wpAny( 'manage_options' )->part( 'settings' )->can( 'vc-general-tab' )->get();
add_action( 'vc_network_menu_page_build', 'vc_page_welcome_add_sub_page', $settings_tab_enabled && ! is_main_site() ? 11 : 1 );
}
add_action( 'admin_menu', 'vc_welcome_menu_hooks', 9 );
add_action( 'network_admin_menu', 'vc_welcome_menu_hooks_network', 9 );
/**
* ====================
* Redirect to welcome page on plugin activation.
* ====================
*/
/**
* Set redirect transition on update or activation
* @since 4.5
*/
function vc_page_welcome_set_redirect() {
if ( ! is_network_admin() && ! vc_get_param( 'activate-multi' ) ) {
set_transient( '_vc_page_welcome_redirect', 1, 30 );
}
}
/**
* Do redirect if required on welcome page
* @since 4.5
*/
function vc_page_welcome_redirect() {
$redirect = get_transient( '_vc_page_welcome_redirect' );
delete_transient( '_vc_page_welcome_redirect' );
if ( $redirect ) {
wp_safe_redirect( admin_url( 'admin.php?page=' . rawurlencode( vc_page_welcome_slug() ) ) );
}
}
// Enables redirect on activation.
add_action( 'vc_activation_hook', 'vc_page_welcome_set_redirect' );
add_action( 'admin_init', 'vc_page_welcome_redirect' );
/**
* @return mixed|void
*/
function vc_get_page_welcome_tabs() {
global $vc_page_welcome_tabs;
$vc_page_welcome_tabs = apply_filters( 'vc_page-welcome-slugs-list', array(
'vc-welcome' => esc_html__( 'What\'s New', 'js_composer' ),
'vc-faq' => esc_html__( 'FAQ', 'js_composer' ),
'vc-resources' => esc_html__( 'Resources', 'js_composer' ),
) );
return $vc_page_welcome_tabs;
}

View File

@@ -0,0 +1,91 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Add WP ui pointers to backend editor.
*/
function vc_add_admin_pointer() {
if ( is_admin() ) {
foreach ( vc_editor_post_types() as $post_type ) {
add_filter( 'vc_ui-pointers-' . $post_type, 'vc_backend_editor_register_pointer' );
}
}
}
add_action( 'admin_init', 'vc_add_admin_pointer' );
/**
* @param $pointers
* @return mixed
*/
function vc_backend_editor_register_pointer( $pointers ) {
$screen = get_current_screen();
$block = false;
if ( method_exists( $screen, 'is_block_editor' ) ) {
if ( $screen->is_block_editor() ) {
$block = true;
}
}
if ( ! $block || 'add' === $screen->action ) {
$pointers['vc_pointers_backend_editor'] = array(
'name' => 'vcPointerController',
'messages' => array(
array(
'target' => '.composer-switch',
'options' => array(
'content' => sprintf( '<h3> %s </h3> <p> %s </p>', esc_html__( 'Welcome to WPBakery Page Builder', 'js_composer' ), esc_html__( 'Choose Backend or Frontend editor.', 'js_composer' ) ),
'position' => array(
'edge' => 'left',
'align' => 'center',
),
'buttonsEvent' => 'vcPointersEditorsTourEvents',
),
),
array(
'target' => '#vc_templates-editor-button, #vc-templatera-editor-button',
'options' => array(
'content' => sprintf( '<h3> %s </h3> <p> %s </p>', esc_html__( 'Add Elements', 'js_composer' ), esc_html__( 'Add new element or start with a template.', 'js_composer' ) ),
'position' => array(
'edge' => 'left',
'align' => 'center',
),
'buttonsEvent' => 'vcPointersEditorsTourEvents',
),
'closeEvent' => 'shortcodes:vc_row:add',
'showEvent' => 'backendEditor.show',
),
array(
'target' => '[data-vc-control="add"]:first',
'options' => array(
'content' => sprintf( '<h3> %s </h3> <p> %s </p>', esc_html__( 'Rows and Columns', 'js_composer' ), esc_html__( 'This is a row container. Divide it into columns and style it. You can add elements into columns.', 'js_composer' ) ),
'position' => array(
'edge' => 'left',
'align' => 'center',
),
'buttonsEvent' => 'vcPointersEditorsTourEvents',
),
'closeEvent' => 'click #wpb_visual_composer',
'showEvent' => 'shortcodeView:ready',
),
array(
'target' => '.wpb_column_container:first .wpb_content_element:first .vc_controls-cc',
'options' => array(
'content' => sprintf( '<h3> %s </h3> <p> %s <br/><br/> %s</p>', esc_html__( 'Control Elements', 'js_composer' ), esc_html__( 'You can edit your element at any time and drag it around your layout.', 'js_composer' ), sprintf( esc_html__( 'P.S. Learn more at our %sKnowledge Base%s.', 'js_composer' ), '<a href="https://kb.wpbakery.com" target="_blank">', '</a>' ) ),
'position' => array(
'edge' => 'left',
'align' => 'center',
),
'buttonsEvent' => 'vcPointersEditorsTourEvents',
),
'showCallback' => 'vcPointersShowOnContentElementControls',
'closeEvent' => 'click #wpb_visual_composer',
),
),
);
}
return $pointers;
}

View File

@@ -0,0 +1,77 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Add WP ui pointers to backend editor.
*/
function vc_frontend_editor_pointer() {
vc_is_frontend_editor() && add_filter( 'vc-ui-pointers', 'vc_frontend_editor_register_pointer' );
}
add_action( 'admin_init', 'vc_frontend_editor_pointer' );
/**
* @param $pointers
* @return mixed
*/
function vc_frontend_editor_register_pointer( $pointers ) {
global $post;
if ( is_object( $post ) && ! strlen( $post->post_content ) ) {
$pointers['vc_pointers_frontend_editor'] = array(
'name' => 'vcPointerController',
'messages' => array(
array(
'target' => '#vc_add-new-element',
'options' => array(
'content' => sprintf( '<h3> %s </h3> <p> %s </p>', esc_html__( 'Add Elements', 'js_composer' ), esc_html__( 'Add new element or start with a template.', 'js_composer' ) ),
'position' => array(
'edge' => 'top',
'align' => 'left',
),
'buttonsEvent' => 'vcPointersEditorsTourEvents',
),
'closeEvent' => 'shortcodes:add',
),
array(
'target' => '.vc_controls-out-tl:first',
'options' => array(
'content' => sprintf( '<h3> %s </h3> <p> %s </p>', esc_html__( 'Rows and Columns', 'js_composer' ), esc_html__( 'This is a row container. Divide it into columns and style it. You can add elements into columns.', 'js_composer' ) ),
'position' => array(
'edge' => 'left',
'align' => 'center',
),
'buttonsEvent' => 'vcPointersEditorsTourEvents',
),
'closeCallback' => 'vcPointersCloseInIFrame',
'showCallback' => 'vcPointersSetInIFrame',
),
array(
'target' => '.vc_controls-cc:first',
'options' => array(
'content' => sprintf( '<h3> %s </h3> <p> %s <br/><br/> %s</p>', esc_html__( 'Control Elements', 'js_composer' ), esc_html__( 'You can edit your element at any time and drag it around your layout.', 'js_composer' ), sprintf( esc_html__( 'P.S. Learn more at our %sKnowledge Base%s.', 'js_composer' ), '<a href="https://kb.wpbakery.com" target="_blank">', '</a>' ) ),
'position' => array(
'edge' => 'left',
'align' => 'center',
),
'buttonsEvent' => 'vcPointersEditorsTourEvents',
),
'closeCallback' => 'vcPointersCloseInIFrame',
'showCallback' => 'vcPointersSetInIFrame',
),
),
);
}
return $pointers;
}
function vc_page_editable_enqueue_pointer_scripts() {
if ( vc_is_page_editable() ) {
wp_enqueue_style( 'wp-pointer' );
wp_enqueue_script( 'wp-pointer' );
}
}
add_action( 'wp_enqueue_scripts', 'vc_page_editable_enqueue_pointer_scripts' );

View File

@@ -0,0 +1,261 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
add_action( 'wp_ajax_vc_action_save_settings_preset', 'vc_action_save_settings_preset' );
add_action( 'wp_ajax_vc_action_set_as_default_settings_preset', 'vc_action_set_as_default_settings_preset' );
add_action( 'wp_ajax_vc_action_delete_settings_preset', 'vc_action_delete_settings_preset' );
add_action( 'wp_ajax_vc_action_restore_default_settings_preset', 'vc_action_restore_default_settings_preset' );
add_action( 'wp_ajax_vc_action_get_settings_preset', 'vc_action_get_settings_preset' );
add_action( 'wp_ajax_vc_action_render_settings_preset_popup', 'vc_action_render_settings_preset_popup' );
add_action( 'wp_ajax_vc_action_render_settings_preset_title_prompt', 'vc_action_render_settings_preset_title_prompt' );
add_action( 'wp_ajax_vc_action_render_settings_templates_prompt', 'vc_action_render_settings_templates_prompt' );
add_action( 'vc_restore_default_settings_preset', 'vc_action_set_as_default_settings_preset', 10, 2 );
add_action( 'vc_register_settings_preset', 'vc_register_settings_preset', 10, 4 );
add_filter( 'vc_add_new_elements_to_box', 'vc_add_new_elements_to_box' );
add_filter( 'vc_add_new_category_filter', 'vc_add_new_category_filter' );
function vc_include_settings_preset_class() {
require_once vc_path_dir( 'AUTOLOAD_DIR', 'class-vc-settings-presets.php' );
}
/**
* @return Vc_Vendor_Preset
*/
function vc_vendor_preset() {
require_once vc_path_dir( 'AUTOLOAD_DIR', 'class-vc-vendor-presets.php' );
return Vc_Vendor_Preset::getInstance();
}
/**
* Save settings preset for specific shortcode
*
* Include freshly rendered html in response
*
* Required _POST params:
* - shortcode_name string
* - title string
* - data string params in json
* - is_default
*
* @since 4.7
*/
function vc_action_save_settings_preset() {
vc_include_settings_preset_class();
vc_user_access()->part( 'presets' )->checkStateAny( true, null )->validateDie(); // user must have permission to save presets
$id = Vc_Settings_Preset::saveSettingsPreset( vc_post_param( 'shortcode_name' ), vc_post_param( 'title' ), vc_post_param( 'data' ), vc_post_param( 'is_default' ) );
$response = array(
'success' => (bool) $id,
'html' => Vc_Settings_Preset::getRenderedSettingsPresetPopup( vc_post_param( 'shortcode_name' ) ),
'id' => $id,
);
wp_send_json( $response );
}
/**
* Set existing preset as default
*
* Include freshly rendered html in response
*
* Required _POST params:
* - id int
* - shortcode_name string
*
* @since 4.7
*/
function vc_action_set_as_default_settings_preset() {
vc_include_settings_preset_class();
vc_user_access()->part( 'presets' )->checkStateAny( true, null )->validateDie(); // user must have permission to set as default presets
$id = vc_post_param( 'id' );
$shortcode_name = vc_post_param( 'shortcode_name' );
$status = Vc_Settings_Preset::setAsDefaultSettingsPreset( $id, $shortcode_name );
$response = array(
'success' => $status,
'html' => Vc_Settings_Preset::getRenderedSettingsPresetPopup( $shortcode_name ),
);
wp_send_json( $response );
}
/**
* Unmark current default preset as default
*
* Include freshly rendered html in response
*
* Required _POST params:
* - shortcode_name string
*
* @since 4.7
*/
function vc_action_restore_default_settings_preset() {
vc_include_settings_preset_class();
vc_user_access()->part( 'presets' )->checkStateAny( true, null )->validateDie(); // user must have permission to restore presets
$shortcode_name = vc_post_param( 'shortcode_name' );
$status = Vc_Settings_Preset::setAsDefaultSettingsPreset( null, $shortcode_name );
$response = array(
'success' => $status,
'html' => Vc_Settings_Preset::getRenderedSettingsPresetPopup( $shortcode_name ),
);
wp_send_json( $response );
}
/**
* Delete specific settings preset
*
* Include freshly rendered html in response
*
* Required _POST params:
* - shortcode_name string
* - id int
*
* @since 4.7
*/
function vc_action_delete_settings_preset() {
vc_include_settings_preset_class();
vc_user_access()->part( 'presets' )->checkStateAny( true, null )->validateDie(); // user must have permission to delete presets
$default = get_post_meta( vc_post_param( 'id' ), '_vc_default', true );
$status = Vc_Settings_Preset::deleteSettingsPreset( vc_post_param( 'id' ) );
$response = array(
'success' => $status,
'default' => $default,
'html' => Vc_Settings_Preset::getRenderedSettingsPresetPopup( vc_post_param( 'shortcode_name' ) ),
);
wp_send_json( $response );
}
/**
* Get data for specific settings preset
*
* Required _POST params:
* - id int
*
* @since 4.7
*/
function vc_action_get_settings_preset() {
vc_include_settings_preset_class();
$data = Vc_Settings_Preset::getSettingsPreset( vc_post_param( 'id' ), true );
if ( false !== $data ) {
$response = array(
'success' => true,
'data' => $data,
);
} else {
$response = array(
'success' => false,
);
}
wp_send_json( $response );
}
/**
* Respond with rendered popup menu
*
* Required _POST params:
* - shortcode_name string
*
* @since 4.7
*/
function vc_action_render_settings_preset_popup() {
vc_include_settings_preset_class();
$html = Vc_Settings_Preset::getRenderedSettingsPresetPopup( vc_post_param( 'shortcode_name' ) );
$response = array(
'success' => true,
'html' => $html,
);
wp_send_json( $response );
}
/**
* Return rendered title prompt
*
* @since 4.7
*
*/
function vc_action_render_settings_preset_title_prompt() {
vc_user_access()->checkAdminNonce()->validateDie()->wpAny( 'edit_posts', 'edit_pages' )->validateDie()->part( 'presets' )->can()->validateDie();
ob_start();
vc_include_template( apply_filters( 'vc_render_settings_preset_title_prompt', 'editors/partials/prompt-presets.tpl.php' ) );
$html = ob_get_clean();
$response = array(
'success' => true,
'html' => $html,
);
wp_send_json( $response );
}
/**
* Return rendered template prompt
*/
function vc_action_render_settings_templates_prompt() {
vc_user_access()->checkAdminNonce()->validateDie()->wpAny( 'edit_posts', 'edit_pages' )->validateDie()->part( 'templates' )->can()->validateDie();
ob_start();
vc_include_template( apply_filters( 'vc_render_settings_preset_title_prompt', 'editors/partials/prompt-templates.tpl.php' ) );
$html = ob_get_clean();
$response = array(
'success' => true,
'html' => $html,
);
wp_send_json( $response );
}
/**
* Register (add) new vendor preset
*
* @since 4.8
*
* @param string $title
* @param string $shortcode
* @param array $params
* @param bool $default
*/
function vc_register_settings_preset( $title, $shortcode, $params, $default = false ) {
vc_vendor_preset()->add( $title, $shortcode, $params, $default );
}
/**
* @param $shortcodes
* @return array
* @throws \Exception
*/
function vc_add_new_elements_to_box( $shortcodes ) {
require_once vc_path_dir( 'AUTOLOAD_DIR', 'class-vc-settings-presets.php' );
return Vc_Settings_Preset::addVcPresetsToShortcodes( $shortcodes );
}
/**
* @param $cat
* @return array
*/
function vc_add_new_category_filter( $cat ) {
require_once vc_path_dir( 'AUTOLOAD_DIR', 'class-vc-settings-presets.php' );
return Vc_Settings_Preset::addPresetCategory( $cat );
}

View File

@@ -0,0 +1,280 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Class VcShortcodeAutoloader
*/
class VcShortcodeAutoloader {
private static $instance = null;
private static $config = null;
private static $cached = null;
/**
* @param bool $load_config
* @return \VcShortcodeAutoloader|null
*/
public static function getInstance( $load_config = true ) {
if ( null === self::$instance ) {
self::$instance = new VcShortcodeAutoloader( $load_config );
}
return self::$instance;
}
/**
* VcShortcodeAutoloader constructor.
* @param bool $load_config
*/
private function __construct( $load_config = true ) {
if ( ! $load_config ) {
return;
}
$config = array(
'classmap_file' => vc_path_dir( 'APP_ROOT', 'vc_classmap.json.php' ),
'shortcodes_dir' => vc_path_dir( 'SHORTCODES_DIR' ),
'root_dir' => vc_path_dir( 'APP_ROOT' ),
);
if ( is_file( $config['classmap_file'] ) ) {
$config['classmap'] = require $config['classmap_file'];
self::$cached = true;
} else {
$config['classmap'] = self::generateClassMap( $config['shortcodes_dir'] );
self::$cached = false;
}
self::$config = $config;
}
/**
* Include class dependencies
*
* @param string $class Class name
*
* @return string[] Included (if any) files
*/
public static function includeClass( $class ) {
// call the constructor (php 7.4 compat)
self::getInstance();
$class = strtolower( $class );
$files = array();
if ( self::$config['classmap'] ) {
$files = isset( self::$config['classmap'][ $class ] ) ? self::$config['classmap'][ $class ] : array();
}
if ( $files ) {
foreach ( $files as $k => $file ) {
if ( self::$cached ) {
$files[ $k ] = $file = self::$config['root_dir'] . DIRECTORY_SEPARATOR . $file;
}
if ( is_file( $file ) ) {
require_once $file;
}
}
}
return $files;
}
/**
* Find all classes defined in file
*
* @param string $file Full path to file
*
* @return string[]
*/
public static function extractClassNames( $file ) {
$classes = array();
// @codingStandardsIgnoreLine
$contents = file_get_contents( $file );
if ( ! $contents ) {
return $classes;
}
$tokens = token_get_all( $contents );
$class_token = false;
foreach ( $tokens as $token ) {
if ( is_array( $token ) ) {
if ( T_CLASS === $token[0] ) {
$class_token = true;
} elseif ( $class_token && T_STRING === $token[0] ) {
$classes[] = $token[1];
$class_token = false;
}
}
}
return $classes;
}
/**
* Extract all classes from file with their extends
*
* @param $file
*
* @return array Associative array where key is class name and value is parent class name (if any))
*/
public static function extractClassesAndExtends( $file ) {
$classes = array();
// @codingStandardsIgnoreLine
$contents = file_get_contents( $file );
if ( ! $contents ) {
return $classes;
}
// class Foo extends Bar {
preg_match_all( '/class\s+(\w+)\s+extends\s(\w+)\s+\{/i', $contents, $matches, PREG_SET_ORDER );
foreach ( $matches as $v ) {
$classes[ $v[1] ] = $v[2];
}
// class Foo {
preg_match_all( '/class\s+(\w+)\s+\{/i', $contents, $matches, PREG_SET_ORDER );
foreach ( $matches as $v ) {
$classes[ $v[1] ] = null;
}
return $classes;
}
/**
* Find file by class name
*
* Search is case-insensitive
*
* @param string $class
* @param string[]|string $dirs One or more directories where to look (recursive)
*
* @return string|false Full path to class file
*/
public static function findClassFile( $class, $dirs ) {
foreach ( (array) $dirs as $dir ) {
$Directory = new RecursiveDirectoryIterator( $dir );
$Iterator = new RecursiveIteratorIterator( $Directory );
$Regex = new RegexIterator( $Iterator, '/^.+\.php$/i', RecursiveRegexIterator::GET_MATCH );
$class = strtolower( $class );
foreach ( $Regex as $file => $object ) {
$classes = self::extractClassNames( $file );
if ( $classes && in_array( $class, array_map( 'strtolower', $classes ), true ) ) {
return $file;
}
}
}
return false;
}
/**
* Construct full dependency list of classes for each class in right order (including class itself)
*
* @param string[]|string $dirs Directories where to look (recursive)
*
* @return array Associative array where key is lowercase class name and value is array of files to include for
* that class to work
*/
public static function generateClassMap( $dirs ) {
$flat_map = array();
foreach ( (array) $dirs as $dir ) {
$Directory = new RecursiveDirectoryIterator( $dir );
$Iterator = new RecursiveIteratorIterator( $Directory );
$Regex = new RegexIterator( $Iterator, '/^.+\.php$/i', RecursiveRegexIterator::GET_MATCH );
foreach ( $Regex as $file => $object ) {
$classes = self::extractClassesAndExtends( $file );
foreach ( $classes as $class => $extends ) {
$class = strtolower( $class );
$extends = strtolower( $extends );
if ( in_array( $extends, array(
'wpbakeryshortcodescontainer',
'wpbakeryvisualcomposer',
'wpbakeryshortcode',
'wpbmap',
), true ) ) {
$extends = null;
}
$flat_map[ $class ] = array(
'class' => $class,
'file' => $file,
'extends' => $extends,
);
}
}
}
$map = array();
foreach ( $flat_map as $params ) {
$dependencies = array(
array(
'class' => $params['class'],
'file' => $params['file'],
),
);
if ( $params['extends'] ) {
$queue = array( $params['extends'] );
while ( $queue ) {
$current_class = array_pop( $queue );
$current_class = $flat_map[ $current_class ];
$dependencies[] = array(
'class' => $current_class['class'],
'file' => $current_class['file'],
);
if ( ! empty( $current_class['extends'] ) ) {
$queue[] = $current_class['extends'];
}
}
$map[ $params['class'] ] = array_reverse( $dependencies );
} else {
$map[ $params['class'] ] = $dependencies;
}
}
// simplify array
$classmap = array();
foreach ( $map as $class => $dependencies ) {
$classmap[ $class ] = array();
foreach ( $dependencies as $v ) {
$classmap[ $class ][] = str_replace( '\\', '/', $v['file'] );
}
}
return $classmap;
}
/**
* Regenerate and save class map file
*
* @param string[]|string $dirs Directories where to look (recursive)
* @param string $target Output file
*
* @return bool
*/
public static function saveClassMap( $dirs, $target ) {
if ( ! $target ) {
return false;
}
$classmap = self::generateClassMap( $dirs );
// @codingStandardsIgnoreLine
$code = '<?php return (array) json_decode(\'' . json_encode( $classmap ) . '\') ?>';
// @codingStandardsIgnoreLine
return (bool) file_put_contents( $target, $code );
}
}

View File

@@ -0,0 +1,83 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
if ( 'vc_edit_form' === vc_post_param( 'action' ) ) {
add_filter( 'vc_edit_form_fields_attributes_vc_single_image', 'vc_single_image_convert_old_link_to_new' );
}
/**
* Backward compatibility
*
* @param $atts
* @return mixed
* @since 4.6
*/
function vc_single_image_convert_old_link_to_new( $atts ) {
if ( empty( $atts['onclick'] ) && isset( $atts['img_link_large'] ) && 'yes' === $atts['img_link_large'] ) {
$atts['onclick'] = 'img_link_large';
unset( $atts['img_link_large'] );
} elseif ( empty( $atts['onclick'] ) && ( ! isset( $atts['img_link_large'] ) || 'yes' !== $atts['img_link_large'] ) ) {
unset( $atts['img_link_large'] );
}
if ( empty( $atts['onclick'] ) && ! empty( $atts['link'] ) ) {
$atts['onclick'] = 'custom_link';
}
return $atts;
}
add_action( 'wp_ajax_wpb_single_image_src', 'vc_single_image_src' );
function vc_single_image_src() {
vc_user_access()->checkAdminNonce()->validateDie()->wpAny( 'edit_posts', 'edit_pages' )->validateDie();
$image_id = (int) vc_post_param( 'content' );
$params = vc_post_param( 'params' );
$post_id = (int) vc_post_param( 'post_id' );
$img_size = vc_post_param( 'size' );
$img = '';
if ( ! empty( $params['source'] ) ) {
$source = $params['source'];
} else {
$source = 'media_library';
}
switch ( $source ) {
case 'media_library':
case 'featured_image':
if ( 'featured_image' === $source ) {
if ( $post_id && has_post_thumbnail( $post_id ) ) {
$img_id = get_post_thumbnail_id( $post_id );
} else {
$img_id = 0;
}
} else {
$img_id = preg_replace( '/[^\d]/', '', $image_id );
}
if ( ! $img_size ) {
$img_size = 'thumbnail';
}
if ( $img_id ) {
$img = wp_get_attachment_image_src( $img_id, $img_size );
if ( $img ) {
$img = $img[0];
}
}
break;
case 'external_link':
if ( ! empty( $params['custom_src'] ) ) {
$img = $params['custom_src'];
}
break;
}
echo esc_url( $img );
die();
}

View File

@@ -0,0 +1,13 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
function vc_navbar_undoredo() {
if ( vc_is_frontend_editor() || is_admin() ) {
require_once vc_path_dir( 'EDITORS_DIR', 'navbar/class-vc-navbar-undoredo.php' );
new Vc_Navbar_Undoredo();
}
}
add_action( 'admin_init', 'vc_navbar_undoredo' );

View File

@@ -0,0 +1,28 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* @since 4.4 vendors initialization moved to hooks in autoload/vendors.
*
* Used to initialize advanced custom fields vendor.
*/
add_action( 'acf/init', 'vc_init_vendor_acf' ); // pro version
add_action( 'acf/register_fields', 'vc_init_vendor_acf' ); // free version
add_action( 'plugins_loaded', 'vc_init_vendor_acf' );
add_action( 'after_setup_theme', 'vc_init_vendor_acf' ); // for themes
function vc_init_vendor_acf() {
if ( did_action( 'vc-vendor-acf-load' ) ) {
return;
}
include_once( ABSPATH . 'wp-admin/includes/plugin.php' ); // Require class-vc-wxr-parser-plugin.php to use is_plugin_active() below
if ( class_exists( 'acf' ) || is_plugin_active( 'advanced-custom-fields/acf.php' ) || is_plugin_active( 'advanced-custom-fields-pro/acf.php' ) ) {
require_once vc_path_dir( 'VENDORS_DIR', 'plugins/class-vc-vendor-advanced-custom-fields.php' );
$vendor = new Vc_Vendor_AdvancedCustomFields();
add_action( 'vc_after_set_mode', array(
$vendor,
'load',
) );
}
}

View File

@@ -0,0 +1,22 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* @since 4.4 vendors initialization moved to hooks in autoload/vendors.
*
* Used to initialize plugin contact form 7 vendor - fix load cf7 shortcode when in editor (frontend)
*/
add_action( 'plugins_loaded', 'vc_init_vendor_cf7' );
function vc_init_vendor_cf7() {
include_once( ABSPATH . 'wp-admin/includes/plugin.php' ); // Require class-vc-wxr-parser-plugin.php to use is_plugin_active() below
if ( is_plugin_active( 'contact-form-7/wp-contact-form-7.php' ) || defined( 'WPCF7_PLUGIN' ) ) {
require_once vc_path_dir( 'VENDORS_DIR', 'plugins/class-vc-vendor-contact-form7.php' );
$vendor = new Vc_Vendor_ContactForm7();
add_action( 'vc_after_set_mode', array(
$vendor,
'load',
) );
} // if contact form7 plugin active
}

View File

@@ -0,0 +1,106 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* @since 4.4 vendors initialization moved to hooks in autoload/vendors.
*
* Used to add gravity forms shortcode into WPBakery Page Builder
*/
add_action( 'plugins_loaded', 'vc_init_vendor_gravity_forms' );
function vc_init_vendor_gravity_forms() {
include_once( ABSPATH . 'wp-admin/includes/plugin.php' ); // Require class-vc-wxr-parser-plugin.php to use is_plugin_active() below
if ( is_plugin_active( 'gravityforms/gravityforms.php' ) || class_exists( 'RGForms' ) || class_exists( 'RGFormsModel' ) ) {
// Call on map
add_action( 'vc_after_init', 'vc_vendor_gravityforms_load' );
} // if gravityforms active
}
function vc_vendor_gravityforms_load() {
$gravity_forms_array[ esc_html__( 'No Gravity forms found.', 'js_composer' ) ] = '';
if ( class_exists( 'RGFormsModel' ) ) {
/** @noinspection PhpUndefinedClassInspection */
$gravity_forms = RGFormsModel::get_forms( 1, 'title' );
if ( $gravity_forms ) {
$gravity_forms_array = array( esc_html__( 'Select a form to display.', 'js_composer' ) => '' );
foreach ( $gravity_forms as $gravity_form ) {
$gravity_forms_array[ $gravity_form->title ] = $gravity_form->id;
}
}
}
vc_map( array(
'name' => esc_html__( 'Gravity Form', 'js_composer' ),
'base' => 'gravityform',
'icon' => 'icon-wpb-vc_gravityform',
'category' => esc_html__( 'Content', 'js_composer' ),
'description' => esc_html__( 'Place Gravity form', 'js_composer' ),
'params' => array(
array(
'type' => 'dropdown',
'heading' => esc_html__( 'Form', 'js_composer' ),
'param_name' => 'id',
'value' => $gravity_forms_array,
'save_always' => true,
'description' => esc_html__( 'Select a form to add it to your post or page.', 'js_composer' ),
'admin_label' => true,
),
array(
'type' => 'dropdown',
'heading' => esc_html__( 'Display Form Title', 'js_composer' ),
'param_name' => 'title',
'value' => array(
esc_html__( 'No', 'js_composer' ) => 'false',
esc_html__( 'Yes', 'js_composer' ) => 'true',
),
'save_always' => true,
'description' => esc_html__( 'Would you like to display the forms title?', 'js_composer' ),
'dependency' => array(
'element' => 'id',
'not_empty' => true,
),
),
array(
'type' => 'dropdown',
'heading' => esc_html__( 'Display Form Description', 'js_composer' ),
'param_name' => 'description',
'value' => array(
esc_html__( 'No', 'js_composer' ) => 'false',
esc_html__( 'Yes', 'js_composer' ) => 'true',
),
'save_always' => true,
'description' => esc_html__( 'Would you like to display the forms description?', 'js_composer' ),
'dependency' => array(
'element' => 'id',
'not_empty' => true,
),
),
array(
'type' => 'dropdown',
'heading' => esc_html__( 'Enable AJAX?', 'js_composer' ),
'param_name' => 'ajax',
'value' => array(
esc_html__( 'No', 'js_composer' ) => 'false',
esc_html__( 'Yes', 'js_composer' ) => 'true',
),
'save_always' => true,
'description' => esc_html__( 'Enable AJAX submission?', 'js_composer' ),
'dependency' => array(
'element' => 'id',
'not_empty' => true,
),
),
array(
'type' => 'textfield',
'heading' => esc_html__( 'Tab Index', 'js_composer' ),
'param_name' => 'tabindex',
'description' => esc_html__( '(Optional) Specify the starting tab index for the fields of this form. Leave blank if you\'re not sure what this is.',
'js_composer' ),
'dependency' => array(
'element' => 'id',
'not_empty' => true,
),
),
),
) );
}

View File

@@ -0,0 +1,89 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* @param $post
* @return bool
*/
function vcv_disable_gutenberg_for_classic_editor( $post ) {
return false;
}
/**
* @param \Vc_Settings $settings
*/
function vc_gutenberg_add_settings( $settings ) {
global $wp_version;
if ( function_exists( 'the_gutenberg_project' ) || version_compare( $wp_version, '4.9.8', '>' ) ) {
$settings->addField( 'general', esc_html__( 'Disable Gutenberg Editor', 'js_composer' ), 'gutenberg_disable', 'vc_gutenberg_sanitize_disable_callback', 'vc_gutenberg_disable_render_callback' );
}
}
/**
* @param $rules
*
* @return mixed
*/
function vc_gutenberg_sanitize_disable_callback( $rules ) {
return (bool) $rules;
}
/**
* Not responsive checkbox callback function
*/
function vc_gutenberg_disable_render_callback() {
$checked = ( $checked = get_option( 'wpb_js_gutenberg_disable' ) ) ? $checked : false;
?>
<label>
<input type="checkbox"<?php echo esc_attr( $checked ) ? ' checked' : ''; ?> value="1"
name="<?php echo 'wpb_js_gutenberg_disable' ?>">
<?php esc_html_e( 'Disable', 'js_composer' ) ?>
</label><br/>
<p
class="description indicator-hint"><?php esc_html_e( 'Disable Gutenberg Editor.', 'js_composer' ); ?></p>
<?php
}
/**
* @param $result
* @param $postType
* @return bool
*/
function vc_gutenberg_check_disabled( $result, $postType ) {
if ( 'wpb_gutenberg_param' === $postType ) {
return true;
}
if ( ! isset( $_GET['vcv-gutenberg-editor'] ) && ( get_option( 'wpb_js_gutenberg_disable' ) || vc_is_wpb_content() || isset( $_GET['classic-editor'] ) ) ) {
return false;
}
return $result;
}
/**
* @return bool
*/
function vc_is_wpb_content() {
$post = get_post();
if ( ! empty( $post ) && isset( $post->post_content ) && preg_match( '/\[vc_row/', $post->post_content ) ) {
return true;
}
return false;
}
function vc_gutenberg_map() {
global $wp_version;
if ( function_exists( 'the_gutenberg_project' ) || version_compare( $wp_version, '4.9.8', '>' ) ) {
vc_lean_map( 'vc_gutenberg', null, dirname( __FILE__ ) . '/shortcode-vc-gutenberg.php' );
}
}
add_filter( 'use_block_editor_for_post_type', 'vc_gutenberg_check_disabled', 10, 2 );
add_action( 'vc_settings_tab-general', 'vc_gutenberg_add_settings' );
add_action( 'init', 'vc_gutenberg_map' );
/** @see include/params/gutenberg/class-vc-gutenberg-param.php */
require_once vc_path_dir( 'PARAMS_DIR', 'gutenberg/class-vc-gutenberg-param.php' );
new Vc_Gutenberg_Param();

View File

@@ -0,0 +1,18 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* @since 4.4 vendors initialization moved to hooks in autoload/vendors.
*
* Used to initialize plugin jwplayer vendor for frontend editor.
*/
add_action( 'plugins_loaded', 'vc_init_vendor_jwplayer' );
function vc_init_vendor_jwplayer() {
if ( is_plugin_active( 'jw-player-plugin-for-wordpress/jwplayermodule.php' ) || defined( 'JWP6' ) || class_exists( 'JWP6_Plugin' ) ) {
require_once vc_path_dir( 'VENDORS_DIR', 'plugins/class-vc-vendor-jwplayer.php' );
$vendor = new Vc_Vendor_Jwplayer();
$vendor->load();
}
}

View File

@@ -0,0 +1,19 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* @since 4.4 vendors initialization moved to hooks in autoload/vendors.
*
* Used to initialize plugin layerslider vendor.
*/
add_action( 'plugins_loaded', 'vc_init_vendor_layerslider' );
function vc_init_vendor_layerslider() {
include_once( ABSPATH . 'wp-admin/includes/plugin.php' ); // Require class-vc-wxr-parser-plugin.php to use is_plugin_active() below
if ( is_plugin_active( 'LayerSlider/layerslider.php' ) || class_exists( 'LS_Sliders' ) || defined( 'LS_ROOT_PATH' ) ) {
require_once vc_path_dir( 'VENDORS_DIR', 'plugins/class-vc-vendor-layerslider.php' );
$vendor = new Vc_Vendor_Layerslider();
$vendor->load();
}
}

View File

@@ -0,0 +1,22 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* @since 4.4 vendors initialization moved to hooks in autoload/vendors.
*
* Used to initialize plugin mqtranslate vendor
*/
add_action( 'plugins_loaded', 'vc_init_vendor_mqtranslate' );
function vc_init_vendor_mqtranslate() {
include_once( ABSPATH . 'wp-admin/includes/plugin.php' ); // Require class-vc-wxr-parser-plugin.php to use is_plugin_active() below
if ( is_plugin_active( 'mqtranslate/mqtranslate.php' ) || function_exists( 'mqtranslate_activation_check' ) ) {
require_once vc_path_dir( 'VENDORS_DIR', 'plugins/class-vc-vendor-mqtranslate.php' );
$vendor = new Vc_Vendor_Mqtranslate();
add_action( 'vc_after_set_mode', array(
$vendor,
'load',
) );
}
}

View File

@@ -0,0 +1,22 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* @since 4.4 vendors initialization moved to hooks in autoload/vendors.
*
* Used to initialize plugin ninja forms vendor
*/
add_action( 'plugins_loaded', 'vc_init_vendor_ninja_forms' );
function vc_init_vendor_ninja_forms() {
include_once( ABSPATH . 'wp-admin/includes/plugin.php' ); // Require class-vc-wxr-parser-plugin.php to use is_plugin_active() below
if ( is_plugin_active( 'ninja-forms/ninja-forms.php' ) || defined( 'NINJA_FORMS_DIR' ) || function_exists( 'ninja_forms_get_all_forms' ) ) {
require_once vc_path_dir( 'VENDORS_DIR', 'plugins/class-vc-vendor-ninja-forms.php' );
$vendor = new Vc_Vendor_NinjaForms();
add_action( 'vc_after_set_mode', array(
$vendor,
'load',
) );
}
}

View File

@@ -0,0 +1,21 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* @since 4.4 vendors initialization moved to hooks in autoload/vendors.
*
* Used to initialize plugin qtranslate vendor.
*/
add_action( 'plugins_loaded', 'vc_init_vendor_qtranslatex' );
function vc_init_vendor_qtranslatex() {
if ( defined( 'QTX_VERSION' ) ) {
require_once vc_path_dir( 'VENDORS_DIR', 'plugins/class-vc-vendor-qtranslate-x.php' );
$vendor = new Vc_Vendor_QtranslateX();
add_action( 'vc_after_set_mode', array(
$vendor,
'load',
) );
}
}

View File

@@ -0,0 +1,22 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* @since 4.4 vendors initialization moved to hooks in autoload/vendors.
*
* Used to initialize plugin qtranslate vendor.
*/
add_action( 'plugins_loaded', 'vc_init_vendor_qtranslate' );
function vc_init_vendor_qtranslate() {
include_once( ABSPATH . 'wp-admin/includes/plugin.php' ); // Require class-vc-wxr-parser-plugin.php to use is_plugin_active() below
if ( is_plugin_active( 'qtranslate/qtranslate.php' ) || defined( 'QT_SUPPORTED_WP_VERSION' ) ) {
require_once vc_path_dir( 'VENDORS_DIR', 'plugins/class-vc-vendor-qtranslate.php' );
$vendor = new Vc_Vendor_Qtranslate();
add_action( 'vc_after_set_mode', array(
$vendor,
'load',
) );
}
}

View File

@@ -0,0 +1,19 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* @since 4.4 vendors initialization moved to hooks in autoload/vendors.
*
* Used to initialize plugin revslider vendor.
*/
add_action( 'plugins_loaded', 'vc_init_vendor_revslider' );
function vc_init_vendor_revslider() {
include_once( ABSPATH . 'wp-admin/includes/plugin.php' ); // Require class-vc-wxr-parser-plugin.php to use is_plugin_active() below
if ( is_plugin_active( 'revslider/revslider.php' ) || class_exists( 'RevSlider' ) ) {
require_once vc_path_dir( 'VENDORS_DIR', 'plugins/class-vc-vendor-revslider.php' );
$vendor = new Vc_Vendor_Revslider();
$vendor->load();
}
}

View File

@@ -0,0 +1,41 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
return array(
'name' => esc_html__( 'Gutenberg Editor', 'js_composer' ),
'icon' => 'vc_icon-vc-gutenberg',
'wrapper_class' => 'clearfix',
'category' => esc_html__( 'Content', 'js_composer' ),
'description' => esc_html__( 'Insert Gutenberg editor in your layout', 'js_composer' ),
'weight' => - 10,
'params' => array(
array(
'type' => 'gutenberg',
'holder' => 'div',
'heading' => esc_html__( 'Text', 'js_composer' ),
'param_name' => 'content',
'value' => '<!-- wp:paragraph --><p>Hello! This is the Gutenberg block you can edit directly from the WPBakery Page Builder.</p><!-- /wp:paragraph -->',
),
vc_map_add_css_animation(),
array(
'type' => 'el_id',
'heading' => esc_html__( 'Element ID', 'js_composer' ),
'param_name' => 'el_id',
'description' => sprintf( esc_html__( 'Enter element ID (Note: make sure it is unique and valid according to %sw3c specification%s).', 'js_composer' ), '<a href="https://www.w3schools.com/tags/att_global_id.asp" target="_blank">', '</a>' ),
),
array(
'type' => 'textfield',
'heading' => esc_html__( 'Extra class name', 'js_composer' ),
'param_name' => 'el_class',
'description' => esc_html__( 'Style particular content element differently - add a class name and refer to it in custom CSS.', 'js_composer' ),
),
array(
'type' => 'css_editor',
'heading' => esc_html__( 'CSS box', 'js_composer' ),
'param_name' => 'css',
'group' => esc_html__( 'Design Options', 'js_composer' ),
),
),
);

View File

@@ -0,0 +1,41 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* Add script for grid item add to card link
*
* @since 4.5
*/
function vc_woocommerce_add_to_cart_script() {
wp_enqueue_script( 'vc_woocommerce-add-to-cart-js', vc_asset_url( 'js/vendors/woocommerce-add-to-cart.js' ), array( 'wc-add-to-cart' ), WPB_VC_VERSION );
}
/**
* @since 4.4 vendors initialization moved to hooks in autoload/vendors.
*
* Used to initialize plugin WooCommerce vendor. (adds tons of WooCommerce shortcodes and some fixes)
*/
add_action( 'plugins_loaded', 'vc_init_vendor_woocommerce' );
function vc_init_vendor_woocommerce() {
include_once( ABSPATH . 'wp-admin/includes/plugin.php' ); // Require class-vc-wxr-parser-plugin.php to use is_plugin_active() below
if ( is_plugin_active( 'woocommerce/woocommerce.php' ) || class_exists( 'WooCommerce' ) ) {
require_once vc_path_dir( 'VENDORS_DIR', 'plugins/class-vc-vendor-woocommerce.php' );
$vendor = new Vc_Vendor_Woocommerce();
add_action( 'vc_after_set_mode', array(
$vendor,
'load',
) );
require_once vc_path_dir( 'VENDORS_DIR', 'plugins/woocommerce/grid-item-filters.php' );
// Add 'add to card' link to the list of Add link.
add_filter( 'vc_gitem_add_link_param', 'vc_gitem_add_link_param_woocommerce' );
// Filter to add link attributes for grid element shortcode.
add_filter( 'vc_gitem_post_data_get_link_link', 'vc_gitem_post_data_get_link_link_woocommerce', 10, 3 );
add_filter( 'vc_gitem_post_data_get_link_target', 'vc_gitem_post_data_get_link_target_woocommerce', 12, 2 );
add_filter( 'vc_gitem_post_data_get_link_real_link', 'vc_gitem_post_data_get_link_real_link_woocommerce', 10, 4 );
add_filter( 'vc_gitem_post_data_get_link_real_target', 'vc_gitem_post_data_get_link_real_target_woocommerce', 12, 3 );
add_filter( 'vc_gitem_zone_image_block_link', 'vc_gitem_zone_image_block_link_woocommerce', 10, 3 );
add_action( 'wp_enqueue_scripts', 'vc_woocommerce_add_to_cart_script' );
}
}

View File

@@ -0,0 +1,16 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
add_action( 'plugins_loaded', 'vc_init_vendor_wpml' );
function vc_init_vendor_wpml() {
if ( defined( 'ICL_SITEPRESS_VERSION' ) ) {
require_once vc_path_dir( 'VENDORS_DIR', 'plugins/class-vc-vendor-wpml.php' );
$vendor = new Vc_Vendor_WPML();
add_action( 'vc_after_set_mode', array(
$vendor,
'load',
) );
}
}

View File

@@ -0,0 +1,27 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
/**
* @since 4.4 vendors initialization moved to hooks in autoload/vendors.
*
* Used to initialize plugin yoast vendor.
*/
// 16 is required to be called after WPSEO_Admin_Init constructor. @since 4.9
add_action( 'plugins_loaded', 'vc_init_vendor_yoast', 16 );
function vc_init_vendor_yoast() {
include_once( ABSPATH . 'wp-admin/includes/plugin.php' ); // Require class-vc-wxr-parser-plugin.php to use is_plugin_active() below
if ( is_plugin_active( 'wordpress-seo/wp-seo.php' ) || class_exists( 'WPSEO_Metabox' ) ) {
require_once vc_path_dir( 'VENDORS_DIR', 'plugins/class-vc-vendor-yoast_seo.php' );
$vendor = new Vc_Vendor_YoastSeo();
if ( defined( 'WPSEO_VERSION' ) && version_compare( WPSEO_VERSION, '3.0.0' ) === - 1 ) {
add_action( 'vc_after_set_mode', array(
$vendor,
'load',
) );
} elseif ( is_admin() && 'vc_inline' === vc_action() ) {
$vendor->frontendEditorBuild();
}
}
}

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>';
}
}

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