Пример #1
1
 public static function attribute_taxonomies()
 {
     global $woocommerce;
     if (!isset($woocommerce)) {
         return array();
     }
     $attributes = array();
     if (function_exists('wc_get_attribute_taxonomies')) {
         $attribute_taxonomies = wc_get_attribute_taxonomies();
     } else {
         $attribute_taxonomies = $woocommerce->get_attribute_taxonomies();
     }
     if (empty($attribute_taxonomies)) {
         return array();
     }
     foreach ($attribute_taxonomies as $attribute) {
         /* FIX TO WOOCOMMERCE 2.1 */
         if (function_exists('wc_attribute_taxonomy_name')) {
             $taxonomy = wc_attribute_taxonomy_name($attribute->attribute_name);
         } else {
             $taxonomy = $woocommerce->attribute_taxonomy_name($attribute->attribute_name);
         }
         if (taxonomy_exists($taxonomy)) {
             $attributes[] = $attribute->attribute_name;
         }
     }
     return $attributes;
 }
 /**
  * Constructor.
  */
 public function __construct()
 {
     // Category/term ordering
     add_action('create_term', array($this, 'create_term'), 5, 3);
     add_action('delete_term', array($this, 'delete_term'), 5);
     // Add form
     add_action('product_cat_add_form_fields', array($this, 'add_category_fields'));
     add_action('product_cat_edit_form_fields', array($this, 'edit_category_fields'), 10);
     add_action('created_term', array($this, 'save_category_fields'), 10, 3);
     add_action('edit_term', array($this, 'save_category_fields'), 10, 3);
     // Add columns
     add_filter('manage_edit-product_cat_columns', array($this, 'product_cat_columns'));
     add_filter('manage_product_cat_custom_column', array($this, 'product_cat_column'), 10, 3);
     // Taxonomy page descriptions
     add_action('product_cat_pre_add_form', array($this, 'product_cat_description'));
     add_action('product_shipping_class_pre_add_form', array($this, 'shipping_class_description'));
     $attribute_taxonomies = wc_get_attribute_taxonomies();
     if ($attribute_taxonomies) {
         foreach (array_keys($attribute_taxonomies) as $attribute) {
             add_action($attribute . '_pre_add_form', array($this, 'product_attribute_description'));
         }
     }
     // Maintain hierarchy of terms
     add_filter('wp_terms_checklist_args', array($this, 'disable_checked_ontop'));
 }
 /**
  * Load the restrictions from the database
  */
 private function LoadRestrictions()
 {
     if ($this->restrictions_loaded) {
         return;
     }
     // Attribute/Variation Restrictions
     $attribute_taxonomies = wc_get_attribute_taxonomies();
     $taxonomies = array();
     foreach ($attribute_taxonomies as $taxonomy) {
         $taxonomies[] = wc_attribute_taxonomy_name($taxonomy->attribute_name);
     }
     $restrictions = get_terms(array('taxonomy' => $taxonomies, 'meta_query' => array(array('key' => 'multiple_of', 'compare' => 'EXISTS')), 'hide_empty' => false));
     if (is_array($restrictions)) {
         foreach ($restrictions as $restriction) {
             $this->multiple_ofs_attributes[$restriction->term_id] = $this->GetMultipleOfForAttribute($restriction->term_id);
             if (!$this->multiple_ofs_attributes[$restriction->term_id]) {
                 unset($this->multiple_ofs_attributes[$restriction->term_id]);
             }
         }
     }
     // Category Restrictions
     $restrictions = get_terms(array('taxonomy' => 'product_cat', 'meta_query' => array(array('key' => 'cat_multiple_of', 'compare' => 'EXISTS')), 'hide_empty' => false));
     if (is_array($restrictions)) {
         foreach ($restrictions as $restriction) {
             $this->multiple_ofs_categories[$restriction->term_id] = $this->GetMultipleOfForCategory($restriction->term_id);
             if (!$this->multiple_ofs_categories[$restriction->term_id]) {
                 unset($this->multiple_ofs_categories[$restriction->term_id]);
             }
         }
     }
     $this->cart_must_be_multiple_of = intval(get_option('woocommerce_cart_multiple_of', 0));
     $this->restrictions_loaded = true;
 }
    /**
     * Automatic Set all Product Attribute as Compare Features
     *
     */
    public function automatic_add_features()
    {
        $current_db_version = get_option('woocommerce_db_version', null);
        if (version_compare($current_db_version, '2.1.0', '<') && null !== $current_db_version) {
            global $woocommerce;
            $top_variations = $woocommerce->get_attribute_taxonomies();
        } else {
            $top_variations = wc_get_attribute_taxonomies();
        }
        if ($top_variations) {
            foreach ($top_variations as $top_variation) {
                $check_existed = WC_Compare_Data::get_count("field_name='" . trim(addslashes($top_variation->attribute_label)) . "'");
                if ($check_existed < 1) {
                    $child_variations = get_terms(version_compare($current_db_version, '2.1.0', '<') && null !== $current_db_version ? $woocommerce->attribute_taxonomy_name($top_variation->attribute_name) : wc_attribute_taxonomy_name($top_variation->attribute_name), array('parent' => 0, 'hide_empty' => 0, 'hierarchical' => 0));
                    $default_value = '';
                    if (count($child_variations) > 0) {
                        $line = '';
                        foreach ($child_variations as $child_variation) {
                            $default_value .= $line . addslashes($child_variation->name);
                            $line = '
';
                        }
                    }
                    if (trim($default_value) != '') {
                        $feature_id = WC_Compare_Data::insert_row(array('field_name' => trim(addslashes($top_variation->attribute_label)), 'field_type' => 'checkbox', 'field_unit' => '', 'default_value' => $default_value));
                    } else {
                        $feature_id = WC_Compare_Data::insert_row(array('field_name' => trim(addslashes($top_variation->attribute_label)), 'field_type' => 'input-text', 'field_unit' => '', 'default_value' => ''));
                    }
                }
            }
        }
    }
Пример #5
0
 /**
  * Layered Nav Init
  *
  * @package    WooCommerce/Widgets
  * @access     public
  * @return void
  */
 public function woocommerce_layered_nav_init()
 {
     if (is_active_widget(false, false, 'yith-woo-ajax-navigation', true) && !is_admin()) {
         global $_chosen_attributes, $woocommerce;
         $_chosen_attributes = array();
         /* FIX TO WOOCOMMERCE 2.1 */
         $attibute_taxonomies = function_exists('wc_get_attribute_taxonomies') ? $attribute_taxonomies = wc_get_attribute_taxonomies() : ($attribute_taxonomies = $woocommerce->get_attribute_taxonomies());
         if ($attribute_taxonomies) {
             foreach ($attribute_taxonomies as $tax) {
                 $attribute = wc_sanitize_taxonomy_name($tax->attribute_name);
                 /* FIX TO WOOCOMMERCE 2.1 */
                 if (function_exists('wc_attribute_taxonomy_name')) {
                     $taxonomy = wc_attribute_taxonomy_name($attribute);
                 } else {
                     $taxonomy = $woocommerce->attribute_taxonomy_name($attribute);
                 }
                 $name = 'filter_' . $attribute;
                 $query_type_name = 'query_type_' . $attribute;
                 if (!empty($_GET[$name]) && taxonomy_exists($taxonomy)) {
                     $_chosen_attributes[$taxonomy]['terms'] = explode(',', $_GET[$name]);
                     if (empty($_GET[$query_type_name]) || !in_array(strtolower($_GET[$query_type_name]), array('and', 'or'))) {
                         $_chosen_attributes[$taxonomy]['query_type'] = apply_filters('woocommerce_layered_nav_default_query_type', 'and');
                     } else {
                         $_chosen_attributes[$taxonomy]['query_type'] = strtolower($_GET[$query_type_name]);
                     }
                 }
             }
         }
         if (version_compare(preg_replace('/-beta-([0-9]+)/', '', $woocommerce->version), '2.1', '<')) {
             add_filter('loop_shop_post_in', 'woocommerce_layered_nav_query');
         } else {
             add_filter('loop_shop_post_in', array(WC()->query, 'layered_nav_query'));
         }
     }
 }
Пример #6
0
 public function color_layered_nav_init()
 {
     if (!is_active_widget(false, false, 'woocommerce_layered_nav', true) && !is_admin()) {
         global $_chosen_attributes;
         $_chosen_attributes = array();
         $attribute_taxonomies = wc_get_attribute_taxonomies();
         if ($attribute_taxonomies) {
             foreach ($attribute_taxonomies as $tax) {
                 if ($tax->attribute_name == "color") {
                     $attribute = wc_sanitize_taxonomy_name($tax->attribute_name);
                     $taxonomy = wc_attribute_taxonomy_name($attribute);
                     $name = 'filter_' . $attribute;
                     $query_type_name = 'query_type_' . $attribute;
                     $taxonomy_exists = in_array($taxonomy, wc_get_attribute_taxonomy_names());
                     if (!empty($_GET[$name]) && $taxonomy_exists) {
                         $_chosen_attributes[$taxonomy]['terms'] = explode(',', $_GET[$name]);
                         if (empty($_GET[$query_type_name]) || !in_array(strtolower($_GET[$query_type_name]), array('and', 'or'))) {
                             $_chosen_attributes[$taxonomy]['query_type'] = apply_filters('woocommerce_layered_nav_default_query_type', 'and');
                         } else {
                             $_chosen_attributes[$taxonomy]['query_type'] = strtolower($_GET[$query_type_name]);
                         }
                     }
                 }
             }
         }
         $wc_query = new WC_Query();
         add_filter('loop_shop_post_in', array($wc_query, 'layered_nav_query'));
     }
 }
