Custom WPBakery elements not displaying in WP admin - php

I'm creating custom elements for WPBakery.
I have a folder called vc-elements which contains two files:
hero.php
text-image.php
On the WordPress admin side, I want both elements to be visible. To do this, in functions.php I'm running:
add_action( 'vc_before_init', 'vc_before_init_actions' );
function vc_before_init_actions() {
// Link to VC elements's folder
if( function_exists('vc_set_shortcodes_templates_dir') ){
vc_set_shortcodes_templates_dir( get_template_directory() . 'vc-elements' );
}
}
But in the admin side, neither of the two blocks show?
Previously I had:
function vc_before_init_actions() {
require_once( get_template_directory().'/vc-elements/hero.php' );
}
Which showed the hero block in the admin. But when I added:
function vc_before_init_actions() {
require_once( get_template_directory().'/vc-elements/hero.php' );
require_once( get_template_directory().'/vc-elements/text-image.php' );
}
In the admin side, the hero element is replaced by the text image element - only one shows at one time. Why's this?

Are you building this with a parent or child theme? I'm not sure about your markup.
Usually, when I add a custom module I need to check if the plugin exists..
<?php
/**
* Adds new shortcode "myprefix_say_hello" and registers it to
* the Visual Composer plugin
*
*/
if ( ! class_exists( 'EZ_VC_Product_Widget' ) ) {
class EZ_VC_Product_Widget {
/**
* Main constructor
*/
public function __construct() {
// Registers the shortcode in WordPress
add_shortcode( 'ez_product', array( 'EZ_VC_Product_Widget', 'output' ) );
// Map shortcode to Visual Composer
if ( function_exists( 'vc_lean_map' ) ) {
vc_lean_map( 'ez_product', array( 'EZ_VC_Product_Widget',
'map' ) );
}
}
/**
* Shortcode output
*/
public static function output( $atts, $content = null ) {
// Extract shortcode attributes (based on the vc_lean_map function - see next function)
extract( vc_map_get_attributes( 'ez_product', $atts ) );
// Define output
$product = wc_get_product($id);
if ( $id && $product) {
global $post;
$post = $product->get_post_data();
setup_postdata( $post );
ob_start();
get_template_part('template-parts/product-module');
wp_reset_postdata();
return ob_get_clean();
}
else
return '';
}
/**
* Map shortcode to VC
*
* This is an array of all your settings which become the shortcode attributes ($atts)
* for the output. See the link below for a description of all available parameters.
*
* #since 1.0.0
* #link https://kb.wpbakery.com/docs/inner-api/vc_map/
*/
public static function map() {
return array(
'name' => esc_html__( 'EZ Product', 'shopkeeper' ),
'description' => esc_html__( 'Shortcode outputs a single product.', 'shopkeeper' ),
'base' => 'ez_product',
"icon" => get_stylesheet_directory_uri() . "/vc_extend/ez_shortcode_icon.png",
'params' => array(
array(
'type' => 'autocomplete',
'heading' => esc_html__( 'Select identificator', 'js_composer' ),
'param_name' => 'id',
'description' => esc_html__( 'Input product ID or product SKU or product title to see suggestions', 'js_composer' ),
),
array(
'type' => 'hidden',
// This will not show on render, but will be used when defining value for autocomplete
'param_name' => 'sku',
),
),
);
}
}
}
add_action('vc_before_init', function(){
new EZ_VC_Product_Widget;
});
/**
* #action wp_ajax_vc_get_autocomplete_suggestion - since 4.4 used to
hook ajax requests for autocomplete suggestions
*/
add_action( 'wp_ajax_vc_get_autocomplete_suggestion',
'ez_vc_get_autocomplete_suggestion' );
/**
* #since 4.4
*/
function ez_vc_get_autocomplete_suggestion() {
vc_user_access()->checkAdminNonce()->validateDie()->wpAny(
'edit_posts', 'edit_pages' )->validateDie();
$query = vc_post_param( 'query' );
$shortcode = wp_strip_all_tags( vc_post_param( 'shortcode' ) );
if ( $shortcode == 'ez_product') {
$tag = 'product';//wp_strip_all_tags( vc_post_param( 'shortcode'
)
);
$param_name = vc_post_param( 'param' );
vc_render_suggestion( $query, $tag, $param_name );
exit;
}
}