Пример #7
0
 /**
  * Register core taxonomies.
  */
 public static function register_taxonomies()
 {
     if (taxonomy_exists('product_type')) {
         return;
     }
     do_action('woocommerce_register_taxonomy');
     $permalinks = get_option('woocommerce_permalinks');
     register_taxonomy('product_type', apply_filters('woocommerce_taxonomy_objects_product_type', array('product')), apply_filters('woocommerce_taxonomy_args_product_type', array('hierarchical' => false, 'show_ui' => false, 'show_in_nav_menus' => false, 'query_var' => is_admin(), 'rewrite' => false, 'public' => false)));
     register_taxonomy('product_cat', apply_filters('woocommerce_taxonomy_objects_product_cat', array('product')), apply_filters('woocommerce_taxonomy_args_product_cat', array('hierarchical' => true, 'update_count_callback' => '_wc_term_recount', 'label' => __('Product Categories', 'woocommerce'), 'labels' => array('name' => __('Product Categories', 'woocommerce'), 'singular_name' => __('Product Category', 'woocommerce'), 'menu_name' => _x('Categories', 'Admin menu name', 'woocommerce'), 'search_items' => __('Search Product Categories', 'woocommerce'), 'all_items' => __('All Product Categories', 'woocommerce'), 'parent_item' => __('Parent Product Category', 'woocommerce'), 'parent_item_colon' => __('Parent Product Category:', 'woocommerce'), 'edit_item' => __('Edit Product Category', 'woocommerce'), 'update_item' => __('Update Product Category', 'woocommerce'), 'add_new_item' => __('Add New Product Category', 'woocommerce'), 'new_item_name' => __('New Product Category Name', 'woocommerce')), 'show_ui' => true, 'query_var' => true, 'capabilities' => array('manage_terms' => 'manage_product_terms', 'edit_terms' => 'edit_product_terms', 'delete_terms' => 'delete_product_terms', 'assign_terms' => 'assign_product_terms'), 'rewrite' => array('slug' => empty($permalinks['category_base']) ? _x('product-category', 'slug', 'woocommerce') : $permalinks['category_base'], 'with_front' => false, 'hierarchical' => true))));
     register_taxonomy('product_tag', apply_filters('woocommerce_taxonomy_objects_product_tag', array('product')), apply_filters('woocommerce_taxonomy_args_product_tag', array('hierarchical' => false, 'update_count_callback' => '_wc_term_recount', 'label' => __('Product Tags', 'woocommerce'), 'labels' => array('name' => __('Product Tags', 'woocommerce'), 'singular_name' => __('Product Tag', 'woocommerce'), 'menu_name' => _x('Tags', 'Admin menu name', 'woocommerce'), 'search_items' => __('Search Product Tags', 'woocommerce'), 'all_items' => __('All Product Tags', 'woocommerce'), 'edit_item' => __('Edit Product Tag', 'woocommerce'), 'update_item' => __('Update Product Tag', 'woocommerce'), 'add_new_item' => __('Add New Product Tag', 'woocommerce'), 'new_item_name' => __('New Product Tag Name', 'woocommerce'), 'popular_items' => __('Popular Product Tags', 'woocommerce'), 'separate_items_with_commas' => __('Separate Product Tags with commas', 'woocommerce'), 'add_or_remove_items' => __('Add or remove Product Tags', 'woocommerce'), 'choose_from_most_used' => __('Choose from the most used Product tags', 'woocommerce'), 'not_found' => __('No Product Tags found', 'woocommerce')), 'show_ui' => true, 'query_var' => true, 'capabilities' => array('manage_terms' => 'manage_product_terms', 'edit_terms' => 'edit_product_terms', 'delete_terms' => 'delete_product_terms', 'assign_terms' => 'assign_product_terms'), 'rewrite' => array('slug' => empty($permalinks['tag_base']) ? _x('product-tag', 'slug', 'woocommerce') : $permalinks['tag_base'], 'with_front' => false))));
     register_taxonomy('product_shipping_class', apply_filters('woocommerce_taxonomy_objects_product_shipping_class', array('product', 'product_variation')), apply_filters('woocommerce_taxonomy_args_product_shipping_class', array('hierarchical' => true, 'update_count_callback' => '_update_post_term_count', 'label' => __('Shipping Classes', 'woocommerce'), 'labels' => array('name' => __('Shipping Classes', 'woocommerce'), 'singular_name' => __('Shipping Class', 'woocommerce'), 'menu_name' => _x('Shipping Classes', 'Admin menu name', 'woocommerce'), 'search_items' => __('Search Shipping Classes', 'woocommerce'), 'all_items' => __('All Shipping Classes', 'woocommerce'), 'parent_item' => __('Parent Shipping Class', 'woocommerce'), 'parent_item_colon' => __('Parent Shipping Class:', 'woocommerce'), 'edit_item' => __('Edit Shipping Class', 'woocommerce'), 'update_item' => __('Update Shipping Class', 'woocommerce'), 'add_new_item' => __('Add New Shipping Class', 'woocommerce'), 'new_item_name' => __('New Shipping Class Name', 'woocommerce')), 'show_ui' => false, 'show_in_nav_menus' => false, 'query_var' => is_admin(), 'capabilities' => array('manage_terms' => 'manage_product_terms', 'edit_terms' => 'edit_product_terms', 'delete_terms' => 'delete_product_terms', 'assign_terms' => 'assign_product_terms'), 'rewrite' => false)));
     global $wc_product_attributes;
     $wc_product_attributes = array();
     if ($attribute_taxonomies = wc_get_attribute_taxonomies()) {
         foreach ($attribute_taxonomies as $tax) {
             if ($name = wc_attribute_taxonomy_name($tax->attribute_name)) {
                 $tax->attribute_public = absint(isset($tax->attribute_public) ? $tax->attribute_public : 1);
                 $label = !empty($tax->attribute_label) ? $tax->attribute_label : $tax->attribute_name;
                 $wc_product_attributes[$name] = $tax;
                 $taxonomy_data = array('hierarchical' => true, 'update_count_callback' => '_update_post_term_count', 'labels' => array('name' => $label, 'singular_name' => $label, 'search_items' => sprintf(__('Search %s', 'woocommerce'), $label), 'all_items' => sprintf(__('All %s', 'woocommerce'), $label), 'parent_item' => sprintf(__('Parent %s', 'woocommerce'), $label), 'parent_item_colon' => sprintf(__('Parent %s:', 'woocommerce'), $label), 'edit_item' => sprintf(__('Edit %s', 'woocommerce'), $label), 'update_item' => sprintf(__('Update %s', 'woocommerce'), $label), 'add_new_item' => sprintf(__('Add New %s', 'woocommerce'), $label), 'new_item_name' => sprintf(__('New %s', 'woocommerce'), $label)), 'show_ui' => false, 'query_var' => 1 === $tax->attribute_public, 'rewrite' => false, 'sort' => false, 'public' => 1 === $tax->attribute_public, 'show_in_nav_menus' => 1 === $tax->attribute_public && apply_filters('woocommerce_attribute_show_in_nav_menus', false, $name), 'capabilities' => array('manage_terms' => 'manage_product_terms', 'edit_terms' => 'edit_product_terms', 'delete_terms' => 'delete_product_terms', 'assign_terms' => 'assign_product_terms'));
                 if (1 === $tax->attribute_public) {
                     $taxonomy_data['rewrite'] = array('slug' => empty($permalinks['attribute_base']) ? '' : trailingslashit($permalinks['attribute_base']) . sanitize_title($tax->attribute_name), 'with_front' => false, 'hierarchical' => true);
                 }
                 register_taxonomy($name, apply_filters("woocommerce_taxonomy_objects_{$name}", array('product')), apply_filters("woocommerce_taxonomy_args_{$name}", $taxonomy_data));
             }
         }
         do_action('woocommerce_after_register_taxonomy');
     }
 }
 public static function attribute_taxonomies()
 {
     global $woocommerce;
     if (!isset($woocommerce)) {
         return array();
     }
     $attributes = array();
     if (function_exists('wc_get_attribute_taxonomies') && function_exists('wc_attribute_taxonomy_name')) {
         $attribute_taxonomies = wc_get_attribute_taxonomies();
         if (empty($attribute_taxonomies)) {
             return array();
         }
         foreach ($attribute_taxonomies as $attribute) {
             $tax = wc_attribute_taxonomy_name($attribute->attribute_name);
             if (taxonomy_exists($tax)) {
                 $attributes[$tax] = ucfirst($attribute->attribute_name);
             }
         }
     } else {
         $attribute_taxonomies = $woocommerce->get_attribute_taxonomies();
         if (empty($attribute_taxonomies)) {
             return array();
         }
         foreach ($attribute_taxonomies as $attribute) {
             $tax = $woocommerce->attribute_taxonomy_name($attribute->attribute_name);
             if (taxonomy_exists($tax)) {
                 $attributes[$tax] = ucfirst($attribute->attribute_name);
             }
         }
     }
     return $attributes;
 }
 public function pf_init_attribute_image()
 {
     global $woocommerce, $_wp_additional_image_sizes;
     $screen = get_current_screen();
     if (strpos($screen->id, 'pa_') !== false) {
         $this->taxonomy = $_REQUEST['taxonomy'];
         if (taxonomy_exists($_REQUEST['taxonomy'])) {
             $term_id = term_exists(isset($_REQUEST['tag_ID']) ? $_REQUEST['tag_ID'] : 0, $_REQUEST['taxonomy']);
             $term = 0;
             if ($term_id) {
                 $term = get_term($term_id, $_REQUEST['taxonomy']);
             }
             $this->image_size = apply_filters('woocommerce_get_pf_thumbs_image_size', $this->image_size, $_REQUEST['taxonomy'], $term_id);
         }
         $the_size = isset($_wp_additional_image_sizes[$this->image_size]) ? $_wp_additional_image_sizes[$this->image_size] : $_wp_additional_image_sizes['shop_thumbnail'];
         if (isset($the_size['width']) && isset($the_size['height'])) {
             $this->image_width = $the_size['width'];
             $this->image_height = $the_size['height'];
         } else {
             $this->image_width = 32;
             $this->image_height = 32;
         }
         $attribute_taxonomies = wc_get_attribute_taxonomies();
         if ($attribute_taxonomies) {
             foreach ($attribute_taxonomies as $tax) {
                 add_action('pa_' . $tax->attribute_name . '_add_form_fields', array(&$this, 'pf_add_attribute_image'), 10, 2);
                 add_action('pa_' . $tax->attribute_name . '_edit_form_fields', array(&$this, 'pf_edit_attribute_image'), 10, 2);
                 add_filter('manage_edit-pa_' . $tax->attribute_name . '_columns', array(&$this, 'pf_attribute_columns'));
                 add_filter('manage_pa_' . $tax->attribute_name . '_custom_column', array(&$this, 'pf_attribute_column'), 10, 3);
             }
         }
     }
 }
 public function init_form_fields()
 {
     global $woocommerce;
     $attribute_taxonomies = wc_get_attribute_taxonomies();
     $args = array('data_hook' => sanitize_text_field($_POST[$this->plugin_id . '_data_hook']) ?: get_option($this->plugin_id . '_data_hook'), 'dom_selector' => sanitize_text_field($_POST[$this->plugin_id . '_dom_selector']) ?: get_option($this->plugin_id . '_dom_selector'), 'data_selector' => sanitize_text_field($_POST[$this->plugin_id . '_data_selector']) ?: get_option($this->plugin_id . '_data_selector'));
     $this->form_fields = array('data_hook' => array('title' => __('<b>Place holder for variation data</b>', 'mp_wc_vdopp'), 'description' => __('Choose a CSS class or id where you want to hook variation data. For instance: .variations or .product_meta. Default value: .variations', 'mp_wc_vdopp'), 'type' => 'text', 'default' => $args['data_hook']), 'dom_selector' => array('title' => __('<b>DOM Selector</b>', 'mp_wc_vdopp'), 'description' => __('Define the selector that will trigger show data event. Default value: form.cart select', 'mp_wc_vdopp'), 'type' => 'text', 'default' => $args['dom_selector']), 'data_selector' => array('title' => __('<b>Data Selector</b>', 'mp_wc_vdopp'), 'description' => __('Choose the id/class of displayed data. Default value: .product_details', 'mp_wc_vdopp'), 'type' => 'text', 'default' => $args['data_selector']));
 }
 public static function wc_get_attribute_taxonomies()
 {
     global $woocommerce;
     if (self::is_wc_version_gte_2_1()) {
         return wc_get_attribute_taxonomies();
     } else {
         return $woocommerce->get_attribute_taxonomies();
     }
 }
/**
 * Get an array of product attribute taxonomies.
 *
 * @access public
 * @return array
 */
function wc_get_attribute_taxonomy_names()
{
    $taxonomy_names = array();
    $attribute_taxonomies = wc_get_attribute_taxonomies();
    if ($attribute_taxonomies) {
        foreach ($attribute_taxonomies as $tax) {
            $taxonomy_names[] = wc_attribute_taxonomy_name($tax->attribute_name);
        }
    }
    return $taxonomy_names;
}
Пример #13
0
 /**
  * Get all possible woocommerce attribute taxonomies
  *
  * @return mixed|void
  */
 function br_aapf_get_attributes()
 {
     $attribute_taxonomies = wc_get_attribute_taxonomies();
     $attributes = array();
     if ($attribute_taxonomies) {
         foreach ($attribute_taxonomies as $tax) {
             $attributes[wc_attribute_taxonomy_name($tax->attribute_name)] = $tax->attribute_label;
         }
     }
     return apply_filters('berocket_aapf_get_attributes', $attributes);
 }
 function adminAssets()
 {
     if (!$this->ourPage()) {
         return;
     }
     wp_enqueue_style('wc-attribute-sets', $this->url . '/assets/css/wc-attribute-sets.css');
     // Registers and adds the required assets to admin pages
     wp_enqueue_script('wc-attribute-sets-angularjs', $this->url . '/assets/js/angular.min.js', null, null, false);
     wp_enqueue_script('wc-attribute-sets-angularjs-route', $this->url . '/assets/js/angular-route.min.js', array('wc-attribute-sets-angularjs'), null, false);
     wp_enqueue_script('wc-attribute-sets-app', $this->url . '/assets/js/wc-attribute-sets-app.js', array('wc-attribute-sets-angularjs-route'), 1.0, false);
     wp_localize_script('wc-attribute-sets-app', 'wcAttributeSets', array('productsAttributes' => wc_get_attribute_taxonomies(), 'viewsUrl' => $this->url . '/views/app/', 'ajaxUrl' => admin_url('admin-ajax.php')));
 }
Пример #15
0
 /**
  * Make all attributes lables managed by polylang string translation
  *
  * @global \Polylang $polylang
  * @global \WooCommerce $woocommerce
  *
  * @return boolean false if polylang or woocommerce can not be found
  */
 public function manageAttrLablesTranslation()
 {
     global $polylang, $woocommerce;
     if (!$polylang || !$woocommerce) {
         return false;
     }
     $attrs = wc_get_attribute_taxonomies();
     $section = __('Woocommerce Attributes', 'woo-poly-integration');
     foreach ($attrs as $attr) {
         pll_register_string($attr->attribute_label, $attr->attribute_label, $section);
     }
 }
 /**
  * Init settings after post types are registered.
  */
 public function init_settings()
 {
     $attribute_array = array();
     $attribute_taxonomies = wc_get_attribute_taxonomies();
     if ($attribute_taxonomies) {
         foreach ($attribute_taxonomies as $tax) {
             if (taxonomy_exists(wc_attribute_taxonomy_name($tax->attribute_name))) {
                 $attribute_array[$tax->attribute_name] = $tax->attribute_name;
             }
         }
     }
     $this->settings = array('title' => array('type' => 'text', 'std' => __('Filter by', 'woocommerce'), 'label' => __('Title', 'woocommerce')), 'attribute' => array('type' => 'select', 'std' => '', 'label' => __('Attribute', 'woocommerce'), 'options' => $attribute_array), 'display_type' => array('type' => 'select', 'std' => 'list', 'label' => __('Display type', 'woocommerce'), 'options' => array('list' => __('List', 'woocommerce'), 'dropdown' => __('Dropdown', 'woocommerce'))), 'query_type' => array('type' => 'select', 'std' => 'and', 'label' => __('Query type', 'woocommerce'), 'options' => array('and' => __('AND', 'woocommerce'), 'or' => __('OR', 'woocommerce'))));
 }
Пример #17
0
 protected function get_woo_attribute_taxonomies()
 {
     $attribute_array = array();
     $attribute_taxonomies = wc_get_attribute_taxonomies();
     if ($attribute_taxonomies) {
         foreach ($attribute_taxonomies as $tax) {
             if (taxonomy_exists(wc_attribute_taxonomy_name($tax->attribute_name))) {
                 $attribute_array[$tax->attribute_name] = $tax->attribute_name;
             }
         }
     }
     return $attribute_array;
 }
Пример #18
0
function pw_attribute_image()
{
    global $woocommerce, $_wp_additional_image_sizes;
    $screen = get_current_screen();
    $attribute_taxonomies = wc_get_attribute_taxonomies();
    if ($attribute_taxonomies) {
        foreach ($attribute_taxonomies as $tax) {
            add_action('pa_' . $tax->attribute_name . '_add_form_fields', 'pw_add_attribute_image', 10, 2);
            add_action('pa_' . $tax->attribute_name . '_edit_form_fields', 'pw_edit_att_image', 10, 2);
            add_filter('manage_edit-pa_' . $tax->attribute_name . '_columns', 'pw_attribute_columns');
            add_filter('manage_pa_' . $tax->attribute_name . '_custom_column', 'pw_attribute_column', 10, 3);
        }
    }
}
 public function wcva_setup_texonomy_based_fields()
 {
     global $woocommerce;
     $woo_version = wcva_get_woo_version_number();
     if ($woo_version < 2.1) {
         $createdattributes = $woocommerce->get_attribute_taxonomies();
     } else {
         $createdattributes = wc_get_attribute_taxonomies();
     }
     foreach ($createdattributes as $attribute) {
         add_action('pa_' . $attribute->attribute_name . '_add_form_fields', array($this, 'add_category_fields'));
         add_action('pa_' . $attribute->attribute_name . '_edit_form_fields', array($this, 'edit_category_fields'), 10, 2);
         add_filter('manage_edit-pa_' . $attribute->attribute_name . '_columns', array($this, 'term_columns'));
         add_filter('manage_pa_' . $attribute->attribute_name . '_custom_column', array($this, 'term_column'), 10, 3);
     }
 }
 /**
  * Constructor
  *
  * @param WC_Variation_Restrictions $instance
  */
 public function __construct()
 {
     add_filter('woocommerce_products_general_settings', array($this, 'Settings'));
     // Category restriction settings
     add_action("product_cat_edit_form_fields", array($this, 'EditProductCategory'));
     add_action("edit_product_cat", array($this, 'SaveProductCategory'));
     // Product attribute/variation restriction setings
     $attribute_taxonomies = wc_get_attribute_taxonomies();
     if ($attribute_taxonomies) {
         foreach ($attribute_taxonomies as $tax) {
             // For each of WooCommerce's custom product attributes
             $attribute_name = wc_attribute_taxonomy_name($tax->attribute_name);
             add_action("{$attribute_name}_edit_form_fields", array($this, 'EditAttributeTerm'));
             add_action("edit_{$attribute_name}", array($this, 'SaveAttributeTerm'), 10, 2);
         }
     }
 }
function woo_print_variations_attribute_check()
{
    $taxonomies = wc_get_attribute_taxonomies();
    $taxonomiesArray = (array) $taxonomies;
    $filteredArray = array_filter($taxonomiesArray, function ($item) {
        return $item->attribute_name == 'print_variations';
    });
    if (count($filteredArray) < 1) {
        global $wpdb;
        $attribute = array('attribute_name' => 'print_variations', 'attribute_label' => 'Print Variations', 'attribute_type' => 'select', 'attribute_orderby' => 'menu_order');
        $wpdb->insert($wpdb->prefix . 'woocommerce_attribute_taxonomies', $attribute);
        do_action('woocommerce_attribute_added', $wpdb->insert_id, $attribute);
        flush_rewrite_rules();
        delete_transient('wc_attribute_taxonomies');
        return true;
    }
}
 function widget($args, $instance)
 {
     extract($args, EXTR_SKIP);
     global $woocommerce;
     $_attributes_array = array();
     if (version_compare(WOOCOMMERCE_VERSION, "2.0.99") >= 0) {
         $attribute_taxonomies = wc_get_attribute_taxonomies();
     } else {
         $attribute_taxonomies = $woocommerce->get_attribute_taxonomies();
     }
     if ($attribute_taxonomies) {
         foreach ($attribute_taxonomies as $tax) {
             $attribute = sanitize_title($tax->attribute_name);
             if (version_compare(WOOCOMMERCE_VERSION, "2.0.99") >= 0) {
                 $taxonomy = wc_attribute_taxonomy_name($attribute);
             } else {
                 $taxonomy = $woocommerce->attribute_taxonomy_name($attribute);
             }
             // create an array of product attribute taxonomies
             $_attributes_array[] = $taxonomy;
         }
     }
     if (!is_post_type_archive('product') && !is_tax(array_merge($_attributes_array, array('product_cat', 'product_tag')))) {
         return;
     }
     if (is_tax('product_tag')) {
         return;
     }
     echo $before_widget;
     if (!empty($instance['title'])) {
         echo $before_title . $instance['title'] . $after_title;
     }
     // Tag list
     $tags = get_terms('product_tag');
     $html = '<ul class="woo-ajax-tags taglist">';
     foreach ($tags as $tag) {
         $term_id = (int) $tag->term_id;
         $tag_link = get_term_link($term_id, 'product_tag');
         $html .= "<li><input type=checkbox id='{$tag->slug}' class=tags name=tag value='{$tag->slug}'> <label for='{$tag->slug}'>{$tag->name}</label></li>";
     }
     $html .= '</ul>';
     echo $html;
     echo $after_widget;
 }
/**
 * Index Woocommerce taxonomies
 *
 * @param   array $taxonomies Index taxonomies array.
 * @param   array $post Post properties array.
 * @since   1.0
 * @return  array
 */
function epwc_whitelist_taxonomies($taxonomies, $post)
{
    $woo_taxonomies = array();
    $product_type = get_taxonomy('product_type');
    $woo_taxonomies[] = $product_type;
    /**
     * Note product_shipping_class, product_cat, and product_tag are already public. Make
     * sure to index non-public attribute taxonomies.
     */
    if ($attribute_taxonomies = wc_get_attribute_taxonomies()) {
        foreach ($attribute_taxonomies as $tax) {
            if ($name = wc_attribute_taxonomy_name($tax->attribute_name)) {
                if (empty($tax->attribute_public)) {
                    $woo_taxonomies[] = get_taxonomy($name);
                }
            }
        }
    }
    return array_merge($taxonomies, $woo_taxonomies);
}
 /**
  * When running the WP importer, ensure attributes exist.
  *
  * WordPress import should work - however, it fails to import custom product attribute taxonomies.
  * This code grabs the file before it is imported and ensures the taxonomies are created.
  */
 public function post_importer_compatibility()
 {
     global $wpdb;
     if (empty($_POST['import_id']) || !class_exists('WXR_Parser')) {
         return;
     }
     $id = absint($_POST['import_id']);
     $file = get_attached_file($id);
     $parser = new WXR_Parser();
     $import_data = $parser->parse($file);
     if (isset($import_data['posts'])) {
         $posts = $import_data['posts'];
         if ($posts && sizeof($posts) > 0) {
             foreach ($posts as $post) {
                 if ('product' === $post['post_type']) {
                     if (!empty($post['terms'])) {
                         foreach ($post['terms'] as $term) {
                             if (strstr($term['domain'], 'pa_')) {
                                 if (!taxonomy_exists($term['domain'])) {
                                     $attribute_name = wc_sanitize_taxonomy_name(str_replace('pa_', '', $term['domain']));
                                     // Create the taxonomy
                                     if (!in_array($attribute_name, wc_get_attribute_taxonomies())) {
                                         $attribute = array('attribute_label' => $attribute_name, 'attribute_name' => $attribute_name, 'attribute_type' => 'select', 'attribute_orderby' => 'menu_order', 'attribute_public' => 0);
                                         $wpdb->insert($wpdb->prefix . 'woocommerce_attribute_taxonomies', $attribute);
                                         delete_transient('wc_attribute_taxonomies');
                                     }
                                     // Register the taxonomy now so that the import works!
                                     register_taxonomy($term['domain'], apply_filters('woocommerce_taxonomy_objects_' . $term['domain'], array('product')), apply_filters('woocommerce_taxonomy_args_' . $term['domain'], array('hierarchical' => true, 'show_ui' => false, 'query_var' => true, 'rewrite' => false)));
                                 }
                             }
                         }
                     }
                 }
             }
         }
     }
 }
Пример #25
0
 /**
  * Layered Nav Init
  *
  * @global array $_chosen_attributes
  *
  * @return false if not layered nav filter
  */
 public function layeredNavInit()
 {
     if (!(is_active_widget(false, false, 'woocommerce_layered_nav', true) && !is_admin())) {
         return false;
     }
     global $_chosen_attributes;
     $attributes = wc_get_attribute_taxonomies();
     foreach ($attributes as $tax) {
         $attribute = wc_sanitize_taxonomy_name($tax->attribute_name);
         $taxonomy = wc_attribute_taxonomy_name($attribute);
         $name = 'filter_' . $attribute;
         if (!(!empty($_GET[$name]) && taxonomy_exists($taxonomy))) {
             continue;
         }
         $terms = explode(',', $_GET[$name]);
         $termsTranslations = array();
         foreach ($terms as $ID) {
             $translation = pll_get_term($ID);
             $termsTranslations[] = $translation ? $translation : $ID;
         }
         $_GET[$name] = implode(',', $termsTranslations);
         $_chosen_attributes[$taxonomy]['terms'] = $termsTranslations;
     }
 }
 /**
  * Get a listing of product attributes
  *
  * @since 2.4.0
  * @param string|null $fields fields to limit response to
  * @return array
  */
 public function get_product_attributes($fields = null)
 {
     try {
         // Permissions check
         if (!current_user_can('manage_product_terms')) {
             throw new WC_API_Exception('woocommerce_api_user_cannot_read_product_attributes', __('You do not have permission to read product attributes', 'woocommerce'), 401);
         }
         $product_attributes = array();
         $attribute_taxonomies = wc_get_attribute_taxonomies();
         foreach ($attribute_taxonomies as $attribute) {
             $product_attributes[] = array('id' => intval($attribute->attribute_id), 'name' => $attribute->attribute_label, 'slug' => wc_attribute_taxonomy_name($attribute->attribute_name), 'type' => $attribute->attribute_type, 'order_by' => $attribute->attribute_orderby, 'has_archives' => (bool) $attribute->attribute_public);
         }
         return array('product_attributes' => apply_filters('woocommerce_api_product_attributes_response', $product_attributes, $attribute_taxonomies, $fields, $this));
     } catch (WC_API_Exception $e) {
         return new WP_Error($e->getErrorCode(), $e->getMessage(), array('status' => $e->getCode()));
     }
 }