Related

Adding Custom Tabs to My Account Page in WooCommerce [duplicate]

This function adds a tab named "Special Page" into "My Account" tab list:
add_filter( 'woocommerce_account_menu_items' , 'jc_menu_panel_nav' );
function jc_menu_panel_nav() {
$items = array(
'dashboard' => __( 'Dashboard', 'woocommerce' ),
'orders' => __( 'Orders', 'woocommerce' ),
'downloads' => __( 'Downloads', 'woocommerce' ),
'edit-address' => __( 'Addresses', 'woocommerce' ),
'payment-methods' => __( 'Payment Methods', 'woocommerce' ),
'edit-account' => __( 'Account Details', 'woocommerce' ),
'special-page' => __( 'Special Page', 'woocommerce' ), // My custom tab here
'customer-logout' => __( 'Logout', 'woocommerce' ),
);
return $items;
}
That results in this:
But the link points to my-account/special-page/, and naturally gives a 404 error.
How I can assign this URL to a file named special-page.php?
Finally I could solve the problem using a snippet provided for the same people of WooCommerce (There are more tips in that page). For anyone interested, paste all the following code in functions.php:
function my_custom_endpoints() {
add_rewrite_endpoint( 'special-page', EP_ROOT | EP_PAGES );
}
add_action( 'init', 'my_custom_endpoints' );
function my_custom_query_vars( $vars ) {
$vars[] = 'special-page';
return $vars;
}
add_filter( 'query_vars', 'my_custom_query_vars', 0 );
function my_custom_flush_rewrite_rules() {
flush_rewrite_rules();
}
add_action( 'wp_loaded', 'my_custom_flush_rewrite_rules' );
I think this way allows more control to order/renaming the menu:
function my_custom_my_account_menu_items( $items ) {
$items = array(
'dashboard' => __( 'Dashboard', 'woocommerce' ),
'orders' => __( 'Orders', 'woocommerce' ),
//'downloads' => __( 'Downloads', 'woocommerce' ),
//'edit-address' => __( 'Addresses', 'woocommerce' ),
//'payment-methods' => __( 'Payment Methods', 'woocommerce' ),
'edit-account' => __( 'Edit Account', 'woocommerce' ),
'special-page' => 'Special Page',
'customer-logout' => __( 'Logout', 'woocommerce' ),
);
return $items;
}
add_filter( 'woocommerce_account_menu_items', 'my_custom_my_account_menu_items' );
In the following function I included the file to maintain some "order", but it also admits direct code.
Be sure to place the special-page.php file in the myaccount folder.
function my_custom_endpoint_content() {
include 'woocommerce/myaccount/special-page.php';
}
add_action( 'woocommerce_account_special-page_endpoint', 'my_custom_endpoint_content' );
Important: Once did this, go to Dashboard > Settings > Permalinks and click "Save Settings" in order to flush rewrite rules (thanks #optimiertes)
Source: Tabbed My Account page
First my-account/special-page/ should be myaccount/special-page/ in woocommerce 2.6+.
This solution is Incomplete and I am still working On…
You can use first this hook:
add_action( 'init', 'add_wc_endpoint' );
function add_wc_endpoint(){
add_rewrite_endpoint( 'special-page', EP_ROOT | EP_PAGES );
}
Then filtering wc_get_templateto call your files when the request match your endpoint:
add_filter( 'wc_get_template', 'custom_vc_endpoint', 10, 5 );
function custom_vc_endpoint($located, $template_name, $args, $template_path, $default_path){
if( $template_name == 'myaccount/special-page.php' ){
global $wp_query;
if(isset($wp_query->query['special-page'])){
$located = get_template_directory() . '/woocommerce/myaccount/special-page.php';
}
}
return $located;
}
If you use a child theme, replace get_template_directory() by get_stylesheet_directory()… Paste this code in function.php file of your active child theme or theme.
To avoid a 404 error "page not found", you will need to refresh rewrite rules adding to your code:
flush_rewrite_rules();
Update: Finally Dario (the OP) found a working solution. Look at his answer.
References:
Tabbed My Account page (Official Woocommerce 2.6+): Creating new endpoints
How to add a new endpoint in woocommerce (old and incomplete)
There is a better way to use a template in your custom page in woocommerce:
function my_custom_endpoint_content() {
wc_get_template( 'myaccount/special-page.php' );
}
add_action( 'woocommerce_account_special-page_endpoint', 'my_custom_endpoint_content' );
this should work without using the wc_get_template filter.
You can add this code to your theme's function.php:
class My_Custom_My_Account_Endpoint {
/**
* Custom endpoint name.
*
* #var string
*/
public static $endpoint = 'special-page';
/**
* Plugin actions.
*/
public function __construct() {
// Actions used to insert a new endpoint in the WordPress.
add_action( 'init', array( $this, 'add_endpoints' ) );
add_filter( 'query_vars', array( $this, 'add_query_vars' ), 0 );
// Change the My Accout page title.
add_filter( 'the_title', array( $this, 'endpoint_title' ) );
// Insering your new tab/page into the My Account page.
add_filter( 'woocommerce_account_menu_items', array( $this, 'new_menu_items' ) );
add_action( 'woocommerce_account_' . self::$endpoint . '_endpoint', array( $this, 'endpoint_content' ) );
}
/**
* Register new endpoint to use inside My Account page.
*
* #see https://developer.wordpress.org/reference/functions/add_rewrite_endpoint/
*/
public function add_endpoints() {
add_rewrite_endpoint( self::$endpoint, EP_ROOT | EP_PAGES );
}
/**
* Add new query var.
*
* #param array $vars
* #return array
*/
public function add_query_vars( $vars ) {
$vars[] = self::$endpoint;
return $vars;
}
/**
* Set endpoint title.
*
* #param string $title
* #return string
*/
public function endpoint_title( $title ) {
global $wp_query;
$is_endpoint = isset( $wp_query->query_vars[ self::$endpoint ] );
if ( $is_endpoint && ! is_admin() && is_main_query() && in_the_loop() && is_account_page() ) {
// New page title.
$title = __( 'Special Page', 'woocommerce' );
remove_filter( 'the_title', array( $this, 'endpoint_title' ) );
}
return $title;
}
/**
* Insert the new endpoint into the My Account menu.
*
* #param array $items
* #return array
*/
public function new_menu_items( $items ) {
// Remove the logout menu item.
$logout = $items['customer-logout'];
unset( $items['customer-logout'] );
// Insert your custom endpoint.
$items[ self::$endpoint ] = __( 'Special Page', 'woocommerce' );
// Insert back the logout item.
$items['customer-logout'] = $logout;
return $items;
}
/**
* Endpoint HTML content.
*/
public function endpoint_content() {
include('woocommerce/myaccount/special-page.php');
}
/**
* Plugin install action.
* Flush rewrite rules to make our custom endpoint available.
*/
public static function install() {
flush_rewrite_rules();
}
}
new My_Custom_My_Account_Endpoint();
// Flush rewrite rules on plugin activation.
register_activation_hook( __FILE__, array( 'My_Custom_My_Account_Endpoint', 'install' ) );
If you don't know where is your theme's function.php:
1.Log in to the WordPress Admin interface
2.In the left sidebar, hover over Appearances, then click Theme Editor
3.In the right sidebar, click functions.php

WooCommerce/Wordpress/JS: Get data from post type then send that to JS then seperate that into inputs

Im currently trying to assemble a plugin for my client that allows them to pull a list of address from a custom-post-type then select which one they would like to ship to then add that to woocommerce's shipping fields, and also make it work with multiple shipping addresses.
I've attached my code below, i've hit a road block when it comes to getting the info into from PHP to the JS and breaking it down to output to the proper fields and output in HTML.
<?php
if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {
if ( ! class_exists( 'WC_MultiAddress' ) ) {
/**
* Localisation
**/
load_plugin_textdomain( 'WC_MultiAddress', false, dirname( plugin_basename( __FILE__ ) ) . '/' );
class WC_MultiAddress {
public function __construct() {
// called only after woocommerce has finished loading
add_action( 'woocommerce_init', array( &$this, 'woocommerce_loaded' ) );
// called after all plugins have loaded
add_action( 'plugins_loaded', array( &$this, 'plugins_loaded' ) );
// called just before the woocommerce template functions are included
add_action( 'init', array( &$this, 'include_template_functions' ), 20 );
// indicates the user is in the right page
if(is_page('checkout')){
add_filter( 'woocommerce_checkout_fields' , 'custom_override_checkout_fields' );
// Our hooked in function - $fields is passed via the filter!
function custom_override_checkout_fields( $fields ) {
unset($fields['address']['address_1']);
unset($fields['address']['address_2']);
return $fields;
}
function custom_override_checkout_fields( $fields ) {
$fields['shipping']['shipping_address'] = array(
'label' => __('Shipping Address', 'woocommerce'),
'placeholder' => _x('Add Full Street Address Here', 'placeholder', 'woocommerce'),
'required' => true,
'class' => array('form-control'),
'clear' => true
);
return $fields;
}
/**
* Display field value on the order edit page
*/
add_action( 'woocommerce_admin_order_data_after_shipping_address', 'my_custom_checkout_field_display_admin_order_meta', 10, 1 );
function my_custom_checkout_field_display_admin_order_meta($order){
echo '<p><strong>'.__('Shipping Address').':</strong> ' . get_post_meta( $order->get_id(), '_shipping_address', true ) . '</p>';
}
// indicates we are being served over ssl
if ( is_ssl() ) {
$shippings = array();
$args = array('post-type'=>'addressbook');
$query = New WP_Query($args);
if($query->have_posts()):while($query->have_posts()):$query->the_post();
$temp = array();
$temp['id'] = get_the_id();
$temp['fname'] = the_field('fname');
$temp['lname'] = the_field('lname');
$temp['email'] = the_field('email');
$temp['company'] = the_field('company');
$temp['addr1'] = the_field('address_line_1');
$temp['addr2'] = the_field('address_line_2');
$temp['city'] = the_field('city');
$temp['state'] = the_field('state');
$temp['zip'] = the_field('zip');
$shipping[] = $temp;
endwhile;endif;wp_reset_postdata();?>
<select id="address-select" class="form-control">
<?php foreach($shippings as $shipping){
extract($shipping);?>
<option value="<?php echo $id; ?>"><?php echo wp_trim_words($fname, 1) . $lname . ' ' . $company . ' ' . $addr1 . ' ' . $city . ' ' . $state;?></option>
<?php
}
</select>
<Script>
$("#address-select").on("change", function(){
//Code here
})
</Script>
<?php
}
add_filter( 'woocommerce_checkout_fields', 'custom_edit_checkout_fields' );
function custom_edit_checkout_fields( $fields ) {
// Change all attributes on a field
$fields['shipping']['shipping_address_1'] = array(
'label' => __('Shipping Address', 'woocommerce'),
'placeholder' => _x('123 Main St', 'placeholder', 'woocommerce'),
'required' => true,
'class' => array('form-control'),
'clear' => true,
'value' => $addr1
);
return $fields;
}
}
// take care of anything else that needs to be done immediately upon plugin instantiation, here in the constructor
}
/**
* Take care of anything that needs woocommerce to be loaded.
* For instance, if you need access to the $woocommerce global
*/
public function woocommerce_loaded() {
// ...
}
/**
* Take care of anything that needs all plugins to be loaded
*/
public function plugins_loaded() {
// ...
}
/**
* Override any of the template functions from woocommerce/woocommerce-template.php
* with our own template functions file
*/
public function include_template_functions() {
include( 'woocommerce-template.php' );
}
}
// finally instantiate our plugin class and add it to the set of globals
$GLOBALS['WC_MultiAddress'] = new WC_MultiAddress();
}
}

Add Custom Endpoint URL to WooCommerce [duplicate]

This function adds a tab named "Special Page" into "My Account" tab list:
add_filter( 'woocommerce_account_menu_items' , 'jc_menu_panel_nav' );
function jc_menu_panel_nav() {
$items = array(
'dashboard' => __( 'Dashboard', 'woocommerce' ),
'orders' => __( 'Orders', 'woocommerce' ),
'downloads' => __( 'Downloads', 'woocommerce' ),
'edit-address' => __( 'Addresses', 'woocommerce' ),
'payment-methods' => __( 'Payment Methods', 'woocommerce' ),
'edit-account' => __( 'Account Details', 'woocommerce' ),
'special-page' => __( 'Special Page', 'woocommerce' ), // My custom tab here
'customer-logout' => __( 'Logout', 'woocommerce' ),
);
return $items;
}
That results in this:
But the link points to my-account/special-page/, and naturally gives a 404 error.
How I can assign this URL to a file named special-page.php?
Finally I could solve the problem using a snippet provided for the same people of WooCommerce (There are more tips in that page). For anyone interested, paste all the following code in functions.php:
function my_custom_endpoints() {
add_rewrite_endpoint( 'special-page', EP_ROOT | EP_PAGES );
}
add_action( 'init', 'my_custom_endpoints' );
function my_custom_query_vars( $vars ) {
$vars[] = 'special-page';
return $vars;
}
add_filter( 'query_vars', 'my_custom_query_vars', 0 );
function my_custom_flush_rewrite_rules() {
flush_rewrite_rules();
}
add_action( 'wp_loaded', 'my_custom_flush_rewrite_rules' );
I think this way allows more control to order/renaming the menu:
function my_custom_my_account_menu_items( $items ) {
$items = array(
'dashboard' => __( 'Dashboard', 'woocommerce' ),
'orders' => __( 'Orders', 'woocommerce' ),
//'downloads' => __( 'Downloads', 'woocommerce' ),
//'edit-address' => __( 'Addresses', 'woocommerce' ),
//'payment-methods' => __( 'Payment Methods', 'woocommerce' ),
'edit-account' => __( 'Edit Account', 'woocommerce' ),
'special-page' => 'Special Page',
'customer-logout' => __( 'Logout', 'woocommerce' ),
);
return $items;
}
add_filter( 'woocommerce_account_menu_items', 'my_custom_my_account_menu_items' );
In the following function I included the file to maintain some "order", but it also admits direct code.
Be sure to place the special-page.php file in the myaccount folder.
function my_custom_endpoint_content() {
include 'woocommerce/myaccount/special-page.php';
}
add_action( 'woocommerce_account_special-page_endpoint', 'my_custom_endpoint_content' );
Important: Once did this, go to Dashboard > Settings > Permalinks and click "Save Settings" in order to flush rewrite rules (thanks #optimiertes)
Source: Tabbed My Account page
First my-account/special-page/ should be myaccount/special-page/ in woocommerce 2.6+.
This solution is Incomplete and I am still working On…
You can use first this hook:
add_action( 'init', 'add_wc_endpoint' );
function add_wc_endpoint(){
add_rewrite_endpoint( 'special-page', EP_ROOT | EP_PAGES );
}
Then filtering wc_get_templateto call your files when the request match your endpoint:
add_filter( 'wc_get_template', 'custom_vc_endpoint', 10, 5 );
function custom_vc_endpoint($located, $template_name, $args, $template_path, $default_path){
if( $template_name == 'myaccount/special-page.php' ){
global $wp_query;
if(isset($wp_query->query['special-page'])){
$located = get_template_directory() . '/woocommerce/myaccount/special-page.php';
}
}
return $located;
}
If you use a child theme, replace get_template_directory() by get_stylesheet_directory()… Paste this code in function.php file of your active child theme or theme.
To avoid a 404 error "page not found", you will need to refresh rewrite rules adding to your code:
flush_rewrite_rules();
Update: Finally Dario (the OP) found a working solution. Look at his answer.
References:
Tabbed My Account page (Official Woocommerce 2.6+): Creating new endpoints
How to add a new endpoint in woocommerce (old and incomplete)
There is a better way to use a template in your custom page in woocommerce:
function my_custom_endpoint_content() {
wc_get_template( 'myaccount/special-page.php' );
}
add_action( 'woocommerce_account_special-page_endpoint', 'my_custom_endpoint_content' );
this should work without using the wc_get_template filter.
You can add this code to your theme's function.php:
class My_Custom_My_Account_Endpoint {
/**
* Custom endpoint name.
*
* #var string
*/
public static $endpoint = 'special-page';
/**
* Plugin actions.
*/
public function __construct() {
// Actions used to insert a new endpoint in the WordPress.
add_action( 'init', array( $this, 'add_endpoints' ) );
add_filter( 'query_vars', array( $this, 'add_query_vars' ), 0 );
// Change the My Accout page title.
add_filter( 'the_title', array( $this, 'endpoint_title' ) );
// Insering your new tab/page into the My Account page.
add_filter( 'woocommerce_account_menu_items', array( $this, 'new_menu_items' ) );
add_action( 'woocommerce_account_' . self::$endpoint . '_endpoint', array( $this, 'endpoint_content' ) );
}
/**
* Register new endpoint to use inside My Account page.
*
* #see https://developer.wordpress.org/reference/functions/add_rewrite_endpoint/
*/
public function add_endpoints() {
add_rewrite_endpoint( self::$endpoint, EP_ROOT | EP_PAGES );
}
/**
* Add new query var.
*
* #param array $vars
* #return array
*/
public function add_query_vars( $vars ) {
$vars[] = self::$endpoint;
return $vars;
}
/**
* Set endpoint title.
*
* #param string $title
* #return string
*/
public function endpoint_title( $title ) {
global $wp_query;
$is_endpoint = isset( $wp_query->query_vars[ self::$endpoint ] );
if ( $is_endpoint && ! is_admin() && is_main_query() && in_the_loop() && is_account_page() ) {
// New page title.
$title = __( 'Special Page', 'woocommerce' );
remove_filter( 'the_title', array( $this, 'endpoint_title' ) );
}
return $title;
}
/**
* Insert the new endpoint into the My Account menu.
*
* #param array $items
* #return array
*/
public function new_menu_items( $items ) {
// Remove the logout menu item.
$logout = $items['customer-logout'];
unset( $items['customer-logout'] );
// Insert your custom endpoint.
$items[ self::$endpoint ] = __( 'Special Page', 'woocommerce' );
// Insert back the logout item.
$items['customer-logout'] = $logout;
return $items;
}
/**
* Endpoint HTML content.
*/
public function endpoint_content() {
include('woocommerce/myaccount/special-page.php');
}
/**
* Plugin install action.
* Flush rewrite rules to make our custom endpoint available.
*/
public static function install() {
flush_rewrite_rules();
}
}
new My_Custom_My_Account_Endpoint();
// Flush rewrite rules on plugin activation.
register_activation_hook( __FILE__, array( 'My_Custom_My_Account_Endpoint', 'install' ) );
If you don't know where is your theme's function.php:
1.Log in to the WordPress Admin interface
2.In the left sidebar, hover over Appearances, then click Theme Editor
3.In the right sidebar, click functions.php

Error in adding extra meta box for woocommerce

I'm adding extra meta boxes to be called inside tabs in front end. This is added inside add new product page.But it gives error saying: Warning:
call_user_func() expects parameter 1 to be a valid callback, class
'WC_Meta_Box_Product_Features_Advantages' not found in
C:\wamp\www\mysite\wp-admin\includes\template.php on line 1048
screenshot:
I simply followed the way short description meta box added. Thus, I created a class file in this location:
C:\wamp\www\mysite\wp-content\plugins\woocommerce\includes\admin\meta-boxes\class-wc-meta-box-features-advantages-.php
and the content looks like:
<?php
/**
* Product Features Advantages
*
* Replaces the standard excerpt box.
*
* #author WooThemes
* #category Admin
* #package WooCommerce/Admin/Meta Boxes
* #version 2.1.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
/**
* WC_Meta_Box_Product_Features_Advantages Class.
*/
class WC_Meta_Box_Product_Features_Advantages {
/**
* Output the metabox.
*
* #param WP_Post $post
*/
public static function output( $post ) {
$settings = array(
'textarea_name' => 'features_advantages',
'quicktags' => array( 'buttons' => 'em,strong,link' ),
'tinymce' => array(
'theme_advanced_buttons1' => 'bold,italic,strikethrough,separator,bullist,numlist,separator,blockquote,separator,justifyleft,justifycenter,justifyright,separator,link,unlink,separator,undo,redo,separator',
'theme_advanced_buttons2' => '',
),
'editor_css' => '<style>#wp-excerpt-editor-container .wp-editor-area{height:175px; width:100%;}</style>',
);
wp_editor( htmlspecialchars_decode( $post->post_excerpt ), 'features_advantages', apply_filters( 'woocommerce_product_features_advantages_editor_settings', $settings ) );
}
}
Also added few more lines here: C:\wamp\www\mysite\wp-content\plugins\woocommerce\includes\admin\class-wc-admin-meta-boxes.php inside add_meta_boxes() function.
add_meta_box( 'features_advantages', __( 'Product Features and Advantages', 'woocommerce' ), 'WC_Meta_Box_Product_Features_Advantages::output', 'product', 'normal' );
and this line inside remove_meta_boxes()
remove_meta_box( 'features_advantages', 'product', 'normal' );
you should add in functions.php file not in plugin folder
add this code in your current active theme functions.php:
add_action( 'add_meta_boxes', 'product_details_add' );
add_action( 'save_post', 'product_details_save' );
function product_details_add() {
add_meta_box( 'product_details', 'Product Details', 'product_details_call', 'product', 'normal', 'high' );
}
function product_details_call( $post ) {
// Use nonce for verification
wp_nonce_field( plugin_basename( __FILE__ ), 'product_details_noncename' );
$field_value = get_post_meta( $post->ID, 'product_details_meta', false );
wp_editor( $field_value[0], 'product_details_meta' );
}

Need help linking a button to a function in wordpress theme customizer

I have created a custom control for the theme customizer which is a simple button and label. I am going to be using it as a theme reset button that will clear the theme mod settings to their original state. Now that I have added the control and have it showing up on the customizer, I am not sure where I am supposed to add the code to reset the settings.
So far I have only created customizer settings for css and text changes. To remove the settings I will be using the remove theme mods function.
<?php remove_theme_mods() ?>
So my question is do is how exactly do I use this button to execute the remove_mods function as seen above? The documentation on that function is very minimal.
If there is another way to reset the theme mod settings to default and this is not the right approach than please chime in.
Here is the code I have created my custom button with.
function newtheme_customize_reset_control($wp_customize) {
/**
* Reset Control
*
*/
class newtheme_Customize_reset_Control extends WP_Customize_Control {
public $type = 'button';
public function render_content() {
?>
<label>
<span class="customize-control-title"><?php echo esc_html( $this->label ); ?></span>
<div>
<?php _e( 'Reset Settings' ); ?>
</div>
</label>
<?php
}
}
}
add_action( 'customize_register', 'newtheme_customize_reset_control', 1, 1 );
In theme customizer you can register your custom javascript to wordpress theme customizer
add_action('customize_preview_init', 'your_live_preview_function');
public static function your_live_preview_function() {
wp_enqueue_script(
'your-theme_customizer', //Give the script an ID
get_template_directory_uri() . '/js/your-customizer-javascript-file.js', //Define it's JS file
array('jquery', 'customize-preview'), //Define dependencies
rand(1, 1000), //Define a version (optional) (but I use it for development as random so don't have to worry about cache etc.
true //Specify whether to put in footer (leave this true)
);
}
and inside your javascript file you can do something like this
( function( $ ) {
wp.customize(
'your_reset_button_control_id',
function( value ) {
value.bind(
function( to ) {
jQuery.post( ajax_url,
{
action: 'your_ajax_action_for_calling_reset',
reset_value: to
},
function( response ) {
jQuery( '.reset-info' ).html( response );
}
);
}
);
}
);
} )( jQuery );
and inside ajax you can do something like this
add_action('wp_ajax_your_ajax_action_for_calling_reset', 'your_ajax_action_for_calling_reset_callback_function');
function your_ajax_action_for_calling_reset_callback_function(){
$reset_value = esc_attr($_POST['reset_value']);
if($reset_value){
remove_theme_mods() ;
}
}
Haaaaaa hope it helps.
The problem with using remove_theme_mods for showing defaults in the Customizer is
the Customizer is a preview which you can exit without saving,
the individual theme_mods are filtered, but not the entire theme_mod array
theme_mods includes menus and widgets.
I also wanted a reset button, but I chose instead to create a Preset control, and one of the presets is "defaults". This way uses a select, so there is no problem with the button not working (because bind is for value changes and buttons don't change their values).
The trick is to use ajax to retrieve the chosen preset, and then loop over the values in javascript, assigning them to the settings so that those changes will trigger the refresh of the preview. My code includes filters so that child themes can add in more options and presets. And the presets can be subsets of the options available.
Here is PHP for the Preset control (just a normal select, but a settingless control):
$wp_customize->add_control( 'option_presets', array(
'label' => __( 'Use preset theme options', 'mytheme' ),
'description' => __( 'Theme options will be set to the preset values.', 'mytheme' ),
'section' => 'mytheme_section',
'settings' => array(),
'type' => 'select',
'capability' => 'edit_theme_options',
'choices' => mytheme_option_presets_choices(),
) );
Here is the rest of the PHP functions.
/**
* Supply list of choices for option presets.
*/
function mytheme_option_presets_choices() {
return apply_filters( 'mytheme_option_presets_choices', array(
'none' => __( 'Select preset', 'mytheme' ),
'defaults' => __( 'Defaults', 'mytheme' ),
'dark' => __( 'Dark', 'mytheme' ),
) );
}
/**
* Sanitize an option preset choice.
*/
function mytheme_sanitize_option_presets_choice( $input ) {
$valid = mytheme_option_presets_choices();
return array_key_exists( $input, $valid ) ? $input : 'none';
}
/**
* Get the preset values for the chosen option preset.
*/
function mytheme_option_preset( $which ) {
$values = array();
if ( 'defaults' === $which ) {
$values = mytheme_default_values();
}
if ( 'dark' === $which ) {
$values = array(
'body_textcolor' => '#f9f7f7',
'background_color' => '#444244',
'header_textcolor' => '#bf9a07',
'area_classes' => array(
'sidebar' => 'semi-black',
'widgets' => 'box',
),
);
}
return apply_filters( 'mytheme_option_preset', $values, $which );
}
/**
* Add a nonce for Customizer for option presets.
*/
function mytheme_refresh_nonces( $nonces ) {
$nonces['mytheme-customize-presets'] = wp_create_nonce( 'mytheme-customize-presets' );
return $nonces;
}
add_filter( 'customize_refresh_nonces', 'mytheme_refresh_nonces' );
/**
* Ajax handler for supplying option preset values.
*/
function mytheme_ajax_option_preset_values() {
check_ajax_referer( 'mytheme-customize-presets', 'option_presets_nonce' );
if ( ! current_user_can( 'edit_theme_options' ) ) {
wp_die( -1 );
}
if ( empty( $_POST['option_preset'] ) ) {
wp_send_json_error( 'mytheme_missing_preset_parameter' );
}
$preset = sanitize_text_field( wp_unslash( $_POST['option_preset'] ) );
$values = mytheme_option_preset( $preset );
if ( empty( $values ) ) {
wp_send_json_error( array( 'message' => __( 'No preset found.', 'mytheme' ) ) );
}
else { // Flatten the array.
foreach ($values as $key => $avalue) {
if ( is_array( $avalue ) ) {
unset( $values[$key] );
foreach ($avalue as $subkey => $subvalue) {
$values[$key . '[' . $subkey . ']'] = $subvalue;
}
}
}
wp_send_json_success( array( 'values' => $values ) );
}
}
add_action( 'wp_ajax_mytheme_option_preset', 'mytheme_ajax_option_preset_values' );
And then just a little bit of Javascript to make the ajax request. This is queued on the 'customize_controls_enqueue_scripts' action. (I left out the display of the error message.)
wp.customize.control( 'option_presets', function( control ) {
control.element = new wp.customize.Element( control.container.find( 'select' ) );
control.element.bind( function( preset ) {
var request = wp.ajax.post( 'mytheme_option_preset', {
option_presets_nonce: wp.customize.settings.nonce['mytheme-customize-presets'],
wp_customize: 'on',
customize_theme: wp.customize.settings.theme.stylesheet,
option_preset: preset
} );
request.done( function( response ) {
_.each( response.values, function( value, id ) {
var setting = wp.customize( id );
if ( setting ) {
setting.set( value );
}
} );
} );
} );
} );

Categories