Пример #27
0
 /**
  * Layered Nav Init.
  */
 public static function get_layered_nav_chosen_attributes()
 {
     if (!is_array(self::$_chosen_attributes)) {
         self::$_chosen_attributes = array();
         if ($attribute_taxonomies = wc_get_attribute_taxonomies()) {
             foreach ($attribute_taxonomies as $tax) {
                 $attribute = wc_sanitize_taxonomy_name($tax->attribute_name);
                 $taxonomy = wc_attribute_taxonomy_name($attribute);
                 $filter_terms = !empty($_GET['filter_' . $attribute]) ? explode(',', wc_clean($_GET['filter_' . $attribute])) : array();
                 if (empty($filter_terms) || !taxonomy_exists($taxonomy)) {
                     continue;
                 }
                 $query_type = !empty($_GET['query_type_' . $attribute]) && in_array($_GET['query_type_' . $attribute], array('and', 'or')) ? wc_clean($_GET['query_type_' . $attribute]) : '';
                 self::$_chosen_attributes[$taxonomy]['terms'] = array_map('sanitize_title', $filter_terms);
                 // Ensures correct encoding
                 self::$_chosen_attributes[$taxonomy]['query_type'] = $query_type ? $query_type : apply_filters('woocommerce_layered_nav_default_query_type', 'and');
             }
         }
     }
     return self::$_chosen_attributes;
 }
    /**
     * Output the metabox
     */
    public static function output($post)
    {
        global $post, $thepostid;
        wp_nonce_field('woocommerce_save_data', 'woocommerce_meta_nonce');
        $thepostid = $post->ID;
        if ($terms = wp_get_object_terms($post->ID, 'product_type')) {
            $product_type = sanitize_title(current($terms)->name);
        } else {
            $product_type = apply_filters('default_product_type', 'simple');
        }
        $product_type_selector = apply_filters('product_type_selector', array('simple' => __('Simple product', 'woocommerce'), 'grouped' => __('Grouped product', 'woocommerce'), 'external' => __('External/Affiliate product', 'woocommerce'), 'variable' => __('Variable product', 'woocommerce')), $product_type);
        $type_box = '<label for="product-type"><select id="product-type" name="product-type"><optgroup label="' . __('Product Type', 'woocommerce') . '">';
        foreach ($product_type_selector as $value => $label) {
            $type_box .= '<option value="' . esc_attr($value) . '" ' . selected($product_type, $value, false) . '>' . esc_html($label) . '</option>';
        }
        $type_box .= '</optgroup></select></label>';
        $product_type_options = apply_filters('product_type_options', array('virtual' => array('id' => '_virtual', 'wrapper_class' => 'show_if_simple', 'label' => __('Virtual', 'woocommerce'), 'description' => __('Virtual products are intangible and aren\'t shipped.', 'woocommerce'), 'default' => 'no'), 'downloadable' => array('id' => '_downloadable', 'wrapper_class' => 'show_if_simple', 'label' => __('Downloadable', 'woocommerce'), 'description' => __('Downloadable products give access to a file upon purchase.', 'woocommerce'), 'default' => 'no')));
        foreach ($product_type_options as $key => $option) {
            $selected_value = get_post_meta($post->ID, '_' . $key, true);
            if ('' == $selected_value && isset($option['default'])) {
                $selected_value = $option['default'];
            }
            $type_box .= '<label for="' . esc_attr($option['id']) . '" class="' . esc_attr($option['wrapper_class']) . ' tips" data-tip="' . esc_attr($option['description']) . '">' . esc_html($option['label']) . ': <input type="checkbox" name="' . esc_attr($option['id']) . '" id="' . esc_attr($option['id']) . '" ' . checked($selected_value, 'yes', false) . ' /></label>';
        }
        ?>
		<div class="panel-wrap product_data">

			<span class="type_box"> &mdash; <?php 
        echo $type_box;
        ?>
</span>

			<ul class="product_data_tabs wc-tabs" style="display:none;">
				<?php 
        $product_data_tabs = apply_filters('woocommerce_product_data_tabs', array('general' => array('label' => __('General', 'woocommerce'), 'target' => 'general_product_data', 'class' => array('hide_if_grouped')), 'inventory' => array('label' => __('Inventory', 'woocommerce'), 'target' => 'inventory_product_data', 'class' => array('show_if_simple', 'show_if_variable', 'show_if_grouped')), 'shipping' => array('label' => __('Shipping', 'woocommerce'), 'target' => 'shipping_product_data', 'class' => array('hide_if_virtual', 'hide_if_grouped', 'hide_if_external')), 'linked_product' => array('label' => __('Linked Products', 'woocommerce'), 'target' => 'linked_product_data', 'class' => array()), 'attribute' => array('label' => __('Attributes', 'woocommerce'), 'target' => 'product_attributes', 'class' => array()), 'variations' => array('label' => __('Variations', 'woocommerce'), 'target' => 'variable_product_options', 'class' => array('variations_tab', 'show_if_variable')), 'advanced' => array('label' => __('Advanced', 'woocommerce'), 'target' => 'advanced_product_data', 'class' => array())));
        foreach ($product_data_tabs as $key => $tab) {
            ?>
<li class="<?php 
            echo $key;
            ?>
_options <?php 
            echo $key;
            ?>
_tab <?php 
            echo implode(' ', $tab['class']);
            ?>
">
							<a href="#<?php 
            echo $tab['target'];
            ?>
"><?php 
            echo esc_html($tab['label']);
            ?>
</a>
						</li><?php 
        }
        do_action('woocommerce_product_write_panel_tabs');
        ?>
			</ul>
			<div id="general_product_data" class="panel woocommerce_options_panel"><?php 
        echo '<div class="options_group hide_if_grouped">';
        // SKU
        if (wc_product_sku_enabled()) {
            woocommerce_wp_text_input(array('id' => '_sku', 'label' => '<abbr title="' . __('Stock Keeping Unit', 'woocommerce') . '">' . __('SKU', 'woocommerce') . '</abbr>', 'desc_tip' => 'true', 'description' => __('SKU refers to a Stock-keeping unit, a unique identifier for each distinct product and service that can be purchased.', 'woocommerce')));
        } else {
            echo '<input type="hidden" name="_sku" value="' . esc_attr(get_post_meta($thepostid, '_sku', true)) . '" />';
        }
        do_action('woocommerce_product_options_sku');
        echo '</div>';
        echo '<div class="options_group show_if_external">';
        // External URL
        woocommerce_wp_text_input(array('id' => '_product_url', 'label' => __('Product URL', 'woocommerce'), 'placeholder' => 'http://', 'description' => __('Enter the external URL to the product.', 'woocommerce')));
        // Button text
        woocommerce_wp_text_input(array('id' => '_button_text', 'label' => __('Button text', 'woocommerce'), 'placeholder' => _x('Buy product', 'placeholder', 'woocommerce'), 'description' => __('This text will be shown on the button linking to the external product.', 'woocommerce')));
        echo '</div>';
        echo '<div class="options_group pricing show_if_simple show_if_external">';
        // Price
        woocommerce_wp_text_input(array('id' => '_regular_price', 'label' => __('Regular Price', 'woocommerce') . ' (' . get_woocommerce_currency_symbol() . ')', 'data_type' => 'price'));
        // Special Price
        woocommerce_wp_text_input(array('id' => '_sale_price', 'data_type' => 'price', 'label' => __('Sale Price', 'woocommerce') . ' (' . get_woocommerce_currency_symbol() . ')', 'description' => '<a href="#" class="sale_schedule">' . __('Schedule', 'woocommerce') . '</a>'));
        // Special Price date range
        $sale_price_dates_from = ($date = get_post_meta($thepostid, '_sale_price_dates_from', true)) ? date_i18n('Y-m-d', $date) : '';
        $sale_price_dates_to = ($date = get_post_meta($thepostid, '_sale_price_dates_to', true)) ? date_i18n('Y-m-d', $date) : '';
        echo '<p class="form-field sale_price_dates_fields">
								<label for="_sale_price_dates_from">' . __('Sale Price Dates', 'woocommerce') . '</label>
								<input type="text" class="short" name="_sale_price_dates_from" id="_sale_price_dates_from" value="' . esc_attr($sale_price_dates_from) . '" placeholder="' . _x('From&hellip;', 'placeholder', 'woocommerce') . ' YYYY-MM-DD" maxlength="10" pattern="[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])" />
								<input type="text" class="short" name="_sale_price_dates_to" id="_sale_price_dates_to" value="' . esc_attr($sale_price_dates_to) . '" placeholder="' . _x('To&hellip;', 'placeholder', 'woocommerce') . '  YYYY-MM-DD" maxlength="10" pattern="[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])" />
								<a href="#" class="cancel_sale_schedule">' . __('Cancel', 'woocommerce') . '</a>
								<img class="help_tip" style="margin-top: 21px;" data-tip="' . __('The sale will end at the beginning of the set date.', 'woocommerce') . '" src="' . esc_url(WC()->plugin_url()) . '/assets/images/help.png" height="16" width="16" />
							</p>';
        do_action('woocommerce_product_options_pricing');
        echo '</div>';
        echo '<div class="options_group show_if_downloadable">';
        ?>
					<div class="form-field downloadable_files">
						<label><?php 
        _e('Downloadable Files', 'woocommerce');
        ?>
:</label>
						<table class="widefat">
							<thead>
								<tr>
									<th class="sort">&nbsp;</th>
									<th><?php 
        _e('Name', 'woocommerce');
        ?>
 <span class="tips" data-tip="<?php 
        _e('This is the name of the download shown to the customer.', 'woocommerce');
        ?>
">[?]</span></th>
									<th colspan="2"><?php 
        _e('File URL', 'woocommerce');
        ?>
 <span class="tips" data-tip="<?php 
        _e('This is the URL or absolute path to the file which customers will get access to. URLs entered here should already be encoded.', 'woocommerce');
        ?>
">[?]</span></th>
									<th>&nbsp;</th>
								</tr>
							</thead>
							<tbody>
								<?php 
        $downloadable_files = get_post_meta($post->ID, '_downloadable_files', true);
        if ($downloadable_files) {
            foreach ($downloadable_files as $key => $file) {
                include 'views/html-product-download.php';
            }
        }
        ?>
							</tbody>
							<tfoot>
								<tr>
									<th colspan="5">
										<a href="#" class="button insert" data-row="<?php 
        $file = array('file' => '', 'name' => '');
        ob_start();
        include 'views/html-product-download.php';
        echo esc_attr(ob_get_clean());
        ?>
"><?php 
        _e('Add File', 'woocommerce');
        ?>
</a>
									</th>
								</tr>
							</tfoot>
						</table>
					</div>
					<?php 
        // Download Limit
        woocommerce_wp_text_input(array('id' => '_download_limit', 'label' => __('Download Limit', 'woocommerce'), 'placeholder' => __('Unlimited', 'woocommerce'), 'description' => __('Leave blank for unlimited re-downloads.', 'woocommerce'), 'type' => 'number', 'custom_attributes' => array('step' => '1', 'min' => '0')));
        // Expirey
        woocommerce_wp_text_input(array('id' => '_download_expiry', 'label' => __('Download Expiry', 'woocommerce'), 'placeholder' => __('Never', 'woocommerce'), 'description' => __('Enter the number of days before a download link expires, or leave blank.', 'woocommerce'), 'type' => 'number', 'custom_attributes' => array('step' => '1', 'min' => '0')));
        // Download Type
        woocommerce_wp_select(array('id' => '_download_type', 'label' => __('Download Type', 'woocommerce'), 'description' => sprintf(__('Choose a download type - this controls the <a href="%s">schema</a>.', 'woocommerce'), 'http://schema.org/'), 'options' => array('' => __('Standard Product', 'woocommerce'), 'application' => __('Application/Software', 'woocommerce'), 'music' => __('Music', 'woocommerce'))));
        do_action('woocommerce_product_options_downloads');
        echo '</div>';
        if (wc_tax_enabled()) {
            echo '<div class="options_group show_if_simple show_if_external show_if_variable">';
            // Tax
            woocommerce_wp_select(array('id' => '_tax_status', 'label' => __('Tax Status', 'woocommerce'), 'options' => array('taxable' => __('Taxable', 'woocommerce'), 'shipping' => __('Shipping only', 'woocommerce'), 'none' => _x('None', 'Tax status', 'woocommerce'))));
            $tax_classes = WC_Tax::get_tax_classes();
            $classes_options = array();
            $classes_options[''] = __('Standard', 'woocommerce');
            if (!empty($tax_classes)) {
                foreach ($tax_classes as $class) {
                    $classes_options[sanitize_title($class)] = esc_html($class);
                }
            }
            woocommerce_wp_select(array('id' => '_tax_class', 'label' => __('Tax Class', 'woocommerce'), 'options' => $classes_options));
            do_action('woocommerce_product_options_tax');
            echo '</div>';
        }
        do_action('woocommerce_product_options_general_product_data');
        ?>
			</div>

			<div id="inventory_product_data" class="panel woocommerce_options_panel">

				<?php 
        echo '<div class="options_group">';
        if ('yes' == get_option('woocommerce_manage_stock')) {
            // manage stock
            woocommerce_wp_checkbox(array('id' => '_manage_stock', 'wrapper_class' => 'show_if_simple show_if_variable', 'label' => __('Manage stock?', 'woocommerce'), 'description' => __('Enable stock management at product level', 'woocommerce')));
            do_action('woocommerce_product_options_stock');
            echo '<div class="stock_fields show_if_simple show_if_variable">';
            // Stock
            woocommerce_wp_text_input(array('id' => '_stock', 'label' => __('Stock Qty', 'woocommerce'), 'desc_tip' => true, 'description' => __('Stock quantity. If this is a variable product this value will be used to control stock for all variations, unless you define stock at variation level.', 'woocommerce'), 'type' => 'number', 'custom_attributes' => array('step' => 'any'), 'data_type' => 'stock'));
            // Backorders?
            woocommerce_wp_select(array('id' => '_backorders', 'label' => __('Allow Backorders?', 'woocommerce'), 'options' => array('no' => __('Do not allow', 'woocommerce'), 'notify' => __('Allow, but notify customer', 'woocommerce'), 'yes' => __('Allow', 'woocommerce')), 'desc_tip' => true, 'description' => __('If managing stock, this controls whether or not backorders are allowed. If enabled, stock quantity can go below 0.', 'woocommerce')));
            do_action('woocommerce_product_options_stock_fields');
            echo '</div>';
        }
        // Stock status
        woocommerce_wp_select(array('id' => '_stock_status', 'wrapper_class' => 'hide_if_variable', 'label' => __('Stock status', 'woocommerce'), 'options' => array('instock' => __('In stock', 'woocommerce'), 'outofstock' => __('Out of stock', 'woocommerce')), 'desc_tip' => true, 'description' => __('Controls whether or not the product is listed as "in stock" or "out of stock" on the frontend.', 'woocommerce')));
        do_action('woocommerce_product_options_stock_status');
        echo '</div>';
        echo '<div class="options_group show_if_simple show_if_variable">';
        // Individual product
        woocommerce_wp_checkbox(array('id' => '_sold_individually', 'wrapper_class' => 'show_if_simple show_if_variable', 'label' => __('Sold Individually', 'woocommerce'), 'description' => __('Enable this to only allow one of this item to be bought in a single order', 'woocommerce')));
        do_action('woocommerce_product_options_sold_individually');
        echo '</div>';
        do_action('woocommerce_product_options_inventory_product_data');
        ?>

			</div>

			<div id="shipping_product_data" class="panel woocommerce_options_panel">

				<?php 
        echo '<div class="options_group">';
        // Weight
        if (wc_product_weight_enabled()) {
            woocommerce_wp_text_input(array('id' => '_weight', 'label' => __('Weight', 'woocommerce') . ' (' . get_option('woocommerce_weight_unit') . ')', 'placeholder' => wc_format_localized_decimal(0), 'desc_tip' => 'true', 'description' => __('Weight in decimal form', 'woocommerce'), 'type' => 'text', 'data_type' => 'decimal'));
        }
        // Size fields
        if (wc_product_dimensions_enabled()) {
            ?>
<p class="form-field dimensions_field">
							<label for="product_length"><?php 
            echo __('Dimensions', 'woocommerce') . ' (' . get_option('woocommerce_dimension_unit') . ')';
            ?>
</label>
							<span class="wrap">
								<input id="product_length" placeholder="<?php 
            _e('Length', 'woocommerce');
            ?>
" class="input-text wc_input_decimal" size="6" type="text" name="_length" value="<?php 
            echo esc_attr(wc_format_localized_decimal(get_post_meta($thepostid, '_length', true)));
            ?>
" />
								<input placeholder="<?php 
            _e('Width', 'woocommerce');
            ?>
" class="input-text wc_input_decimal" size="6" type="text" name="_width" value="<?php 
            echo esc_attr(wc_format_localized_decimal(get_post_meta($thepostid, '_width', true)));
            ?>
" />
								<input placeholder="<?php 
            _e('Height', 'woocommerce');
            ?>
" class="input-text wc_input_decimal last" size="6" type="text" name="_height" value="<?php 
            echo esc_attr(wc_format_localized_decimal(get_post_meta($thepostid, '_height', true)));
            ?>
" />
							</span>
							<img class="help_tip" data-tip="<?php 
            esc_attr_e('LxWxH in decimal form', 'woocommerce');
            ?>
" src="<?php 
            echo esc_url(WC()->plugin_url());
            ?>
/assets/images/help.png" height="16" width="16" />
						</p><?php 
        }
        do_action('woocommerce_product_options_dimensions');
        echo '</div>';
        echo '<div class="options_group">';
        // Shipping Class
        $classes = get_the_terms($thepostid, 'product_shipping_class');
        if ($classes && !is_wp_error($classes)) {
            $current_shipping_class = current($classes)->term_id;
        } else {
            $current_shipping_class = '';
        }
        $args = array('taxonomy' => 'product_shipping_class', 'hide_empty' => 0, 'show_option_none' => __('No shipping class', 'woocommerce'), 'name' => 'product_shipping_class', 'id' => 'product_shipping_class', 'selected' => $current_shipping_class, 'class' => 'select short');
        ?>
<p class="form-field dimensions_field"><label for="product_shipping_class"><?php 
        _e('Shipping class', 'woocommerce');
        ?>
</label> <?php 
        wp_dropdown_categories($args);
        ?>
 <img class="help_tip" data-tip="<?php 
        esc_attr_e('Shipping classes are used by certain shipping methods to group similar products.', 'woocommerce');
        ?>
" src="<?php 
        echo esc_url(WC()->plugin_url());
        ?>
/assets/images/help.png" height="16" width="16" /></p><?php 
        do_action('woocommerce_product_options_shipping');
        echo '</div>';
        ?>

			</div>

			<div id="product_attributes" class="panel wc-metaboxes-wrapper">
				<div class="product_attributes wc-metaboxes">

					<?php 
        global $wc_product_attributes;
        // Array of defined attribute taxonomies
        $attribute_taxonomies = wc_get_attribute_taxonomies();
        // Product attributes - taxonomies and custom, ordered, with visibility and variation attributes set
        $attributes = maybe_unserialize(get_post_meta($thepostid, '_product_attributes', true));
        // Output All Set Attributes
        if (!empty($attributes)) {
            $attribute_keys = array_keys($attributes);
            $attribute_total = sizeof($attribute_keys);
            for ($i = 0; $i < $attribute_total; $i++) {
                $attribute = $attributes[$attribute_keys[$i]];
                $position = empty($attribute['position']) ? 0 : absint($attribute['position']);
                $taxonomy = '';
                $metabox_class = array();
                if ($attribute['is_taxonomy']) {
                    $taxonomy = $attribute['name'];
                    if (!taxonomy_exists($taxonomy)) {
                        continue;
                    }
                    $attribute_taxonomy = $wc_product_attributes[$taxonomy];
                    $metabox_class[] = 'taxonomy';
                    $metabox_class[] = $taxonomy;
                    $attribute_label = wc_attribute_label($taxonomy);
                } else {
                    $attribute_label = apply_filters('woocommerce_attribute_label', $attribute['name'], $attribute['name']);
                }
                include 'views/html-product-attribute.php';
            }
        }
        ?>
				</div>

				<p class="toolbar">
					<button type="button" class="button button-primary add_attribute"><?php 
        _e('Add', 'woocommerce');
        ?>
</button>
					<select name="attribute_taxonomy" class="attribute_taxonomy">
						<option value=""><?php 
        _e('Custom product attribute', 'woocommerce');
        ?>
</option>
						<?php 
        if ($attribute_taxonomies) {
            foreach ($attribute_taxonomies as $tax) {
                $attribute_taxonomy_name = wc_attribute_taxonomy_name($tax->attribute_name);
                $label = $tax->attribute_label ? $tax->attribute_label : $tax->attribute_name;
                echo '<option value="' . esc_attr($attribute_taxonomy_name) . '">' . esc_html($label) . '</option>';
            }
        }
        ?>
					</select>

					<button type="button" class="button save_attributes"><?php 
        _e('Save attributes', 'woocommerce');
        ?>
</button>
				</p>
				<?php 
        do_action('woocommerce_product_options_attributes');
        ?>
			</div>
			<div id="linked_product_data" class="panel woocommerce_options_panel">

				<div class="options_group">

					<p class="form-field">
						<label for="upsell_ids"><?php 
        _e('Up-Sells', 'woocommerce');
        ?>
</label>
						<input type="hidden" class="wc-product-search" style="width: 50%;" id="upsell_ids" name="upsell_ids" data-placeholder="<?php 
        _e('Search for a product&hellip;', 'woocommerce');
        ?>
" data-action="woocommerce_json_search_products" data-multiple="true" data-exclude="<?php 
        echo intval($post->ID);
        ?>
" data-selected="<?php 
        $product_ids = array_filter(array_map('absint', (array) get_post_meta($post->ID, '_upsell_ids', true)));
        $json_ids = array();
        foreach ($product_ids as $product_id) {
            $product = wc_get_product($product_id);
            if (is_object($product)) {
                $json_ids[$product_id] = wp_kses_post(html_entity_decode($product->get_formatted_name()));
            }
        }
        echo esc_attr(json_encode($json_ids));
        ?>
" value="<?php 
        echo implode(',', array_keys($json_ids));
        ?>
" /> <img class="help_tip" data-tip='<?php 
        _e('Up-sells are products which you recommend instead of the currently viewed product, for example, products that are more profitable or better quality or more expensive.', 'woocommerce');
        ?>
' src="<?php 
        echo WC()->plugin_url();
        ?>
/assets/images/help.png" height="16" width="16" />
					</p>

					<p class="form-field">
						<label for="crosssell_ids"><?php 
        _e('Cross-Sells', 'woocommerce');
        ?>
</label>
						<input type="hidden" class="wc-product-search" style="width: 50%;" id="crosssell_ids" name="crosssell_ids" data-placeholder="<?php 
        _e('Search for a product&hellip;', 'woocommerce');
        ?>
" data-action="woocommerce_json_search_products" data-multiple="true" data-exclude="<?php 
        echo intval($post->ID);
        ?>
" data-selected="<?php 
        $product_ids = array_filter(array_map('absint', (array) get_post_meta($post->ID, '_crosssell_ids', true)));
        $json_ids = array();
        foreach ($product_ids as $product_id) {
            $product = wc_get_product($product_id);
            if (is_object($product)) {
                $json_ids[$product_id] = wp_kses_post(html_entity_decode($product->get_formatted_name()));
            }
        }
        echo esc_attr(json_encode($json_ids));
        ?>
" value="<?php 
        echo implode(',', array_keys($json_ids));
        ?>
" /> <img class="help_tip" data-tip='<?php 
        _e('Cross-sells are products which you promote in the cart, based on the current product.', 'woocommerce');
        ?>
' src="<?php 
        echo WC()->plugin_url();
        ?>
/assets/images/help.png" height="16" width="16" />
					</p>
				</div>

				<div class="options_group grouping show_if_simple show_if_external">

					<p class="form-field">
						<label for="parent_id"><?php 
        _e('Grouping', 'woocommerce');
        ?>
</label>
						<input type="hidden" class="wc-product-search" style="width: 50%;" id="parent_id" name="parent_id" data-placeholder="<?php 
        _e('Search for a product&hellip;', 'woocommerce');
        ?>
" data-action="woocommerce_json_search_grouped_products" data-allow_clear="true" data-multiple="false" data-exclude="<?php 
        echo intval($post->ID);
        ?>
" data-selected="<?php 
        $parent_id = absint($post->post_parent);
        if ($parent_id) {
            $parent = wc_get_product($parent_id);
            if (is_object($parent)) {
                $parent_title = wp_kses_post(html_entity_decode($parent->get_formatted_name()));
            }
            echo esc_attr($parent_title);
        }
        ?>
" value="<?php 
        echo $parent_id ? $parent_id : '';
        ?>
" /> <img class="help_tip" data-tip='<?php 
        _e('Set this option to make this product part of a grouped product.', 'woocommerce');
        ?>
' src="<?php 
        echo WC()->plugin_url();
        ?>
/assets/images/help.png" height="16" width="16" />
					</p>

					<?php 
        woocommerce_wp_hidden_input(array('id' => 'previous_parent_id', 'value' => absint($post->post_parent)));
        do_action('woocommerce_product_options_grouping');
        ?>
				</div>

				<?php 
        do_action('woocommerce_product_options_related');
        ?>
			</div>

			<div id="advanced_product_data" class="panel woocommerce_options_panel">

				<div class="options_group hide_if_external">
					<?php 
        // Purchase note
        woocommerce_wp_textarea_input(array('id' => '_purchase_note', 'label' => __('Purchase Note', 'woocommerce'), 'desc_tip' => 'true', 'description' => __('Enter an optional note to send the customer after purchase.', 'woocommerce')));
        ?>
				</div>

				<div class="options_group">
					<?php 
        // menu_order
        woocommerce_wp_text_input(array('id' => 'menu_order', 'label' => __('Menu order', 'woocommerce'), 'desc_tip' => 'true', 'description' => __('Custom ordering position.', 'woocommerce'), 'value' => intval($post->menu_order), 'type' => 'number', 'custom_attributes' => array('step' => '1')));
        ?>
				</div>

				<div class="options_group reviews">
					<?php 
        woocommerce_wp_checkbox(array('id' => 'comment_status', 'label' => __('Enable reviews', 'woocommerce'), 'cbvalue' => 'open', 'value' => esc_attr($post->comment_status)));
        do_action('woocommerce_product_options_reviews');
        ?>
				</div>

				<?php 
        do_action('woocommerce_product_options_advanced');
        ?>

			</div>

			<?php 
        self::output_variations();
        do_action('woocommerce_product_data_panels');
        do_action('woocommerce_product_write_panels');
        // _deprecated
        ?>

			<div class="clear"></div>

		</div>
		<?php 
    }
 /**
  * Add woocommerce shortcodes and hooks/filters for it.
  * @since 4.4
  */
 public function mapShortcodes()
 {
     add_action('wp_ajax_vc_woocommerce_get_attribute_terms', array(&$this, 'getAttributeTermsAjax'));
     $order_by_values = array('', __('Date', 'js_composer') => 'date', __('ID', 'js_composer') => 'ID', __('Author', 'js_composer') => 'author', __('Title', 'js_composer') => 'title', __('Modified', 'js_composer') => 'modified', __('Random', 'js_composer') => 'rand', __('Comment count', 'js_composer') => 'comment_count', __('Menu order', 'js_composer') => 'menu_order');
     $order_way_values = array('', __('Descending', 'js_composer') => 'DESC', __('Ascending', 'js_composer') => 'ASC');
     $args = array('type' => 'post', 'child_of' => 0, 'parent' => '', 'orderby' => 'name', 'order' => 'ASC', 'hide_empty' => false, 'hierarchical' => 1, 'exclude' => '', 'include' => '', 'number' => '', 'taxonomy' => 'product_cat', 'pad_counts' => false);
     $categories = get_categories($args);
     $product_categories_dropdown = array();
     $this->getCategoryChilds(0, 0, $categories, 0, $product_categories_dropdown);
     /**
      * @shortcode woocommerce_cart
      * @description Used on the cart page, the cart shortcode displays the cart contents and interface for coupon codes and other cart bits and pieces.
      * @no_params
      * @not_editable
      */
     vc_map(array('name' => __('Cart', 'js_composer'), 'base' => 'woocommerce_cart', 'icon' => 'icon-wpb-woocommerce', 'category' => __('WooCommerce', 'js_composer'), 'description' => __('Displays the cart contents', 'js_composer'), 'show_settings_on_create' => false, 'php_class_name' => 'Vc_WooCommerce_NotEditable'));
     /**
      * @shortcode woocommerce_checkout
      * @description Used on the checkout page, the checkout shortcode displays the checkout process.
      * @no_params
      * @not_editable
      */
     vc_map(array('name' => __('Checkout', 'js_composer'), 'base' => 'woocommerce_checkout', 'icon' => 'icon-wpb-woocommerce', 'category' => __('WooCommerce', 'js_composer'), 'description' => __('Displays the checkout', 'js_composer'), 'show_settings_on_create' => false, 'php_class_name' => 'Vc_WooCommerce_NotEditable'));
     /**
      * @shortcode woocommerce_order_tracking
      * @description Lets a user see the status of an order by entering their order details.
      * @no_params
      * @not_editable
      */
     vc_map(array('name' => __('Order Tracking Form', 'js_composer'), 'base' => 'woocommerce_order_tracking', 'icon' => 'icon-wpb-woocommerce', 'category' => __('WooCommerce', 'js_composer'), 'description' => __('Lets a user see the status of an order', 'js_composer'), 'show_settings_on_create' => false, 'php_class_name' => 'Vc_WooCommerce_NotEditable'));
     /**
      * @shortcode woocommerce_my_account
      * @description Shows the ‘my account’ section where the customer can view past orders and update their information.
      * You can specify the number or order to show, it’s set by default to 15 (use -1 to display all orders.)
      *
      * @param order_count integer
      * Current user argument is automatically set using get_user_by( ‘id’, get_current_user_id() ).
      */
     vc_map(array('name' => __('My Account', 'js_composer'), 'base' => 'woocommerce_my_account', 'icon' => 'icon-wpb-woocommerce', 'category' => __('WooCommerce', 'js_composer'), 'description' => __('Shows the "my account" section', 'js_composer'), 'params' => array(array('type' => 'textfield', 'heading' => __('Order count', 'js_composer'), 'value' => 15, 'param_name' => 'order_count', 'description' => __('You can specify the number or order to show, it\'s set by default to 15 (use -1 to display all orders.)', 'js_composer')))));
     /**
      * @shortcode recent_products
      * @description Lists recent products – useful on the homepage. The ‘per_page’ shortcode determines how many products
      * to show on the page and the columns attribute controls how many columns wide the products should be before wrapping.
      * To learn more about the default ‘orderby’ parameters please reference the WordPress Codex: http://codex.wordpress.org/Class_Reference/WP_Query
      *
      * @param per_page integer
      * @param columns integer
      * @param orderby array
      * @param order array
      */
     vc_map(array('name' => __('Recent products', 'js_composer'), 'base' => 'recent_products', 'icon' => 'icon-wpb-woocommerce', 'category' => __('WooCommerce', 'js_composer'), 'description' => __('Lists recent products', 'js_composer'), 'params' => array(array('type' => 'textfield', 'heading' => __('Per page', 'js_composer'), 'value' => 12, 'param_name' => 'per_page', 'description' => __('The "per_page" shortcode determines how many products to show on the page', 'js_composer')), array('type' => 'textfield', 'heading' => __('Columns', 'js_composer'), 'value' => 4, 'param_name' => 'columns', 'description' => __('The columns attribute controls how many columns wide the products should be before wrapping.', 'js_composer')), array('type' => 'dropdown', 'heading' => __('Order by', 'js_composer'), 'param_name' => 'orderby', 'value' => $order_by_values, 'description' => sprintf(__('Select how to sort retrieved products. More at %s.', 'js_composer'), '<a href="http://codex.wordpress.org/Class_Reference/WP_Query#Order_.26_Orderby_Parameters" target="_blank">WordPress codex page</a>')), array('type' => 'dropdown', 'heading' => __('Order way', 'js_composer'), 'param_name' => 'order', 'value' => $order_way_values, 'description' => sprintf(__('Designates the ascending or descending order. More at %s.', 'js_composer'), '<a href="http://codex.wordpress.org/Class_Reference/WP_Query#Order_.26_Orderby_Parameters" target="_blank">WordPress codex page</a>')))));
     /**
      * @shortcode featured_products
      * @description Works exactly the same as recent products but displays products which have been set as “featured”.
      *
      * @param per_page integer
      * @param columns integer
      * @param orderby array
      * @param order array
      */
     vc_map(array('name' => __('Featured products', 'js_composer'), 'base' => 'featured_products', 'icon' => 'icon-wpb-woocommerce', 'category' => __('WooCommerce', 'js_composer'), 'description' => __('Display products set as "featured"', 'js_composer'), 'params' => array(array('type' => 'textfield', 'heading' => __('Per page', 'js_composer'), 'value' => 12, 'param_name' => 'per_page', 'description' => __('The "per_page" shortcode determines how many products to show on the page', 'js_composer')), array('type' => 'textfield', 'heading' => __('Columns', 'js_composer'), 'value' => 4, 'param_name' => 'columns', 'description' => __('The columns attribute controls how many columns wide the products should be before wrapping.', 'js_composer')), array('type' => 'dropdown', 'heading' => __('Order by', 'js_composer'), 'param_name' => 'orderby', 'value' => $order_by_values, 'description' => sprintf(__('Select how to sort retrieved products. More at %s.', 'js_composer'), '<a href="http://codex.wordpress.org/Class_Reference/WP_Query#Order_.26_Orderby_Parameters" target="_blank">WordPress codex page</a>')), array('type' => 'dropdown', 'heading' => __('Order way', 'js_composer'), 'param_name' => 'order', 'value' => $order_way_values, 'description' => sprintf(__('Designates the ascending or descending order. More at %s.', 'js_composer'), '<a href="http://codex.wordpress.org/Class_Reference/WP_Query#Order_.26_Orderby_Parameters" target="_blank">WordPress codex page</a>')))));
     /**
      * @shortcode product
      * @description Show a single product by ID or SKU.
      *
      * @param id integer
      * @param sku string
      * If the product isn’t showing, make sure it isn’t set to Hidden in the Catalog Visibility.
      * To find the Product ID, go to the Product > Edit screen and look in the URL for the postid= .
      */
     vc_map(array('name' => __('Product', 'js_composer'), 'base' => 'product', 'icon' => 'icon-wpb-woocommerce', 'category' => __('WooCommerce', 'js_composer'), 'description' => __('Show a single product by ID or SKU', 'js_composer'), 'params' => array(array('type' => 'autocomplete', 'heading' => __('Select identificator', 'js_composer'), 'param_name' => 'id', 'description' => __('Input product ID or product SKU or product title to see suggestions', 'js_composer')), array('type' => 'hidden', 'param_name' => 'sku'))));
     //Filters For autocomplete param:
     //For suggestion: vc_autocomplete_[shortcode_name]_[param_name]_callback
     add_filter('vc_autocomplete_product_id_callback', array(&$this, 'productIdAutocompleteSuggester'), 10, 1);
     // Get suggestion(find). Must return an array
     add_filter('vc_autocomplete_product_id_render', array(&$this, 'productIdAutocompleteRender'), 10, 1);
     // Render exact product. Must return an array (label,value)
     //For param: ID default value filter
     add_filter('vc_form_fields_render_field_product_id_param_value', array(&$this, 'productIdDefaultValue'), 10, 4);
     // Defines default value for param if not provided. Takes from other param value.
     /**
      * @shortcode products
      * @description Show multiple products by ID or SKU. Make note of the plural ‘products’.
      *
      * @param columns integer
      * @param orderby array
      * @param order array
      * If the product isn’t showing, make sure it isn’t set to Hidden in the Catalog Visibility.
      */
     vc_map(array('name' => __('Products', 'js_composer'), 'base' => 'products', 'icon' => 'icon-wpb-woocommerce', 'category' => __('WooCommerce', 'js_composer'), 'description' => __('Show multiple products by ID or SKU.', 'js_composer'), 'params' => array(array('type' => 'textfield', 'heading' => __('Columns', 'js_composer'), 'value' => 4, 'param_name' => 'columns'), array('type' => 'dropdown', 'heading' => __('Order by', 'js_composer'), 'param_name' => 'orderby', 'value' => $order_by_values, 'std' => 'title', 'description' => sprintf(__('Select how to sort retrieved products. More at %s. Default by Title', 'js_composer'), '<a href="http://codex.wordpress.org/Class_Reference/WP_Query#Order_.26_Orderby_Parameters" target="_blank">WordPress codex page</a>')), array('type' => 'dropdown', 'heading' => __('Order way', 'js_composer'), 'param_name' => 'order', 'value' => $order_way_values, 'description' => sprintf(__('Designates the ascending or descending order. More at %s. Default by ASC', 'js_composer'), '<a href="http://codex.wordpress.org/Class_Reference/WP_Query#Order_.26_Orderby_Parameters" target="_blank">WordPress codex page</a>')), array('type' => 'autocomplete', 'heading' => __('Products', 'js_composer'), 'param_name' => 'ids', 'settings' => array('multiple' => true, 'sortable' => true, 'unique_values' => true), 'description' => __('Enter List of Products', 'js_composer')), array('type' => 'hidden', 'param_name' => 'skus'))));
     //Filters For autocomplete param:
     //For suggestion: vc_autocomplete_[shortcode_name]_[param_name]_callback
     add_filter('vc_autocomplete_products_ids_callback', array(&$this, 'productIdAutocompleteSuggester'), 10, 1);
     // Get suggestion(find). Must return an array
     add_filter('vc_autocomplete_products_ids_render', array(&$this, 'productIdAutocompleteRender'), 10, 1);
     // Render exact product. Must return an array (label,value)
     //For param: ID default value filter
     add_filter('vc_form_fields_render_field_products_ids_param_value', array(&$this, 'productsIdsDefaultValue'), 10, 4);
     // Defines default value for param if not provided. Takes from other param value.
     /**
      * @shortcode add_to_cart
      * @description Show the price and add to cart button of a single product by ID (or SKU).
      *
      * @param id integer
      * @param sku string
      * @param style string
      * If the product isn’t showing, make sure it isn’t set to Hidden in the Catalog Visibility.
      */
     vc_map(array('name' => __('Add to cart', 'js_composer'), 'base' => 'add_to_cart', 'icon' => 'icon-wpb-woocommerce', 'category' => __('WooCommerce', 'js_composer'), 'description' => __('Show multiple products by ID or SKU', 'js_composer'), 'params' => array(array('type' => 'autocomplete', 'heading' => __('Select identificator', 'js_composer'), 'param_name' => 'id', 'description' => __('Input product ID or product SKU or product title to see suggestions', 'js_composer')), array('type' => 'hidden', 'param_name' => 'sku'), array('type' => 'textfield', 'heading' => __('Wrapper inline style', 'js_composer'), 'param_name' => 'style'))));
     //Filters For autocomplete param: Exactly Same as "product" shortcode
     //For suggestion: vc_autocomplete_[shortcode_name]_[param_name]_callback
     add_filter('vc_autocomplete_add_to_cart_id_callback', array(&$this, 'productIdAutocompleteSuggester'), 10, 1);
     // Get suggestion(find). Must return an array
     add_filter('vc_autocomplete_add_to_cart_id_render', array(&$this, 'productIdAutocompleteRender'), 10, 1);
     // Render exact product. Must return an array (label,value)
     //For param: ID default value filter
     add_filter('vc_form_fields_render_field_add_to_cart_id_param_value', array(&$this, 'productIdDefaultValue'), 10, 4);
     // Defines default value for param if not provided. Takes from other param value.
     /**
      * @shortcode add_to_cart_url
      * @description Echo the URL on the add to cart button of a single product by ID.
      *
      * @param id integer
      * @param sku string
      */
     vc_map(array('name' => __('Add to cart URL', 'js_composer'), 'base' => 'add_to_cart_url', 'icon' => 'icon-wpb-woocommerce', 'category' => __('WooCommerce', 'js_composer'), 'description' => __('Show URL on the add to cart button', 'js_composer'), 'params' => array(array('type' => 'autocomplete', 'heading' => __('Select identificator', 'js_composer'), 'param_name' => 'id', 'description' => __('Input product ID or product SKU or product title to see suggestions', 'js_composer')), array('type' => 'hidden', 'param_name' => 'sku'))));
     //Filters For autocomplete param: Exactly Same as "product" shortcode
     //For suggestion: vc_autocomplete_[shortcode_name]_[param_name]_callback
     add_filter('vc_autocomplete_add_to_cart_url_id_callback', array(&$this, 'productIdAutocompleteSuggester'), 10, 1);
     // Get suggestion(find). Must return an array
     add_filter('vc_autocomplete_add_to_cart_url_id_render', array(&$this, 'productIdAutocompleteRender'), 10, 1);
     // Render exact product. Must return an array (label,value)
     //For param: ID default value filter
     add_filter('vc_form_fields_render_field_add_to_cart_url_id_param_value', array(&$this, 'productIdDefaultValue'), 10, 4);
     // Defines default value for param if not provided. Takes from other param value.
     /**
      * @shortcode product_page
      * @description Show a full single product page by ID or SKU.
      *
      * @param id integer
      * @param sku string
      */
     vc_map(array('name' => __('Product page', 'js_composer'), 'base' => 'product_page', 'icon' => 'icon-wpb-woocommerce', 'category' => __('WooCommerce', 'js_composer'), 'description' => __('Show single product by ID or SKU', 'js_composer'), 'params' => array(array('type' => 'autocomplete', 'heading' => __('Select identificator', 'js_composer'), 'param_name' => 'id', 'description' => __('Input product ID or product SKU or product title to see suggestions', 'js_composer')), array('type' => 'hidden', 'param_name' => 'sku'))));
     //Filters For autocomplete param: Exactly Same as "product" shortcode
     //For suggestion: vc_autocomplete_[shortcode_name]_[param_name]_callback
     add_filter('vc_autocomplete_product_page_id_callback', array(&$this, 'productIdAutocompleteSuggester'), 10, 1);
     // Get suggestion(find). Must return an array
     add_filter('vc_autocomplete_product_page_id_render', array(&$this, 'productIdAutocompleteRender'), 10, 1);
     // Render exact product. Must return an array (label,value)
     //For param: ID default value filter
     add_filter('vc_form_fields_render_field_product_page_id_param_value', array(&$this, 'productIdDefaultValue'), 10, 4);
     // Defines default value for param if not provided. Takes from other param value.
     /**
      * @shortcode product_category
      * @description Show multiple products in a category by slug.
      *
      * @param per_page integer
      * @param columns integer
      * @param orderby array
      * @param order array
      * @param category string
      * Go to: WooCommerce > Products > Categories to find the slug column.
      */
     vc_map(array('name' => __('Product category', 'js_composer'), 'base' => 'product_category', 'icon' => 'icon-wpb-woocommerce', 'category' => __('WooCommerce', 'js_composer'), 'description' => __('Show multiple products in a category', 'js_composer'), 'params' => array(array('type' => 'textfield', 'heading' => __('Per page', 'js_composer'), 'value' => 12, 'param_name' => 'per_page', 'description' => __('How much items per page to show', 'js_composer')), array('type' => 'textfield', 'heading' => __('Columns', 'js_composer'), 'value' => 4, 'param_name' => 'columns', 'description' => __('How much columns grid', 'js_composer')), array('type' => 'dropdown', 'heading' => __('Order by', 'js_composer'), 'param_name' => 'orderby', 'value' => $order_by_values, 'description' => sprintf(__('Select how to sort retrieved products. More at %s.', 'js_composer'), '<a href="http://codex.wordpress.org/Class_Reference/WP_Query#Order_.26_Orderby_Parameters" target="_blank">WordPress codex page</a>')), array('type' => 'dropdown', 'heading' => __('Order way', 'js_composer'), 'param_name' => 'order', 'value' => $order_way_values, 'description' => sprintf(__('Designates the ascending or descending order. More at %s.', 'js_composer'), '<a href="http://codex.wordpress.org/Class_Reference/WP_Query#Order_.26_Orderby_Parameters" target="_blank">WordPress codex page</a>')), array('type' => 'dropdown', 'heading' => __('Category', 'js_composer'), 'value' => $product_categories_dropdown, 'param_name' => 'category', 'description' => __('Product category list', 'js_composer')))));
     //Filters For autocomplete param:
     //For suggestion: vc_autocomplete_[shortcode_name]_[param_name]_callback
     add_filter('vc_autocomplete_product_category_category_callback', array(&$this, 'productCategoryCategoryAutocompleteSuggesterBySlug'), 10, 1);
     // Get suggestion(find). Must return an array
     add_filter('vc_autocomplete_product_category_category_render', array(&$this, 'productCategoryCategoryRenderBySlugExact'), 10, 1);
     // Render exact category by Slug. Must return an array (label,value)
     /**
      * @shortcode product_categories
      * @description Display product categories loop.
      *
      * @param number integer
      * @param columns integer
      * @param orderby array
      * @param order array
      * @param hide_empty bool
      * @param parent integer
      * @param ids string
      * The `number` field is used to display the number of products and the `ids` field is to tell the shortcode which categories to display.
      * Set the parent paramater to 0 to only display top level categories. Set ids to a comma separated list of category ids to only show those.
      */
     vc_map(array('name' => __('Product categories', 'js_composer'), 'base' => 'product_categories', 'icon' => 'icon-wpb-woocommerce', 'category' => __('WooCommerce', 'js_composer'), 'description' => __('Display product categories loop', 'js_composer'), 'params' => array(array('type' => 'textfield', 'heading' => __('Number', 'js_composer'), 'param_name' => 'number', 'description' => __('The `number` field is used to display the number of products.', 'js_composer')), array('type' => 'dropdown', 'heading' => __('Order by', 'js_composer'), 'param_name' => 'orderby', 'value' => $order_by_values, 'description' => sprintf(__('Select how to sort retrieved products. More at %s.', 'js_composer'), '<a href="http://codex.wordpress.org/Class_Reference/WP_Query#Order_.26_Orderby_Parameters" target="_blank">WordPress codex page</a>')), array('type' => 'dropdown', 'heading' => __('Order way', 'js_composer'), 'param_name' => 'order', 'value' => $order_way_values, 'description' => sprintf(__('Designates the ascending or descending order. More at %s.', 'js_composer'), '<a href="http://codex.wordpress.org/Class_Reference/WP_Query#Order_.26_Orderby_Parameters" target="_blank">WordPress codex page</a>')), array('type' => 'textfield', 'heading' => __('Columns', 'js_composer'), 'value' => 4, 'param_name' => 'columns', 'description' => __('How much columns grid', 'js_composer')), array('type' => 'textfield', 'heading' => __('Number', 'js_composer'), 'param_name' => 'hide_empty', 'description' => __('Hide empty', 'js_composer')), array('type' => 'autocomplete', 'heading' => __('Categories', 'js_composer'), 'param_name' => 'ids', 'settings' => array('multiple' => true, 'sortable' => true), 'description' => __('List of product categories', 'js_composer')))));
     //Filters For autocomplete param:
     //For suggestion: vc_autocomplete_[shortcode_name]_[param_name]_callback
     add_filter('vc_autocomplete_product_categories_ids_callback', array(&$this, 'productCategoryCategoryAutocompleteSuggester'), 10, 1);
     // Get suggestion(find). Must return an array
     add_filter('vc_autocomplete_product_categories_ids_render', array(&$this, 'productCategoryCategoryRenderByIdExact'), 10, 1);
     // Render exact category by id. Must return an array (label,value)
     /**
      * @shortcode sale_products
      * @description List all products on sale.
      *
      * @param per_page integer
      * @param columns integer
      * @param orderby array
      * @param order array
      */
     vc_map(array('name' => __('Sale products', 'js_composer'), 'base' => 'sale_products', 'icon' => 'icon-wpb-woocommerce', 'category' => __('WooCommerce', 'js_composer'), 'description' => __('List all products on sale', 'js_composer'), 'params' => array(array('type' => 'textfield', 'heading' => __('Per page', 'js_composer'), 'value' => 12, 'param_name' => 'per_page', 'description' => __('How much items per page to show', 'js_composer')), array('type' => 'textfield', 'heading' => __('Columns', 'js_composer'), 'value' => 4, 'param_name' => 'columns', 'description' => __('How much columns grid', 'js_composer')), array('type' => 'dropdown', 'heading' => __('Order by', 'js_composer'), 'param_name' => 'orderby', 'value' => $order_by_values, 'description' => sprintf(__('Select how to sort retrieved products. More at %s.', 'js_composer'), '<a href="http://codex.wordpress.org/Class_Reference/WP_Query#Order_.26_Orderby_Parameters" target="_blank">WordPress codex page</a>')), array('type' => 'dropdown', 'heading' => __('Order way', 'js_composer'), 'param_name' => 'order', 'value' => $order_way_values, 'description' => sprintf(__('Designates the ascending or descending order. More at %s.', 'js_composer'), '<a href="http://codex.wordpress.org/Class_Reference/WP_Query#Order_.26_Orderby_Parameters" target="_blank">WordPress codex page</a>')))));
     /**
      * @shortcode best_selling_products
      * @description List best selling products on sale.
      *
      * @param per_page integer
      * @param columns integer
      */
     vc_map(array('name' => __('Best Selling Products', 'js_composer'), 'base' => 'best_selling_products', 'icon' => 'icon-wpb-woocommerce', 'category' => __('WooCommerce', 'js_composer'), 'description' => __('List best selling products on sale', 'js_composer'), 'params' => array(array('type' => 'textfield', 'heading' => __('Per page', 'js_composer'), 'value' => 12, 'param_name' => 'per_page', 'description' => __('How much items per page to show', 'js_composer')), array('type' => 'textfield', 'heading' => __('Columns', 'js_composer'), 'value' => 4, 'param_name' => 'columns', 'description' => __('How much columns grid', 'js_composer')))));
     /**
      * @shortcode top_rated_products
      * @description List top rated products on sale.
      *
      * @param per_page integer
      * @param columns integer
      * @param orderby array
      * @param order array
      */
     vc_map(array('name' => __('Top Rated Products', 'js_composer'), 'base' => 'top_rated_products', 'icon' => 'icon-wpb-woocommerce', 'category' => __('WooCommerce', 'js_composer'), 'description' => __('List all products on sale', 'js_composer'), 'params' => array(array('type' => 'textfield', 'heading' => __('Per page', 'js_composer'), 'value' => 12, 'param_name' => 'per_page', 'description' => __('How much items per page to show', 'js_composer')), array('type' => 'textfield', 'heading' => __('Columns', 'js_composer'), 'value' => 4, 'param_name' => 'columns', 'description' => __('How much columns grid', 'js_composer')), array('type' => 'dropdown', 'heading' => __('Order by', 'js_composer'), 'param_name' => 'orderby', 'value' => $order_by_values, 'description' => sprintf(__('Select how to sort retrieved products. More at %s.', 'js_composer'), '<a href="http://codex.wordpress.org/Class_Reference/WP_Query#Order_.26_Orderby_Parameters" target="_blank">WordPress codex page</a>')), array('type' => 'dropdown', 'heading' => __('Order way', 'js_composer'), 'param_name' => 'order', 'value' => $order_way_values, 'description' => sprintf(__('Designates the ascending or descending order. More at %s.', 'js_composer'), '<a href="http://codex.wordpress.org/Class_Reference/WP_Query#Order_.26_Orderby_Parameters" target="_blank">WordPress codex page</a>')))));
     /**
      * @shortcode product_attribute
      * @description List products with an attribute shortcode.
      *
      * @param per_page integer
      * @param columns integer
      * @param orderby array
      * @param order array
      * @param attribute string
      * @param filter string
      */
     $attributes_tax = wc_get_attribute_taxonomies();
     $attributes = array();
     foreach ($attributes_tax as $attribute) {
         $attributes[$attribute->attribute_label] = $attribute->attribute_name;
     }
     vc_map(array('name' => __('Product Attribute', 'js_composer'), 'base' => 'product_attribute', 'icon' => 'icon-wpb-woocommerce', 'category' => __('WooCommerce', 'js_composer'), 'description' => __('List products with an attribute shortcode', 'js_composer'), 'params' => array(array('type' => 'textfield', 'heading' => __('Per page', 'js_composer'), 'value' => 12, 'param_name' => 'per_page', 'description' => __('How much items per page to show', 'js_composer')), array('type' => 'textfield', 'heading' => __('Columns', 'js_composer'), 'value' => 4, 'param_name' => 'columns', 'description' => __('How much columns grid', 'js_composer')), array('type' => 'dropdown', 'heading' => __('Order by', 'js_composer'), 'param_name' => 'orderby', 'value' => $order_by_values, 'description' => sprintf(__('Select how to sort retrieved products. More at %s.', 'js_composer'), '<a href="http://codex.wordpress.org/Class_Reference/WP_Query#Order_.26_Orderby_Parameters" target="_blank">WordPress codex page</a>')), array('type' => 'dropdown', 'heading' => __('Order way', 'js_composer'), 'param_name' => 'order', 'value' => $order_way_values, 'description' => sprintf(__('Designates the ascending or descending order. More at %s.', 'js_composer'), '<a href="http://codex.wordpress.org/Class_Reference/WP_Query#Order_.26_Orderby_Parameters" target="_blank">WordPress codex page</a>')), array('type' => 'dropdown', 'heading' => __('Attribute', 'js_composer'), 'param_name' => 'attribute', 'value' => $attributes, 'description' => __('List of product taxonomy attribute', 'js_composer')), array('type' => 'checkbox', 'heading' => __('Filter', 'js_composer'), 'param_name' => 'filter', 'value' => array('empty' => 'empty'), 'description' => __('Taxonomy values', 'js_composer'), 'dependency' => array('element' => 'attribute', 'is_empty' => true, 'callback' => 'vc_woocommerce_product_attribute_filter_dependency_callback')))));
     //For param: "filter" param value
     //vc_form_fields_render_field_{shortcode_name}_{param_name}_param
     add_filter('vc_form_fields_render_field_product_attribute_filter_param', array(&$this, 'productAttributeFilterParamValue'), 10, 4);
     // Defines default value for param if not provided. Takes from other param value.
     /**
      * @shortcode related_products
      * @description List related products.
      *
      * @param per_page integer
      * @param columns integer
      * @param orderby array
      * @param order array
      */
     /* we need to detect post type to show this shortcode */
     global $post, $typenow, $current_screen;
     $post_type = "";
     if ($post && $post->post_type) {
         //we have a post so we can just get the post type from that
         $post_type = $post->post_type;
     } elseif ($typenow) {
         //check the global $typenow - set in admin.php
         $post_type = $typenow;
     } elseif ($current_screen && $current_screen->post_type) {
         //check the global $current_screen object - set in sceen.php
         $post_type = $current_screen->post_type;
     } elseif (isset($_REQUEST['post_type'])) {
         //lastly check the post_type querystring
         $post_type = sanitize_key($_REQUEST['post_type']);
         //we do not know the post type!
     }
     vc_map(array('name' => __('Related Products', 'js_composer'), 'base' => 'related_products', 'icon' => 'icon-wpb-woocommerce', 'content_element' => $post_type == 'product', 'category' => __('WooCommerce', 'js_composer'), 'description' => __('List related products', 'js_composer'), 'params' => array(array('type' => 'textfield', 'heading' => __('Per page', 'js_composer'), 'value' => 12, 'param_name' => 'per_page', 'description' => __('Please note: the "per_page" shortcode argument will determine how many products are shown on a page. This will not add pagination to the shortcode. ', 'js_composer')), array('type' => 'textfield', 'heading' => __('Columns', 'js_composer'), 'value' => 4, 'param_name' => 'columns', 'description' => __('How much columns grid', 'js_composer')), array('type' => 'dropdown', 'heading' => __('Order by', 'js_composer'), 'param_name' => 'orderby', 'value' => $order_by_values, 'description' => sprintf(__('Select how to sort retrieved products. More at %s.', 'js_composer'), '<a href="http://codex.wordpress.org/Class_Reference/WP_Query#Order_.26_Orderby_Parameters" target="_blank">WordPress codex page</a>')), array('type' => 'dropdown', 'heading' => __('Order way', 'js_composer'), 'param_name' => 'order', 'value' => $order_way_values, 'description' => sprintf(__('Designates the ascending or descending order. More at %s.', 'js_composer'), '<a href="http://codex.wordpress.org/Class_Reference/WP_Query#Order_.26_Orderby_Parameters" target="_blank">WordPress codex page</a>')))));
 }
function porto_load_product_attribute_shortcode()
{
    $animation_type = porto_vc_animation_type();
    $animation_duration = porto_vc_animation_duration();
    $animation_delay = porto_vc_animation_delay();
    $custom_class = porto_vc_custom_class();
    $order_by_values = porto_vc_woo_order_by();
    $order_way_values = porto_vc_woo_order_way();
    $attributes_tax = wc_get_attribute_taxonomies();
    $attributes = array();
    foreach ($attributes_tax as $attribute) {
        $attributes[$attribute->attribute_label] = $attribute->attribute_name;
    }
    // woocommerce product attribute
    vc_map(array('name' => "Porto " . __('Product Attribute', 'js_composer'), 'base' => 'porto_product_attribute', 'icon' => 'porto_vc_woocommerce', 'category' => __('WooCommerce', 'js_composer'), 'description' => __('Show products with an attribute shortcode', 'porto-shortcodes'), 'params' => array(array('type' => 'textfield', 'heading' => __('Title', 'woocommerce'), 'param_name' => 'title', 'admin_label' => true), array('type' => 'dropdown', 'heading' => __('View mode', 'porto-shortcodes'), 'param_name' => 'view', 'value' => porto_vc_commons('products_view_mode'), 'admin_label' => true), array('type' => 'textfield', 'heading' => __('Per page', 'js_composer'), 'value' => 12, 'param_name' => 'per_page', 'description' => __('The "per_page" shortcode determines how many products to show on the page', 'js_composer')), array('type' => 'dropdown', 'heading' => __('Columns', 'porto-shortcodes'), 'param_name' => 'columns', 'dependency' => array('element' => 'view', 'value' => array('products-slider', 'grid')), 'std' => '4', 'value' => porto_vc_commons('products_columns')), array('type' => 'dropdown', 'heading' => __('Column Width', 'porto-shortcodes'), 'param_name' => 'column_width', 'dependency' => array('element' => 'view', 'value' => array('products-slider', 'grid')), 'value' => porto_vc_commons('products_column_width')), array('type' => 'dropdown', 'heading' => __('Order by', 'js_composer'), 'param_name' => 'orderby', 'value' => $order_by_values, 'description' => sprintf(__('Select how to sort retrieved products. More at %s.', 'js_composer'), '<a href="http://codex.wordpress.org/Class_Reference/WP_Query#Order_.26_Orderby_Parameters" target="_blank">WordPress codex page</a>')), array('type' => 'dropdown', 'heading' => __('Order way', 'js_composer'), 'param_name' => 'order', 'value' => $order_way_values, 'description' => sprintf(__('Designates the ascending or descending order. More at %s.', 'js_composer'), '<a href="http://codex.wordpress.org/Class_Reference/WP_Query#Order_.26_Orderby_Parameters" target="_blank">WordPress codex page</a>')), array('type' => 'dropdown', 'heading' => __('Attribute', 'js_composer'), 'param_name' => 'attribute', 'value' => $attributes, 'description' => __('List of product taxonomy attribute', 'js_composer')), array('type' => 'checkbox', 'heading' => __('Filter', 'js_composer'), 'param_name' => 'filter', 'value' => array('empty' => 'empty'), 'description' => __('Taxonomy values', 'js_composer'), 'dependency' => array('element' => 'attribute', 'is_empty' => true, 'callback' => 'vc_woocommerce_product_attribute_filter_dependency_callback')), array('type' => 'dropdown', 'heading' => __('Add Links Position', 'porto-shortcodes'), 'desc' => 'Select position of add to cart, add to wishlist, quickview.', 'param_name' => 'addlinks_pos', 'value' => porto_vc_commons('products_addlinks_pos')), array('type' => 'checkbox', 'heading' => __('Show Navigation', 'porto-shortcodes'), 'param_name' => 'navigation', 'std' => 'yes', 'dependency' => array('element' => 'view', 'value' => array('products-slider')), 'value' => array(__('Yes', 'js_composer') => 'yes')), array('type' => 'checkbox', 'heading' => __('Show Pagination', 'porto-shortcodes'), 'param_name' => 'pagination', 'std' => 'no', 'dependency' => array('element' => 'view', 'value' => array('products-slider')), 'value' => array(__('Yes', 'js_composer') => 'yes')), $animation_type, $animation_duration, $animation_delay, $custom_class)));
    //For param: "filter" param value
    //vc_form_fields_render_field_{shortcode_name}_{param_name}_param
    add_filter('vc_form_fields_render_field_porto_product_attribute_filter_param', 'porto_shortcode_product_attribute_filter_param', 10, 4);
    // Defines default value for param if not provided. Takes from other param value.
    if (!class_exists('WPBakeryShortCode_Porto_Product_Attribute')) {
        class WPBakeryShortCode_Porto_Product_Attribute extends WPBakeryShortCode
        {
        }
    }
}