Plugin Directory

Changeset 2739048


Ignore:
Timestamp:
06/08/2022 07:01:58 AM (4 years ago)
Author:
mycholan
Message:

Added additonal params for wcff_new_field_id filter

Location:
wc-fields-factory
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • wc-fields-factory/tags/4.0.1/includes/wcff_dao.php

    r2739039 r2739048  
    1212 */
    1313class wcff_dao {
    14    
    15     /*
    16      * 
    17     * Namespace for WCFF related post meta
    18     * "wccpf_" for Custom product page Fields ( Front end product page )
    19     * "wccaf_" for Custom admin page fields ( for Admin Products )
    20     * "wccvf_" for Custom admin page fields ( for Variation Fields )
    21     * "wcccf_" for Custom admin page fields ( for Checkout Fields )
    22      *
    23     **/
    24     private $wcff_key_prefix = "wccpf_";
    25    
    26     /* Holds all the supported field's specific configuration meta */
    27     private $fields_meta = array();
    28    
    29     /* Holds all the configuration meta that are common to all fields ( both Product as well as Admin ) */
    30     private $common_meta = array();
    31    
    32     /* Holds all the configuration meta that are common to Admin Fields */
    33     private $wccaf_common_meta = array();
    34    
    35     /**/
    36     public $has_variable_tab_fields = false;
    37    
    38     /*
    39      *
    40     * Cusdtom post meta Keys that are used by WCFF for various purposes
    41      *
    42     * */
    43     public $special_keys = array(
    44         'fee_rules',
    45         'layout_meta',
    46         'field_rules',
    47         'group_rules',
    48         'pricing_rules',
    49         'location_rules',
    50         'condition_rules', 
    51         'show_group_title',
    52         'use_custom_layout',
    53         'product_tab_title',
    54         'product_tab_priority',
    55         'is_this_group_clonable',
    56         'fields_label_alignement',
    57         'field_location_on_product',
    58         'field_location_on_archive',       
    59         'is_this_group_for_authorized_only',
    60         'wcff_group_preference_target_roles'
    61     );
    62    
    63     public function __construct() {
    64         /* Wordpress's Save Post action hook
    65         * This is where we would save all the rules for the Fields Group ( post ) that is being saved */
    66         add_action( 'save_post', array($this, 'on_save_post' ), 1, 3 );
    67     }
    68    
    69     /**
    70     *
    71     * Set the current post type properties,<br/>
    72     * based on this only all the subsequent fields related operation will happen<br/>
    73     * this option could be either 'wccpf' for product fields or 'wccaf' for admin fields.
    74     *
    75     * @param string $_type
    76     *
    77     */
    78     public function set_current_post_type($_type = "wccpf") {
    79         $this->wcff_key_prefix = $_type . "_";
    80     }
    81    
    82     /**
    83     *
    84     * Return the Fields config meta for Factory View<br/>
    85     * Contains entire (specific to each fields) config meta list for each field type.
    86     *
    87     * @return array
    88     *
    89     */
    90     public function get_fields_meta() {
    91         /* Make sure the meta is loaded */
    92         $this->load_core_meta();
    93         return $this->fields_meta;
    94     }
    95    
    96     /**
    97     *
    98     * Return the Fields config common meta for Factory View<br/>
    99     * Contains entire (common for all fields) config meta list for each field type.
    100     *
    101     * @return array
    102     *
    103     */
    104     public function get_fields_common_meta() {
    105         /* Make sure the meta is loaded */
    106         $this->load_core_meta();
    107         return $this->common_meta;
    108     }
    109    
    110     /**
    111     *
    112     * Return the Admin Fields config common meta for Factory View<br/>
    113     * Contains entire (common for all admin fields) config meta list for each field type.
    114     *
    115     * @return array
    116     *
    117     */
    118     public function get_admin_fields_comman_meta() {
    119         /* Make sure the meta is loaded */
    120         $this->load_core_meta();
    121         return $this->wccaf_common_meta;
    122     }
    123    
    124     /**
    125     *
    126     * Loads Fields configuration meta from the file system<br>
    127     * Fields specific configuration meta from 'meta/wcff-meta.php'<br>
    128     * Common configuration meta from 'meta/wcff-common-meta.php'<br>
    129     * Common admin configuration meta from 'meta/wcff-common-wccaf-meta.php'
    130     *
    131     */
    132     private function load_core_meta() {
    133         /* Load core fields config meta */
    134         if (!is_array($this->fields_meta) || empty( $this->fields_meta)) {
    135             $this->fields_meta = include('meta/wcff-meta.php');
    136         }
    137         /* Load common config meta for all fields */
    138         if (!is_array($this->common_meta) || empty($this->common_meta)) {
    139             $this->common_meta = include('meta/wcff-common-meta.php');
    140         }
    141         /* Load common config meta for admin fields */
    142         if (!is_array($this->wccaf_common_meta) || empty($this->wccaf_common_meta)) {
    143             $this->wccaf_common_meta = include('meta/wcff-common-wccaf-meta.php');
    144         }
    145     }
    146    
    147     /**
    148     *
    149     * Called whenever user 'Update' or 'Save' post from wp-admin single post view<br/>
    150     * This is where the various (Product, Cat, Location ... ) rules for the fields group will be stored in their respective post meta.
    151     *
    152     * @param integer $_pid
    153     * @param WP_Post $_post
    154     * @param boolean $_update
    155     * @return void|boolean
    156     *
    157     */
    158     public function on_save_post($_pid, $_post, $_update) {
    159         /* Maje sure the post types are valid */
    160         if (!$_pid || ! $_post || ($_post->post_type != "wccpf" && $_post->post_type != "wccaf" && $_post->post_type != "wccvf" && $_post->post_type != "wcccf")) {
    161             return false;
    162         }
    163        
    164         $_pid = absint($_pid);
    165        
    166         /* Prepare the post type prefix for meta key */
    167         $this->wcff_key_prefix = $_post->post_type . "_";
    168        
    169         /* Conditional rules - determine which fields group belongs to which products */
    170         if (isset($_REQUEST["wcff_condition_rules"])) {
    171             delete_post_meta($_pid, $this->wcff_key_prefix .'condition_rules');
    172             add_post_meta($_pid, $this->wcff_key_prefix .'condition_rules', $_REQUEST["wcff_condition_rules"]);
    173         }
    174        
    175         /* Location rules - specific to Admin Fields */
    176         if (isset($_REQUEST["wcff_location_rules"])) {
    177             delete_post_meta($_pid, $this->wcff_key_prefix .'location_rules');
    178             add_post_meta($_pid, $this->wcff_key_prefix .'location_rules', $_REQUEST["wcff_location_rules"]);
    179         }
    180        
    181         /**/
    182         if (isset($_REQUEST["wcff_layout_meta"])) {
    183             delete_post_meta($_pid, $this->wcff_key_prefix .'layout_meta');
    184             add_post_meta($_pid, $this->wcff_key_prefix .'layout_meta', $_REQUEST["wcff_layout_meta"]);
    185         }
    186        
    187         if (isset($_REQUEST["wcff_use_custom_layout"])) {           
    188             delete_post_meta($_pid, $this->wcff_key_prefix .'use_custom_layout');
    189             add_post_meta($_pid, $this->wcff_key_prefix .'use_custom_layout', "yes");
    190         } else {
    191             delete_post_meta($_pid, $this->wcff_key_prefix .'use_custom_layout');
    192             add_post_meta($_pid, $this->wcff_key_prefix .'use_custom_layout', "no");
    193         }
    194        
    195         /* Field location for each field's group */
    196         if (isset($_REQUEST["field_location_on_product"])) {
    197             delete_post_meta($_pid, $this->wcff_key_prefix .'field_location_on_product');
    198             add_post_meta($_pid, $this->wcff_key_prefix .'field_location_on_product', $_REQUEST["field_location_on_product"]);
    199             delete_post_meta($_pid, $this->wcff_key_prefix .'product_tab_title');
    200             delete_post_meta($_pid, $this->wcff_key_prefix .'product_tab_priority');
    201             if ($_REQUEST["field_location_on_product"] == "woocommerce_single_product_tab" && isset($_REQUEST["product_tab_config_title"])) {
    202                 add_post_meta($_pid, $this->wcff_key_prefix .'product_tab_title', $_REQUEST["product_tab_config_title"]);
    203                 add_post_meta($_pid, $this->wcff_key_prefix .'product_tab_priority', $_REQUEST["product_tab_config_priority"]);
    204             }
    205         }
    206        
    207         /* Field location for archive page */
    208         if (isset($_REQUEST["field_location_on_archive"])) {
    209             delete_post_meta($_pid, $this->wcff_key_prefix .'field_location_on_archive');
    210             add_post_meta($_pid, $this->wcff_key_prefix .'field_location_on_archive', $_REQUEST["field_location_on_archive"]);
    211         }
    212        
    213         /* Group level cloning option */
    214         if (isset($_REQUEST["wcff_group_clonable_radio"])) {
    215             delete_post_meta($_pid, $this->wcff_key_prefix .'is_this_group_clonable');
    216             add_post_meta($_pid, $this->wcff_key_prefix .'is_this_group_clonable', $_REQUEST["wcff_group_clonable_radio"]);         
    217         }
    218        
    219         /* Group title display option */
    220         if (isset($_REQUEST["wcff_group_title_radio"])) {
    221             delete_post_meta($_pid, $this->wcff_key_prefix .'show_group_title');
    222             add_post_meta($_pid, $this->wcff_key_prefix .'show_group_title', $_REQUEST["wcff_group_title_radio"]);
    223         }
    224        
    225         /**/
    226         if (isset($_REQUEST["wcff_label_alignment_radio"])) {
    227             delete_post_meta($_pid, $this->wcff_key_prefix .'fields_label_alignement');
    228             add_post_meta($_pid, $this->wcff_key_prefix .'fields_label_alignement', $_REQUEST["wcff_label_alignment_radio"]);
    229         }
    230        
    231         /* Authorized users only option */
    232         if (isset($_REQUEST["wcff_group_authorized_only_radio"])) {         
    233             delete_post_meta($_pid, $this->wcff_key_prefix .'is_this_group_for_authorized_only');
    234             add_post_meta($_pid, $this->wcff_key_prefix .'is_this_group_for_authorized_only', $_REQUEST["wcff_group_authorized_only_radio"]);       
    235         }
    236        
    237         /* Target roles option */
    238         if (isset($_REQUEST["wcff_group_preference_target_roles"])) {
    239             delete_post_meta($_pid, $this->wcff_key_prefix .'wcff_group_preference_target_roles');
    240             add_post_meta($_pid, $this->wcff_key_prefix .'wcff_group_preference_target_roles', json_encode($_REQUEST["wcff_group_preference_target_roles"]));   
    241         }
    242        
    243         /* Update the fields order */
    244         $this->update_fields_order($_pid);
    245        
    246         /* Update the dirty fields meta */
    247         if (isset($_REQUEST["wcff_dirty_fields_configuration"]) && !empty($_REQUEST["wcff_dirty_fields_configuration"])) {   
    248             $fields = json_decode(str_replace('\"','"', $_REQUEST["wcff_dirty_fields_configuration"]), true);
    249             foreach ($fields as $fkey => $meta) {
    250                 if (!isset($meta["updated"])) {
    251                     /* Only update if no 'updated' property found */
    252                     $this->update_field($_pid, $meta);
    253                 }               
    254             }           
    255         }   
    256        
    257         return true;
    258     }
    259    
    260     /**
    261     *
    262     * Update the fields sequence order properties for all fields on a given group (represented by $_pid)<br/>
    263     * Called when Fields Group got saved or updated.
    264     *
    265     * @param integer $_pid
    266     * @return boolean
    267     *
    268     */
    269     public function update_fields_order($_pid = 0) {
    270         $fields = $this->load_fields($_pid, false);
    271         /* Update each fields order property */
    272         foreach ($fields as $key => $field) {
    273             if (isset($_REQUEST[$key."_order"])) {
    274                 $field["order"] = $_REQUEST[$key."_order"];
    275                 update_post_meta($_pid, $key, wp_slash(json_encode($field)));
    276             }
    277         }
    278        
    279         return true;
    280     }
    281    
    282     /**
    283     *
    284     * Load conditional rules for given Fields Group Post
    285     *
    286     * @param integer $_pid
    287     * @return mixed
    288     *
    289     */
    290     public function load_target_products_rules($_pid = 0) {
    291         $condition = array();
    292         if ($_pid) {
    293             $_pid = absint( $_pid );
    294             /* Since we have renamed 'group_rules' meta as 'condition_rules' we need to make sure it is upto date
    295              * and we remove the old 'group_rules' meta as well
    296              **/
    297             $rules = get_post_meta($_pid, $this->wcff_key_prefix .'group_rules', true);
    298             if ($rules && $rules != "") {
    299                 delete_post_meta($_pid, $this->wcff_key_prefix .'group_rules');
    300                 update_post_meta($_pid, $this->wcff_key_prefix .'condition_rules', $rules);
    301             }
    302             $condition = get_post_meta($_pid, $this->wcff_key_prefix .'condition_rules', true);
    303            
    304             if ($condition != "") {
    305                 $condition = json_decode($condition, true);
    306             }
    307         }
    308         return apply_filters($this->wcff_key_prefix .'condition_rules', $condition, $_pid);
    309     }
    310    
    311     public function load_layout_meta($_pid = 0) {
    312         $layout = array();
    313         if ($_pid) {
    314             $_pid = absint($_pid);
    315             $layout = get_post_meta($_pid, $this->wcff_key_prefix .'layout_meta', true);
    316             if ($layout != "") {
    317                 $layout = json_decode($layout, true);
    318             }
    319         }       
    320         return apply_filters($this->wcff_key_prefix .'layout_meta', $layout, $_pid);
    321     }
    322    
    323     public function load_use_custom_layout($_pid) {
    324         $_pid = absint($_pid);
    325         $use_custom_layout = get_post_meta($_pid, ($this->wcff_key_prefix ."use_custom_layout"), true);
    326         return ($use_custom_layout != "") ? $use_custom_layout : "no";
    327     }
    328    
    329     /**
    330     *
    331     * Load locational rules for given Admin Fields Group Post
    332     *
    333     * @param integer $_pid
    334     * @return mixed
    335     *
    336     */
    337     public function load_location_rules($_pid = 0) {
    338         $location = "";
    339         if ($_pid) {
    340             $_pid = absint($_pid);
    341             $location = get_post_meta($_pid, $this->wcff_key_prefix .'location_rules', true);
    342         }       
    343         return apply_filters( $this->wcff_key_prefix .'location_rules', $location, $_pid );
    344     }
    345    
    346     /**
    347     *
    348     * Load locational rules for entire admin fields posts
    349     *
    350     * @return mixed
    351     *
    352     */
    353     public function load_all_wccaf_location_rules() {
    354         $location_rules = array();
    355         $wcffs = get_posts(array(
    356             'post_type' => "wccaf",
    357             'posts_per_page' => -1,
    358             'order' => 'ASC')
    359         );
    360         if (count($wcffs) > 0) {
    361             foreach ($wcffs as $wcff) {
    362                 $temp_rules = get_post_meta($wcff->ID, 'wccaf_location_rules', true);
    363                 $location_rules[] = json_decode($temp_rules, true);             
    364             }
    365         }
    366        
    367         return apply_filters( 'wccaf_all_location_rules', $location_rules );
    368     }
    369    
    370     /**
    371     *
    372     * Used to load all woocommerce products<br/>
    373     * Used in "Conditions" Widget
    374     *
    375     * @return  ARRAY of products ( ids & titles )
    376     *
    377     */
    378     public function load_all_products() {
    379         $productsList = array();
    380         $products = get_posts(array(
    381             'post_type' => 'product',
    382             'posts_per_page' => -1,
    383             'order' => 'ASC')
    384         );
    385        
    386         if (count($products) > 0) {
    387             foreach ($products as $product) {
    388                 $productsList[] = array("id" => $product->ID, "title" => $product->post_title);
    389             }
    390         }
    391        
    392         return apply_filters( 'wcff_products', $productsList );
    393     }
    394    
    395     /**
    396     *
    397     * Used to load all woocommerce products<br/>
    398     * Used in "Conditions" Widget
    399     *
    400     * @return  ARRAY of products ( ids & titles )
    401     *
    402     */
    403     public function load_variable_products() {
    404         $productsList = array();
    405         $products = get_posts(array(
    406             'post_type' => 'product',
    407             'posts_per_page' => -1,
    408             'order' => 'ASC')
    409         );
    410        
    411         if (count($products) > 0) {
    412             $wcG3 = version_compare(WC()->version, '2.2.0', '<');
    413             foreach ($products as $product) {
    414                 $product_ob = $wcG3 ? get_product($product->ID) : wc_get_product($product->ID);             
    415                 if ($product_ob->is_type( 'variable' )){
    416                     $productsList[] = array("id" => $product->ID, "title" => $product->post_title);
    417                 }
    418             }
    419         }
    420        
    421         return apply_filters( 'wcff_products_with_variation', $productsList );
    422     }
    423    
    424     /**
    425     *
    426     * Used to load all woocommerce product category<br/>
    427     * Used in "Conditions" Widget
    428     *
    429     * @return  ARRAY of product categories ( ids & titles )
    430     *
    431     */
    432     public function load_product_categories() {
    433         $product_cats = array();
    434         $pcat_terms = get_terms('product_cat', 'orderby=count&hide_empty=0');
    435        
    436         foreach ($pcat_terms as $pterm) {
    437             $product_cats[] = array("id" => $pterm->slug, "title" => $pterm->name);
    438         }
    439        
    440         return apply_filters( 'wcff_product_categories', $product_cats );
    441     }
    442    
    443     /**
    444     *
    445     * Used to load all woocommerce product tags<br/>
    446     * Used in "Conditions" Widget
    447     *
    448     * @return  ARRAY of product tags ( ids & titles )
    449     *
    450     */
    451     public function load_product_tags() {
    452         $product_tags = array();
    453         $ptag_terms = get_terms('product_tag', 'orderby=count&hide_empty=0');
    454        
    455         foreach ($ptag_terms as $pterm) {
    456             $product_tags[] = array("id" => $pterm->slug, "title" => $pterm->name);
    457         }
    458        
    459         return apply_filters( 'wcff_product_tags', $product_tags );
    460     }
    461    
    462     /**
    463     *
    464     * Used to load all woocommerce product types<br/>
    465     * Used in "Conditions" Widget
    466     *
    467     * @return  ARRAY of product types ( slugs & titles )
    468     *
    469     */
    470     public function load_product_types() {
    471         $product_types = array();
    472         $all_types = array (
    473             'simple'   => __( 'Simple product', 'woocommerce' ),
    474             'grouped'  => __( 'Grouped product', 'woocommerce' ),
    475             'external' => __( 'External/Affiliate product', 'woocommerce' ),
    476             'variable' => __( 'Variable product', 'woocommerce' )
    477         );
    478        
    479         foreach ($all_types as $key => $value) {
    480             $product_types[] = array("id" => $key, "title" => $value);
    481         }
    482        
    483         return apply_filters( 'wcff_product_types', $product_types );
    484     }
    485    
    486     /**
    487     *
    488     * Used to load all woocommerce product types<br/>
    489     * Used in "Conditions" Widget
    490     *
    491     * @return  ARRAY of product types ( slugs & titles )
    492     *
    493     */
    494     public function load_product_variations($parent = 0) {
    495         $products_variation_list = array();
    496         $variations = array();
    497         $arg = array (
    498             'post_type' => 'product_variation',
    499             'posts_per_page' => -1,
    500             'order' => 'ASC'
    501         );
    502         if ($parent != 0) {
    503             $arg['post_parent']  = $parent;
    504         }
    505         $variations = get_posts($arg);
    506         foreach ($variations as $product) {
    507             $products_variation_list[] = array("id" => $product->ID, "title" => $product->post_title);
    508         }
    509         return apply_filters( 'wcff_product_variations', $products_variation_list );
    510     }
    511    
    512     /**
    513     *
    514     * Used to load all woocommerce product tabs<br/>
    515     * Used in "Location" Widget
    516     *
    517     * @return  ARRAY of product tabs ( titles & tab slugs )
    518     *
    519     */
    520     public function load_product_tabs() {
    521         return apply_filters( 'wcff_product_tabs', array (
    522             "General Tab" => "woocommerce_product_options_general_product_data",
    523             "Inventory Tab" => "woocommerce_product_options_inventory_product_data",
    524             "Shipping Tab" => "woocommerce_product_options_shipping",
    525             "Attributes Tab" => "woocommerce_product_options_attributes",
    526             "Related Tab" => "woocommerce_product_options_related",
    527             "Advanced Tab" => "woocommerce_product_options_advanced",
    528             "Variable Tab" => "woocommerce_product_after_variable_attributes"
    529         ));
    530     }
    531    
    532     /**
    533     *
    534     * Used to load all wp context used for meta box<br/>
    535     * Used for laying Admin Fields
    536     *
    537     * @return  ARRAY of meta contexts ( slugs & titles )
    538     *
    539     */
    540     public function load_metabox_contexts() {
    541         return apply_filters( 'wcff_metabox_contexts', array (
    542             "normal" => __( "Normal", "wc-fields-factory" ),
    543             "advanced" => __( "Advanced", "wc-fields-factory" ),
    544             "side" => __( "Side", "wc-fields-factory" )
    545         ));
    546     }
    547    
    548     /**
    549     *
    550     * Used to load all wp priorities used for meta box<br/>
    551     * Used for laying Admin Fields
    552     *
    553     * @return  ARRAY of meta priorities ( slugs & titles )
    554     *
    555     */
    556     public function load_metabox_priorities() {     
    557         return apply_filters( 'wcff_metabox_priorities', array (
    558             "low" => __( "Low", "wc-fields-factory" ),
    559             "high" => __( "High", "wc-fields-factory" ),
    560             "core" => __( "Core", "wc-fields-factory" ),
    561             "default" => __( "Default", "wc-fields-factory" )
    562         ));
    563     }
    564    
    565     /**
    566     *
    567     * Used to load all woocommerce form fields validation types, to built Checkout Fields
    568     *
    569     * @return ARRAY of validation types
    570     *
    571     */
    572     public function load_wcccf_validation_types() {
    573         return apply_filters( 'wcccf_validation_types', array (
    574             "required" => __( "Required", "wc-fields-factory" ),
    575             "phone" => __( "Phone", "wc-fields-factory" ),
    576             "email" => __( "Email", "wc-fields-factory" ),
    577             "postcode" => __( "Post Code", "wc-fields-factory" )
    578         ));
    579     }
    580    
    581     public function load_target_contexts() {
    582         return apply_filters( "wcff_target_context", array (
    583             array("id" => "product", "title" => __("Product", "wc-fields-factory")),
    584             array("id" => "product_cat", "title" => __("Product Category", "wc-fields-factory")),
    585             array("id" => "product_tag", "title" => __("Product Tag", "wc-fields-factory")),
    586             array("id" => "product_type", "title" => __("Product Type", "wc-fields-factory")),
    587             array("id" => "product_variation", "title" => __("Product Variation", "wc-fields-factory"))
    588         ));
    589     }
    590    
    591     public function load_target_logics() {
    592         return apply_filters( "wcff_target_logic", array (
    593             array("id"=>"==", "title"=>__("is equal to", "wc-fields-factory")),
    594             array("id"=>"!=", "title"=>__("is not equal to", "wc-fields-factory"))
    595         ));
    596     }
    597    
    598     public function search_posts($_payload = array()) {
    599        
    600         global $wpdb;
    601         $res = array();     
    602         $posts = array();
    603        
    604         $parent = isset($_payload["parent"]) ? $_payload["parent"] : 0;
    605         $search = isset($_payload["search"]) ? $_payload["search"] : "";       
    606         $post_type = isset($_payload["post_type"]) ? $_payload["post_type"] : "";
    607        
    608         if (absint($parent) != 0) {
    609             $posts = $wpdb->get_results($wpdb->prepare("SELECT ID, post_title FROM $wpdb->posts WHERE post_type='%s' AND post_parent=%d AND post_status='publish' AND post_excerpt LIKE '%s'", $post_type, $parent, '%'. $wpdb->esc_like($search) .'%'));
    610         } else {
    611             $posts = $wpdb->get_results($wpdb->prepare("SELECT ID, post_title FROM $wpdb->posts WHERE post_type='%s' AND post_status='publish' AND post_title LIKE '%s'", $post_type, '%'. $wpdb->esc_like($search) .'%'));
    612         }       
    613    
    614         if ($post_type != "product") {
    615             foreach ($posts as $post) {
    616                 $res[] = array( "id" => $post->{"ID"}, "title" => $post->{"post_title"});
    617             }
    618         } else {
    619             $wcG3 = version_compare(WC()->version, '2.2.0', '<');
    620             foreach ($posts as $post) {
    621                 $product = $wcG3 ? get_product($post->{"ID"}) : wc_get_product($post->{"ID"});
    622                 if ($product->is_type('variable')) {
    623                     $res[] = array( "id" => $post->{"ID"}, "title" => $post->{"post_title"});
    624                 }               
    625             }
    626         }       
    627         return $res;
    628     }
    629 
    630     public function insert_wccvf_map_varioation_level($_payload = array()) {
    631        
    632         $res = false;       
    633        
    634         if (!isset($_payload["rules"]) || !is_array($_payload["rules"]) || empty($_payload["rules"])) {         
    635             return false;
    636         }
    637 
    638         foreach ($_payload["rules"] as $gpid => $new_rules) {
    639             $all_rules = $this->load_target_products_rules($gpid);
    640             if (!is_array($all_rules)) {
    641                 $all_rules = array();
    642             }
    643             /* Append the new rule entry */         
    644             foreach ($new_rules as $new_rule) {
    645                 if (!in_array($new_rule, $all_rules)) {
    646                     $all_rules[] =$new_rule;           
    647                 }           
    648             }
    649             /* Update the condition rules */
    650             delete_post_meta($gpid, $this->wcff_key_prefix .'condition_rules');
    651             $res = add_post_meta($gpid, $this->wcff_key_prefix .'condition_rules', json_encode($all_rules));
    652         }       
    653        
    654         return $res ? true : false;
    655        
    656     }
    657    
    658     public function remove_wccvf_map_variation_level($_payload = array()) {
    659        
    660         if (!isset($_payload["pid"]) && empty($_payload["pid"])) {
    661             return false;
    662         }
    663         if (!isset($_payload["vid"]) || empty($_payload["vid"])) {
    664             return false;
    665         }
    666 
    667         /* Retrive the current condition  rules */
    668         $all_rules = $this->load_target_products_rules($_payload["pid"]);
    669 
    670         if (is_array($all_rules)) {
    671             foreach ($all_rules as $aIndex => $rules) {
    672                 foreach ($rules as $rIndex => $rule) {                 
    673                     if ($rule["endpoint"] == $_payload["vid"]) {
    674                         unset($all_rules[$aIndex][$rIndex]);   
    675                     }                       
    676                 }
    677                 /* Remove the group if it is empty */
    678                 if (empty($all_rules[$aIndex])) {
    679                     unset($all_rules[$aIndex]);
    680                 }
    681             }
    682         }
    683        
    684         /* Update the condition rules */
    685         delete_post_meta($_payload["pid"], $this->wcff_key_prefix .'condition_rules');
    686         return add_post_meta($_payload["pid"], $this->wcff_key_prefix .'condition_rules', json_encode($all_rules));
    687        
    688     }
    689    
    690     /**
    691      *
    692     * This routine does some reverse pulkling data extraction
    693      *
    694     * @return array
    695     */
    696     public function load_map_wccvf_variations() {
    697        
    698         $flag = false;
    699         $result = array();
    700         $vproducts = array();
    701        
    702         $all_rules = array();
    703         $wccvf_rules = array();     
    704        
    705         $wcG3 = version_compare(WC()->version, '2.2.0', '<');       
    706         $products = get_posts(array('post_type' => 'product', 'posts_per_page' => -1));             
    707         $wccvfs = get_posts(array('post_type' => "wccvf", 'posts_per_page' => -1));
    708        
    709         /**
    710          *
    711          * Step 1. 
    712          * Consolidating all rules, from all wccvf post
    713          *
    714          */     
    715         foreach ($wccvfs as $wccvf) {
    716                    
    717             $wccvf_rules = get_post_meta($wccvf->ID, 'wccvf_condition_rules', true);
    718             if ($wccvf_rules != null) {
    719                 $wccvf_rules = json_decode($wccvf_rules, true);
    720                
    721                 /* Well this is a two dimentional array */
    722                 foreach ($wccvf_rules as $rules) {
    723                     if (is_array($rules)) {
    724                         foreach ($rules as $rule) {
    725                             if (is_array($rule)) {
    726                                
    727                                 $rule["group_id"] = $wccvf->ID;
    728                                 $rule["group_title"] = $wccvf->post_title;
    729                                 $all_rules[] = $rule;
    730                                
    731                             }
    732                         }
    733                     }
    734                 }
    735             }                       
    736            
    737         }
    738    
    739         /**
    740          *
    741         * Step 2.
    742         * Fetching all products with variations.
    743          *
    744         */
    745         foreach ($products as $post) {
    746            
    747             $product = $wcG3 ? get_product($post->ID) : wc_get_product($post->ID);
    748             if ($product->is_type( 'variable' )) {
    749                 $wp_query = new WP_Query(array(
    750                     'post_type'         => 'product_variation',
    751                     'post_status'       => 'publish',
    752                     'post_parent'       => $post->ID,
    753                     'posts_per_page'    => -1,
    754                     'fields'            => array('ID', 'post_title')
    755                 ));
    756                 $vproducts[] = array("id" => $post->ID, "title" => $post->post_title, "variations" => $wp_query->posts);
    757             }
    758            
    759         }
    760        
    761         foreach ($vproducts as $product) {
    762             if (is_array($product["variations"])) {
    763                 $variations = array();
    764                
    765                 foreach ($product["variations"] as $variation) {
    766                     $flag = false;
    767                     $fgroups = array();
    768                    
    769                     foreach ($all_rules as $rule) {
    770                         if (absint($rule["endpoint"]) == absint($variation->ID)) {
    771                             $flag = true;
    772                             $fgroups[] = array("gid" => $rule["group_id"], "gtitle" => $rule["group_title"]);
    773                         }
    774                         if ($flag) {
    775                             $variations[$variation->ID] = array("variation_title" => $variation->post_excerpt, "groups" => $fgroups);
    776                         }
    777                     }
    778                     if (!empty($variations)) {
    779                         $result[$product["id"]] = array("product_title" => $product["title"], "variations" => $variations);
    780                     }
    781                 }
    782                
    783             }
    784         }
    785        
    786         return $result;
    787        
    788     }
    789        
    790     public function check_product_for_variation_mappings($_pid, $_type) {
    791        
    792         if ($_pid) {
    793            
    794             $_pid = absint($_pid);       
    795             $this->wcff_key_prefix = $_type . "_";
    796            
    797             $wp_query = new WP_Query(array(
    798                 'post_type'         => 'product_variation',
    799                 'post_status'       => 'publish',
    800                 'post_parent'       => $_pid,
    801                 'posts_per_page'    => -1,
    802                 'fields'            => array('ID', 'post_title')
    803             ));
    804            
    805             $wccvfs = get_posts(array('post_type' => $_type, 'posts_per_page' => -1));         
    806             foreach ($wccvfs as $wccvf) {
    807                
    808                 $wccvf_rules = get_post_meta($wccvf->ID, $_type .'_condition_rules', true);
    809                 if ($wccvf_rules != null) {
    810                     $wccvf_rules = json_decode($wccvf_rules, true);
    811                    
    812                     /* Well this is a two dimentional array */
    813                     foreach ($wccvf_rules as $rules) {
    814                         if (is_array($rules)) {
    815                             foreach ($rules as $rule) {
    816                                 if (is_array($rule)) {                                 
    817                                     foreach ($wp_query->posts as $variation) {
    818                                         if (isset($rule["endpoint"]) && absint($rule["endpoint"]) == absint($variation->ID)) {
    819                                             $this->has_variable_tab_fields = true;
    820                                             return true;
    821                                         }   
    822                                     }                                   
    823                                 }
    824                             }
    825                         }
    826                     }
    827                 }
    828             }           
    829         }
    830        
    831         return false;
    832        
    833     }
    834    
    835     /**
    836     *
    837     * This function is used to load all wcff fields (actualy post meta) for a single WCFF post<br/>
    838     * Mostly used in editing wccpf fields in admin screen
    839     *
    840     * @param   integer $pid    - WCFF Post Id
    841     * @param  boolean  $sort   - Whether returning fields should be sorted
    842     * @return  array
    843     *
    844     */
    845     public function load_fields($_pid = 0, $_sort = true) {
    846        
    847         $fields = array();     
    848         if ($_pid) {
    849             $_pid = absint($_pid);     
    850             $meta = get_post_meta($_pid);
    851            
    852             $excluded_keys = $this->prepare_special_keys();
    853             foreach ($meta as $key => $val) {
    854                 /* Exclude special purpose custom meta */
    855                 if (!in_array($key, $excluded_keys) && (strpos($key, $this->wcff_key_prefix) === 0)) {
    856                     $fields[$key] = json_decode($val[0], true);
    857                 }
    858             }
    859            
    860             if ($_sort) {
    861                 $this->usort_by_column($fields, "order");
    862             }
    863         }
    864        
    865         return apply_filters( $this->wcff_key_prefix .'fields', $fields, $_pid, $_sort );
    866        
    867     }
    868    
    869     /**
    870     *
    871     * Loads all fields of the given Fields Group Post
    872     *
    873     * @param number $_pid
    874     * @param string $_mkey
    875     * @return mixed
    876     *
    877     */
    878     public function load_field($_pid = 0, $_mkey = "") {
    879         $_pid = absint($_pid);
    880         $post = get_post($_pid);
    881         $field = get_post_meta($_pid, $_mkey, true);
    882         if ($field === "") {
    883             $field = "{}";
    884         }
    885         $field = json_decode($field, true);
    886         return apply_filters( $post->post_type .'_field', $field, $_pid, $_mkey );
    887     }
    888    
    889     /**
    890      *
    891     * Create a Unique ID for the field and store with initial data
    892      *
    893     * @param number $_pid
    894     * @param string $_type
    895     * @return string|boolean
    896     */
    897     public function create_field($_pid, $_type, $_order) {
    898         $_pid = absint($_pid);
    899 
    900         $id = $this->generate_unique_id();
    901         $id = apply_filters("wcff_new_field_id", $id);
    902 
    903         $meta = array (
    904             "id" => $id,
    905             "type" => $_type,
    906             "label" => "",
    907             "order" => $_order,
    908             "status" => true
    909         );     
    910         if (add_post_meta($_pid, ($this->wcff_key_prefix . $id), wp_slash(json_encode($meta)))) {
    911             return ($this->wcff_key_prefix . $id);
    912         }       
    913         return false;
    914     }
    915    
    916     /**
    917     *
    918     * Save the given field's config meta as the post meta on a given Fields Group Post.
    919     *
    920     * @param number $_pid
    921     * @param object $_payload
    922     * @return number|false
    923     *
    924     */
    925     public function save_field($_pid, $_payload) {
    926         $_pid = absint($_pid);
    927         $_payload= apply_filters( 'wcff_before_save_'. $this->wcff_key_prefix .'field', $_payload, $_pid );
    928         if (!isset($_payload["name"]) || $_payload["name"] == "_" || $_payload["name"] != "") {
    929             $_payload["key"] = $this->wcff_key_prefix . $this->url_slug($_payload["name"], array('delimiter' => '_'));
    930         }
    931         $flg = add_post_meta($_pid,  $_payload["key"], wp_slash(json_encode($_payload))) == false ? false : true;
    932         return $flg;
    933     }
    934    
    935     public function update_field($_pid, $_payload) {
    936         $msg = "";
    937         $res = true;
    938         $_pid = absint($_pid);
    939         if (isset($_payload["key"])) {
    940             delete_post_meta($_pid, $_payload["key"]);
    941             if (add_post_meta($_pid,  $_payload["key"], wp_slash(json_encode($_payload))) == false) {
    942                 $res = false;
    943                 $msg = __( "Failed to update the custom field", "wc-fields-factory" );
    944             }
    945         }   
    946         return array("res" => $res, "msg" => $msg);
    947     }
    948    
    949     public function toggle_field($_pid, $_key, $_status) {
    950         $msg = "";
    951         $res = true;
    952         $meta_val = get_post_meta($_pid, $_key, true);
    953         if ($meta_val && !empty($meta_val)) {
    954             $field = json_decode(wp_unslash($meta_val), true);
    955             if (isset($field["is_enable"])) {
    956                 $field["is_enable"] = $_status;
    957                 delete_post_meta($_pid, $_key);
    958                 if (add_post_meta($_pid, $_key, wp_slash(json_encode($field))) == false) {
    959                     $res = false;
    960                     $msg = __( "Failed to update.!", "wc-fields-factory" );
    961                 }
    962             } else {
    963                 $res = false;
    964                 $msg = __( "Failed to update, Key is missing.!", "wc-fields-factory" );
    965             }
    966         } else {
    967             $res = false;
    968             $msg = __( "Failed to update, Meta is empty.!", "wc-fields-factory" );
    969         }
    970         return array("res" => $res, "msg" => $msg);
    971     }
    972    
    973     public function clone_group($_pid = 0, $_post_type = "") {
    974         global $wpdb;       
    975         $_pid = ($_pid == 0) ? (isset($_REQUEST["post"]) ? $_REQUEST["post"] : 0) : 0;
    976         $_post_type = ($_post_type == "") ? (isset($_REQUEST["post_type"]) ? $_REQUEST["post_type"] : "") : "";
    977         if (isset($_pid) && $_pid > 0) {
    978             $post = get_post($_pid);
    979             $new_post_id = wp_insert_post(array(
    980                 'comment_status' => $post->comment_status,
    981                 'ping_status'    => $post->ping_status,
    982                 'post_author'    => $post->post_author,
    983                 'post_content'   => $post->post_content,
    984                 'post_excerpt'   => $post->post_excerpt,
    985                 'post_name'      => $post->post_name,
    986                 'post_parent'    => $post->post_parent,
    987                 'post_password'  => $post->post_password,
    988                 'post_status'    => 'publish',
    989                 'post_title'     => "Copy - ". $post->post_title,
    990                 'post_type'      => $post->post_type,
    991                 'to_ping'        => $post->to_ping,
    992                 'menu_order'     => $post->menu_order
    993             ));
    994            
    995             $post_meta_infos = $wpdb->get_results("SELECT meta_key, meta_value FROM $wpdb->postmeta WHERE post_id=$_pid");
    996             if (count($post_meta_infos)!=0) {
    997                 $sql_query_sel = array();
    998                 $sql_query = "INSERT INTO $wpdb->postmeta (post_id, meta_key, meta_value) ";
    999                 foreach ($post_meta_infos as $meta_info) {
    1000                     $meta_key = $meta_info->meta_key;
    1001                     if( $meta_key == '_wp_old_slug' ) continue;
    1002                     $meta_value = addslashes($meta_info->meta_value);
    1003                     $sql_query_sel[]= "SELECT $new_post_id, '$meta_key', '$meta_value'";
    1004                 }
    1005                 $sql_query.= implode(" UNION ALL ", $sql_query_sel);
    1006                 $wpdb->query($sql_query);
    1007             }
    1008         }
    1009         if ($_post_type != "wccvf") {
    1010             wp_redirect( admin_url('edit.php?post_type='. $_post_type));
    1011         } else {
    1012             wp_redirect( admin_url('edit.php?post_type=wccpf&page=variation_fields_config'));
    1013         }       
    1014         exit;
    1015     }
    1016    
    1017     public function clone_field($_pid, $_fkey) {
    1018         $_pid = absint($_pid);
    1019         $id = $this->generate_unique_id();
    1020         $id = apply_filters("wcff_new_field_id", $id);
    1021         $cloned = $this->load_field($_pid, $_fkey);     
    1022         if (is_array($cloned)) {
    1023             $cloned["id"] = $id;
    1024             $cloned["label"] = "Copy - ". $cloned["label"];
    1025             if (add_post_meta($_pid, ($this->wcff_key_prefix . $id), wp_slash(json_encode($cloned)))) {
    1026                 return ($this->wcff_key_prefix . $id);
    1027             }
    1028         }
    1029         return false;
    1030     }
    1031    
    1032     /**
    1033     *
    1034     * Remove the given field from Fields Group Post
    1035     *
    1036     * @param number $_pid
    1037     * @param string $_mkey
    1038     * @return boolean
    1039     *
    1040     */
    1041     public function remove_field($_pid, $_mkey) {
    1042         if ($_pid) {
    1043             $_pid = absint($_pid);
    1044             $post = get_post($_pid);
    1045             do_action($post->post_type .'_before_remove_field', $_mkey, $_pid);
    1046             /* Update the layout meta */
    1047             $layout = $this->load_layout_meta($_pid);
    1048             if (!empty($layout)) {
    1049                 /* Row update */
    1050                 foreach ($layout["rows"] as $rIndex => $row) {
    1051                     foreach($row as $fIndex => $fkey) {
    1052                         if ($_mkey == $fkey) {
    1053                             if (count($row) == 1) {
    1054                                 /* Could be only one field */
    1055                                 unset($layout["rows"][$rIndex]);
    1056                             } else {
    1057                                 $current_field_width = floatval($layout["columns"][$_mkey]["width"]);
    1058                                 /* Could be first field */
    1059                                 if ($fIndex == 0) {
    1060                                     $next_field_width = floatval($layout["columns"][$layout["rows"][$rIndex][$fIndex+1]]["width"]);
    1061                                     $layout["columns"][$layout["rows"][$rIndex][$fIndex+1]]["width"] = ($current_field_width + $next_field_width);
    1062                                 } else {
    1063                                     /* Could be last or middle */
    1064                                     $prev_field_width = floatval($layout["columns"][$layout["rows"][$rIndex][$fIndex-1]]["width"]);
    1065                                     $layout["columns"][$layout["rows"][$rIndex][$fIndex-1]]["width"] = ($current_field_width + $prev_field_width);
    1066                                 }
    1067                                 unset($layout["rows"][$rIndex][$fIndex]);
    1068                             }
    1069                         }
    1070                     }
    1071                 }
    1072                 /* Column update */
    1073                 unset($layout["columns"][$_mkey]);
    1074                
    1075                 delete_post_meta($_pid, $this->wcff_key_prefix .'layout_meta');
    1076                 add_post_meta($_pid, $this->wcff_key_prefix .'layout_meta', json_encode($layout));
    1077             }
    1078            
    1079             return delete_post_meta($_pid, $_mkey);
    1080         }
    1081        
    1082         return false;
    1083     }
    1084    
    1085     /**
    1086      *
    1087     * @param integer $_pid
    1088     * @param string $_type
    1089     * @param string $_template
    1090     * @param string $_fields_location
    1091      *
    1092     */
    1093     public function load_fields_groups_for_product($_pid, $_type = "wccpf", $_template = "single-product", $_fields_location = "", $_is_variation_template = false) {
    1094         /* Holds custom post meta */
    1095         $meta = array();
    1096         /* Holds the fields list */
    1097         $fields = array();
    1098         /**/
    1099         $groups = array();
    1100         /* Holds the final list of fields */
    1101         $all_fields = array();     
    1102         /* Location rules flag */
    1103         $location_passed = false;   
    1104         /* Condition rules flag */
    1105         $target_product_passed = false;
    1106         /**/
    1107         $admin_target_location = array();
    1108                    
    1109         $_pid = absint($_pid);
    1110         $this->wcff_key_prefix = $_type . "_";     
    1111         $wcff_options = wcff()->option->get_options();
    1112        
    1113         /* Reset variable tab field flaq */
    1114         $this->has_variable_tab_fields = false;
    1115                
    1116         /* Special keys that is not part of fields meta */
    1117         $excluded_keys = $this->prepare_special_keys();
    1118        
    1119         /* Fields on archive template Flaq */
    1120         $fields_on_archive = isset($wcff_options["fields_on_archive"]) ? $wcff_options["fields_on_archive"] : "no";
    1121        
    1122         /* Fields location on single product page */
    1123         $global_location_single = isset($wcff_options["field_location"]) ? $wcff_options["field_location"] : "woocommerce_before_add_to_cart_button";
    1124         /* Check user wants custom location */
    1125         if ($global_location_single == "woocommerce_product_custom_location") {
    1126             $global_location_single = isset($wcff_options["custom_product_fields_location"]) ? $wcff_options["custom_product_fields_location"] : "";
    1127         }
    1128      
    1129         /* Fields location for archive product */
    1130         $global_location_archive = isset($wcff_options["field_archive_location"]) ? $wcff_options["field_archive_location"] : "woocommerce_before_shop_loop_item";
    1131         /* Check user wants custom location */
    1132         if ($global_location_archive == "woocommerce_archive_custom_location") {
    1133             $global_location_archive = isset($wcff_options["custom_archive_fields_location"]) ? $wcff_options["custom_archive_fields_location"] : "";
    1134         }
    1135 
    1136         /* Check whether the request for Archive template and fields on archive is enabled */
    1137         if ($_template == "archive-product" && $fields_on_archive == "no") {
    1138             /* No need to go further */
    1139             return apply_filters( 'wcff_fields_for_product', array(), $_pid, $_type, $_template, $_fields_location );
    1140         }
    1141        
    1142         /* Fetch the group posts */
    1143         $group_posts = get_posts(
    1144             array(
    1145                 "post_type" => $_type,
    1146                 "posts_per_page" => -1,
    1147                 "order" => "ASC",
    1148                 "post_status" => array('publish')               
    1149             )
    1150         );     
    1151                
    1152         if (count($group_posts) > 0) {
    1153             /* Loop through all group posts */
    1154             foreach ($group_posts as $g_post) {
    1155                
    1156                 $all_fields = array();             
    1157                 /* Get all custom meta */
    1158                 $fields = get_post_meta($g_post->ID);
    1159                
    1160                 /* Check whether this group is for Authorized users only */
    1161                 $authorized_only = get_post_meta($g_post->ID, $this->wcff_key_prefix."is_this_group_for_authorized_only", true);
    1162                 $authorized_only = (!$authorized_only || $authorized_only == "") ? "no" : $authorized_only;
    1163                 if ($authorized_only == "yes" && !is_user_logged_in()) {
    1164                     continue;
    1165                 }
    1166                
    1167                 /* Retrive the group level role assignment */
    1168                 $targeted_roles = get_post_meta($g_post->ID, $this->wcff_key_prefix ."wcff_group_preference_target_roles", true);
    1169                
    1170                 if ($targeted_roles) {
    1171                     $targeted_roles = json_decode($targeted_roles, true);
    1172                 } else {
    1173                     $targeted_roles = array();
    1174                 }           
    1175                
    1176                 /* If it is for authorized only fields, then check for the roles */
    1177                 if ($authorized_only == "yes" && !$this->check_for_roles($targeted_roles)) {
    1178                     continue;
    1179                 }
    1180                    
    1181                 if ($_template != "any" && $_template != "variable") {
    1182                     /* Check for single-product location rule */
    1183                     if ($_template == "single-product") {
    1184                         /* Group level Location */
    1185                         $field_group_location_single = get_post_meta($g_post->ID, $this->wcff_key_prefix."field_location_on_product", true);
    1186                         $field_group_location_single = empty($field_group_location_single) ? "use_global_setting" : $field_group_location_single;
    1187                        
    1188                         if ($field_group_location_single == "use_global_setting") {
    1189                             if ($_fields_location == "any" || $global_location_single == $_fields_location) {
    1190                                 $location_passed = true;
    1191                             }                           
    1192                         } else if ($_fields_location == "any" || $field_group_location_single == $_fields_location) {
    1193                             $location_passed = true;
    1194                         } else {
    1195                             /* Ignore */
    1196                         }                       
    1197                     } else if ($_template == "archive-product") {
    1198                        /* Check for archive-product location rule */                   
    1199                         $field_group_location_archive = get_post_meta($g_post->ID, $this->wcff_key_prefix."field_location_on_archive", true);
    1200                         $field_group_location_archive = empty( $field_group_location_archive ) ? "none" : $field_group_location_archive;
    1201                        
    1202                         if ($field_group_location_archive == "use_global_setting") {
    1203                             if ($_fields_location == "any" || $global_location_archive == $_fields_location) {
    1204                                 $location_passed = true;
    1205                             }
    1206                         } else if ($_fields_location == "any" || $global_location_archive == $_fields_location) {
    1207                             $location_passed = true;
    1208                         } else {
    1209                             /* Ignore */
    1210                         }
    1211                     } else if ($_template == "admin") {
    1212                         $location_passed = true;
    1213                         $field_group_locations_admin = get_post_meta($g_post->ID, $this->wcff_key_prefix."location_rules", true);                   
    1214                         $field_group_locations_admin = json_decode( $field_group_locations_admin, true );
    1215                         if ($_fields_location != "any") {
    1216                             $location_passed = $this->check_for_location($field_group_locations_admin, $_fields_location);
    1217                         }                               
    1218                     }
    1219                 } else {
    1220                     $location_passed = true;
    1221                 }
    1222                
    1223                 if ($_type == "wccaf") {
    1224                     $admin_target_location = get_post_meta($g_post->ID, $_type .'_location_rules', true);                   
    1225                     $admin_target_location = json_decode($admin_target_location, true);
    1226                 }               
    1227                
    1228                 /* Check for 'variation_tab' location, needs to exclude admin fields which has location of variable tab */
    1229                 if ($_type == "wccaf" && ($_template == "single-product" || $_template == "archive-product")) {               
    1230                     if ($admin_target_location["endpoint"] == "woocommerce_product_after_variable_attributes") {                       
    1231                         $location_passed = false;
    1232                         $this->has_variable_tab_fields = true;
    1233                     }               
    1234                 }
    1235                
    1236                 /* Needs to includes admin fields which has variable tab as target location */
    1237                 if ($_type == "wccaf" && $_is_variation_template) {
    1238                     $location_passed = false;
    1239                     if ($admin_target_location["endpoint"] == "woocommerce_product_after_variable_attributes") {
    1240                         $location_passed = true;                     
    1241                     }
    1242                 }
    1243                
    1244                 /* Finally check for the target products */
    1245                 $product_map_rules = $this->load_target_products_rules($g_post->ID);
    1246                
    1247                 if (is_array($product_map_rules)) {
    1248                     $target_product_passed = true;
    1249                     if ($_pid > 0) {
    1250                         $target_product_passed = $this->check_for_product($_pid, $product_map_rules);
    1251                     }                   
    1252                 } else {
    1253                     $target_product_passed = false;
    1254                 }           
    1255 
    1256                 /* By passing flaq for variation fields (especially from admin fields group - variable tab) */
    1257                 if (($target_product_passed || $_is_variation_template) && $location_passed) {
    1258                     /* Well prepare the field list */
    1259                     foreach ($fields as $key => $meta) {
    1260                         /* Exclude special purpose custom meta */
    1261                         if (!in_array($key, $excluded_keys) && (strpos($key, $this->wcff_key_prefix) === 0)) {
    1262                            
    1263                             $field = json_decode($meta[0], true);
    1264                             if (!isset($field["key"])) {
    1265                                 continue;
    1266                             }
    1267                            
    1268                             /* If it is admin field and the template is for front end, then check for the "show_on_product_page" flaq */
    1269                             if (($_type == "wccaf" && isset($field["show_on_product_page"])) && ($_template == "single-product" || $_template == "archive-product" || $_template == "variable")) {
    1270                                 if ($field["show_on_product_page"] == "no") {
    1271                                     continue;
    1272                                 }                               
    1273                             }
    1274                            
    1275                             /* Check for authorized user only flaq */
    1276                             $authorized_only = isset($field["login_user_field"]) ? $field["login_user_field"] : "no";                           
    1277                             if ($authorized_only == "yes") {
    1278                                 $targeted_roles = isset($field["show_for_roles"]) ? $field["show_for_roles"] : array();                             
    1279                                 /* If it is for authorized only fields, then check for the roles */
    1280                                 if (!$this->check_for_roles($targeted_roles)) {
    1281                                     continue;
    1282                                 }
    1283                             }                   
    1284                            
    1285                             if(isset($field["is_enable"])) {
    1286                                 if ($field["is_enable"]) {
    1287                                     $all_fields[] = $field;
    1288                                 }                               
    1289                             } else {
    1290                                 $all_fields[] = $field;
    1291                             }
    1292                         }
    1293                     }
    1294                    
    1295                     /* Sort the fields */
    1296                     $this->usort_by_column($all_fields, "order");
    1297                    
    1298                     $groups[] = array(
    1299                         "id" => $g_post->ID,
    1300                         "type" => $_type,
    1301                         "fields" => $all_fields,
    1302                         "title" =>  get_the_title($g_post->ID),
    1303                         "layout" => $this->load_layout_meta($g_post->ID),
    1304                         "use_custom_layout" => $this->load_use_custom_layout($g_post->ID),
    1305                         "show_title" => get_post_meta($g_post->ID, ($this->wcff_key_prefix ."show_group_title"), true),
    1306                         "is_clonable" => get_post_meta($g_post->ID, ($this->wcff_key_prefix ."is_this_group_clonable"), true),                     
    1307                         "label_alignment" => get_post_meta($g_post->ID, ($this->wcff_key_prefix ."fields_label_alignement"), true),
    1308                         "template_single_location" => get_post_meta($g_post->ID, ($this->wcff_key_prefix ."field_location_on_product"), true),
     14   
     15    /*
     16     *
     17    * Namespace for WCFF related post meta
     18    * "wccpf_" for Custom product page Fields ( Front end product page )
     19    * "wccaf_" for Custom admin page fields ( for Admin Products )
     20    * "wccvf_" for Custom admin page fields ( for Variation Fields )
     21    * "wcccf_" for Custom admin page fields ( for Checkout Fields )
     22     *
     23    **/
     24    private $wcff_key_prefix = "wccpf_";
     25   
     26    /* Holds all the supported field's specific configuration meta */
     27    private $fields_meta = array();
     28   
     29    /* Holds all the configuration meta that are common to all fields ( both Product as well as Admin ) */
     30    private $common_meta = array();
     31   
     32    /* Holds all the configuration meta that are common to Admin Fields */
     33    private $wccaf_common_meta = array();
     34   
     35    /**/
     36    public $has_variable_tab_fields = false;
     37   
     38    /*
     39     *
     40    * Cusdtom post meta Keys that are used by WCFF for various purposes
     41     *
     42    * */
     43    public $special_keys = array(
     44        'fee_rules',
     45        'layout_meta',
     46        'field_rules',
     47        'group_rules',
     48        'pricing_rules',
     49        'location_rules',
     50        'condition_rules',
     51        'show_group_title',
     52        'use_custom_layout',
     53        'product_tab_title',
     54        'product_tab_priority',
     55        'is_this_group_clonable',
     56        'fields_label_alignement',
     57        'field_location_on_product',
     58        'field_location_on_archive',
     59        'is_this_group_for_authorized_only',
     60        'wcff_group_preference_target_roles'
     61    );
     62   
     63    public function __construct() {
     64        /* Wordpress's Save Post action hook
     65        * This is where we would save all the rules for the Fields Group ( post ) that is being saved */
     66        add_action( 'save_post', array($this, 'on_save_post' ), 1, 3 );
     67    }
     68   
     69    /**
     70    *
     71    * Set the current post type properties,<br/>
     72    * based on this only all the subsequent fields related operation will happen<br/>
     73    * this option could be either 'wccpf' for product fields or 'wccaf' for admin fields.
     74    *
     75    * @param string $_type
     76    *
     77    */
     78    public function set_current_post_type($_type = "wccpf") {
     79        $this->wcff_key_prefix = $_type . "_";
     80    }
     81   
     82    /**
     83    *
     84    * Return the Fields config meta for Factory View<br/>
     85    * Contains entire (specific to each fields) config meta list for each field type.
     86    *
     87    * @return array
     88    *
     89    */
     90    public function get_fields_meta() {
     91        /* Make sure the meta is loaded */
     92        $this->load_core_meta();
     93        return $this->fields_meta;
     94    }
     95   
     96    /**
     97    *
     98    * Return the Fields config common meta for Factory View<br/>
     99    * Contains entire (common for all fields) config meta list for each field type.
     100    *
     101    * @return array
     102    *
     103    */
     104    public function get_fields_common_meta() {
     105        /* Make sure the meta is loaded */
     106        $this->load_core_meta();
     107        return $this->common_meta;
     108    }
     109   
     110    /**
     111    *
     112    * Return the Admin Fields config common meta for Factory View<br/>
     113    * Contains entire (common for all admin fields) config meta list for each field type.
     114    *
     115    * @return array
     116    *
     117    */
     118    public function get_admin_fields_comman_meta() {
     119        /* Make sure the meta is loaded */
     120        $this->load_core_meta();
     121        return $this->wccaf_common_meta;
     122    }
     123   
     124    /**
     125    *
     126    * Loads Fields configuration meta from the file system<br>
     127    * Fields specific configuration meta from 'meta/wcff-meta.php'<br>
     128    * Common configuration meta from 'meta/wcff-common-meta.php'<br>
     129    * Common admin configuration meta from 'meta/wcff-common-wccaf-meta.php'
     130    *
     131    */
     132    private function load_core_meta() {
     133        /* Load core fields config meta */
     134        if (!is_array($this->fields_meta) || empty( $this->fields_meta)) {
     135            $this->fields_meta = include('meta/wcff-meta.php');
     136        }
     137        /* Load common config meta for all fields */
     138        if (!is_array($this->common_meta) || empty($this->common_meta)) {
     139            $this->common_meta = include('meta/wcff-common-meta.php');
     140        }
     141        /* Load common config meta for admin fields */
     142        if (!is_array($this->wccaf_common_meta) || empty($this->wccaf_common_meta)) {
     143            $this->wccaf_common_meta = include('meta/wcff-common-wccaf-meta.php');
     144        }
     145    }
     146   
     147    /**
     148    *
     149    * Called whenever user 'Update' or 'Save' post from wp-admin single post view<br/>
     150    * This is where the various (Product, Cat, Location ... ) rules for the fields group will be stored in their respective post meta.
     151    *
     152    * @param integer $_pid
     153    * @param WP_Post $_post
     154    * @param boolean $_update
     155    * @return void|boolean
     156    *
     157    */
     158    public function on_save_post($_pid, $_post, $_update) {
     159        /* Maje sure the post types are valid */
     160        if (!$_pid || ! $_post || ($_post->post_type != "wccpf" && $_post->post_type != "wccaf" && $_post->post_type != "wccvf" && $_post->post_type != "wcccf")) {
     161            return false;
     162        }
     163       
     164        $_pid = absint($_pid);
     165       
     166        /* Prepare the post type prefix for meta key */
     167        $this->wcff_key_prefix = $_post->post_type . "_";
     168       
     169        /* Conditional rules - determine which fields group belongs to which products */
     170        if (isset($_REQUEST["wcff_condition_rules"])) {
     171            delete_post_meta($_pid, $this->wcff_key_prefix .'condition_rules');
     172            add_post_meta($_pid, $this->wcff_key_prefix .'condition_rules', $_REQUEST["wcff_condition_rules"]);
     173        }
     174       
     175        /* Location rules - specific to Admin Fields */
     176        if (isset($_REQUEST["wcff_location_rules"])) {
     177            delete_post_meta($_pid, $this->wcff_key_prefix .'location_rules');
     178            add_post_meta($_pid, $this->wcff_key_prefix .'location_rules', $_REQUEST["wcff_location_rules"]);
     179        }
     180       
     181        /**/
     182        if (isset($_REQUEST["wcff_layout_meta"])) {
     183            delete_post_meta($_pid, $this->wcff_key_prefix .'layout_meta');
     184            add_post_meta($_pid, $this->wcff_key_prefix .'layout_meta', $_REQUEST["wcff_layout_meta"]);
     185        }
     186       
     187        if (isset($_REQUEST["wcff_use_custom_layout"])) {
     188            delete_post_meta($_pid, $this->wcff_key_prefix .'use_custom_layout');
     189            add_post_meta($_pid, $this->wcff_key_prefix .'use_custom_layout', "yes");
     190        } else {
     191            delete_post_meta($_pid, $this->wcff_key_prefix .'use_custom_layout');
     192            add_post_meta($_pid, $this->wcff_key_prefix .'use_custom_layout', "no");
     193        }
     194       
     195        /* Field location for each field's group */
     196        if (isset($_REQUEST["field_location_on_product"])) {
     197            delete_post_meta($_pid, $this->wcff_key_prefix .'field_location_on_product');
     198            add_post_meta($_pid, $this->wcff_key_prefix .'field_location_on_product', $_REQUEST["field_location_on_product"]);
     199            delete_post_meta($_pid, $this->wcff_key_prefix .'product_tab_title');
     200            delete_post_meta($_pid, $this->wcff_key_prefix .'product_tab_priority');
     201            if ($_REQUEST["field_location_on_product"] == "woocommerce_single_product_tab" && isset($_REQUEST["product_tab_config_title"])) {
     202                add_post_meta($_pid, $this->wcff_key_prefix .'product_tab_title', $_REQUEST["product_tab_config_title"]);
     203                add_post_meta($_pid, $this->wcff_key_prefix .'product_tab_priority', $_REQUEST["product_tab_config_priority"]);
     204            }
     205        }
     206       
     207        /* Field location for archive page */
     208        if (isset($_REQUEST["field_location_on_archive"])) {
     209            delete_post_meta($_pid, $this->wcff_key_prefix .'field_location_on_archive');
     210            add_post_meta($_pid, $this->wcff_key_prefix .'field_location_on_archive', $_REQUEST["field_location_on_archive"]);
     211        }
     212       
     213        /* Group level cloning option */
     214        if (isset($_REQUEST["wcff_group_clonable_radio"])) {
     215            delete_post_meta($_pid, $this->wcff_key_prefix .'is_this_group_clonable');
     216            add_post_meta($_pid, $this->wcff_key_prefix .'is_this_group_clonable', $_REQUEST["wcff_group_clonable_radio"]);
     217        }
     218       
     219        /* Group title display option */
     220        if (isset($_REQUEST["wcff_group_title_radio"])) {
     221            delete_post_meta($_pid, $this->wcff_key_prefix .'show_group_title');
     222            add_post_meta($_pid, $this->wcff_key_prefix .'show_group_title', $_REQUEST["wcff_group_title_radio"]);
     223        }
     224       
     225        /**/
     226        if (isset($_REQUEST["wcff_label_alignment_radio"])) {
     227            delete_post_meta($_pid, $this->wcff_key_prefix .'fields_label_alignement');
     228            add_post_meta($_pid, $this->wcff_key_prefix .'fields_label_alignement', $_REQUEST["wcff_label_alignment_radio"]);
     229        }
     230       
     231        /* Authorized users only option */
     232        if (isset($_REQUEST["wcff_group_authorized_only_radio"])) {
     233            delete_post_meta($_pid, $this->wcff_key_prefix .'is_this_group_for_authorized_only');
     234            add_post_meta($_pid, $this->wcff_key_prefix .'is_this_group_for_authorized_only', $_REQUEST["wcff_group_authorized_only_radio"]);
     235        }
     236       
     237        /* Target roles option */
     238        if (isset($_REQUEST["wcff_group_preference_target_roles"])) {
     239            delete_post_meta($_pid, $this->wcff_key_prefix .'wcff_group_preference_target_roles');
     240            add_post_meta($_pid, $this->wcff_key_prefix .'wcff_group_preference_target_roles', json_encode($_REQUEST["wcff_group_preference_target_roles"]));
     241        }
     242       
     243        /* Update the fields order */
     244        $this->update_fields_order($_pid);
     245       
     246        /* Update the dirty fields meta */
     247        if (isset($_REQUEST["wcff_dirty_fields_configuration"]) && !empty($_REQUEST["wcff_dirty_fields_configuration"])) {
     248            $fields = json_decode(str_replace('\"','"', $_REQUEST["wcff_dirty_fields_configuration"]), true);
     249            foreach ($fields as $fkey => $meta) {
     250                if (!isset($meta["updated"])) {
     251                    /* Only update if no 'updated' property found */
     252                    $this->update_field($_pid, $meta);
     253                }
     254            }
     255        }
     256       
     257        return true;
     258    }
     259   
     260    /**
     261    *
     262    * Update the fields sequence order properties for all fields on a given group (represented by $_pid)<br/>
     263    * Called when Fields Group got saved or updated.
     264    *
     265    * @param integer $_pid
     266    * @return boolean
     267    *
     268    */
     269    public function update_fields_order($_pid = 0) {
     270        $fields = $this->load_fields($_pid, false);
     271        /* Update each fields order property */
     272        foreach ($fields as $key => $field) {
     273            if (isset($_REQUEST[$key."_order"])) {
     274                $field["order"] = $_REQUEST[$key."_order"];
     275                update_post_meta($_pid, $key, wp_slash(json_encode($field)));
     276            }
     277        }
     278       
     279        return true;
     280    }
     281   
     282    /**
     283    *
     284    * Load conditional rules for given Fields Group Post
     285    *
     286    * @param integer $_pid
     287    * @return mixed
     288    *
     289    */
     290    public function load_target_products_rules($_pid = 0) {
     291        $condition = array();
     292        if ($_pid) {
     293            $_pid = absint( $_pid );
     294            /* Since we have renamed 'group_rules' meta as 'condition_rules' we need to make sure it is upto date
     295             * and we remove the old 'group_rules' meta as well
     296             **/
     297            $rules = get_post_meta($_pid, $this->wcff_key_prefix .'group_rules', true);
     298            if ($rules && $rules != "") {
     299                delete_post_meta($_pid, $this->wcff_key_prefix .'group_rules');
     300                update_post_meta($_pid, $this->wcff_key_prefix .'condition_rules', $rules);
     301            }
     302            $condition = get_post_meta($_pid, $this->wcff_key_prefix .'condition_rules', true);
     303           
     304            if ($condition != "") {
     305                $condition = json_decode($condition, true);
     306            }
     307        }
     308        return apply_filters($this->wcff_key_prefix .'condition_rules', $condition, $_pid);
     309    }
     310   
     311    public function load_layout_meta($_pid = 0) {
     312        $layout = array();
     313        if ($_pid) {
     314            $_pid = absint($_pid);
     315            $layout = get_post_meta($_pid, $this->wcff_key_prefix .'layout_meta', true);
     316            if ($layout != "") {
     317                $layout = json_decode($layout, true);
     318            }
     319        }
     320        return apply_filters($this->wcff_key_prefix .'layout_meta', $layout, $_pid);
     321    }
     322   
     323    public function load_use_custom_layout($_pid) {
     324        $_pid = absint($_pid);
     325        $use_custom_layout = get_post_meta($_pid, ($this->wcff_key_prefix ."use_custom_layout"), true);
     326        return ($use_custom_layout != "") ? $use_custom_layout : "no";
     327    }
     328   
     329    /**
     330    *
     331    * Load locational rules for given Admin Fields Group Post
     332    *
     333    * @param integer $_pid
     334    * @return mixed
     335    *
     336    */
     337    public function load_location_rules($_pid = 0) {
     338        $location = "";
     339        if ($_pid) {
     340            $_pid = absint($_pid);
     341            $location = get_post_meta($_pid, $this->wcff_key_prefix .'location_rules', true);
     342        }
     343        return apply_filters( $this->wcff_key_prefix .'location_rules', $location, $_pid );
     344    }
     345   
     346    /**
     347    *
     348    * Load locational rules for entire admin fields posts
     349    *
     350    * @return mixed
     351    *
     352    */
     353    public function load_all_wccaf_location_rules() {
     354        $location_rules = array();
     355        $wcffs = get_posts(array(
     356            'post_type' => "wccaf",
     357            'posts_per_page' => -1,
     358            'order' => 'ASC')
     359            );
     360        if (count($wcffs) > 0) {
     361            foreach ($wcffs as $wcff) {
     362                $temp_rules = get_post_meta($wcff->ID, 'wccaf_location_rules', true);
     363                $location_rules[] = json_decode($temp_rules, true);
     364            }
     365        }
     366       
     367        return apply_filters( 'wccaf_all_location_rules', $location_rules );
     368    }
     369   
     370    /**
     371    *
     372    * Used to load all woocommerce products<br/>
     373    * Used in "Conditions" Widget
     374    *
     375    * @return  ARRAY of products ( ids & titles )
     376    *
     377    */
     378    public function load_all_products() {
     379        $productsList = array();
     380        $products = get_posts(array(
     381            'post_type' => 'product',
     382            'posts_per_page' => -1,
     383            'order' => 'ASC')
     384            );
     385       
     386        if (count($products) > 0) {
     387            foreach ($products as $product) {
     388                $productsList[] = array("id" => $product->ID, "title" => $product->post_title);
     389            }
     390        }
     391       
     392        return apply_filters( 'wcff_products', $productsList );
     393    }
     394   
     395    /**
     396    *
     397    * Used to load all woocommerce products<br/>
     398    * Used in "Conditions" Widget
     399    *
     400    * @return  ARRAY of products ( ids & titles )
     401    *
     402    */
     403    public function load_variable_products() {
     404        $productsList = array();
     405        $products = get_posts(array(
     406            'post_type' => 'product',
     407            'posts_per_page' => -1,
     408            'order' => 'ASC')
     409            );
     410       
     411        if (count($products) > 0) {
     412            $wcG3 = version_compare(WC()->version, '2.2.0', '<');
     413            foreach ($products as $product) {
     414                $product_ob = $wcG3 ? get_product($product->ID) : wc_get_product($product->ID);
     415                if ($product_ob->is_type( 'variable' )){
     416                    $productsList[] = array("id" => $product->ID, "title" => $product->post_title);
     417                }
     418            }
     419        }
     420       
     421        return apply_filters( 'wcff_products_with_variation', $productsList );
     422    }
     423   
     424    /**
     425    *
     426    * Used to load all woocommerce product category<br/>
     427    * Used in "Conditions" Widget
     428    *
     429    * @return  ARRAY of product categories ( ids & titles )
     430    *
     431    */
     432    public function load_product_categories() {
     433        $product_cats = array();
     434        $pcat_terms = get_terms('product_cat', 'orderby=count&hide_empty=0');
     435       
     436        foreach ($pcat_terms as $pterm) {
     437            $product_cats[] = array("id" => $pterm->slug, "title" => $pterm->name);
     438        }
     439       
     440        return apply_filters( 'wcff_product_categories', $product_cats );
     441    }
     442   
     443    /**
     444    *
     445    * Used to load all woocommerce product tags<br/>
     446    * Used in "Conditions" Widget
     447    *
     448    * @return  ARRAY of product tags ( ids & titles )
     449    *
     450    */
     451    public function load_product_tags() {
     452        $product_tags = array();
     453        $ptag_terms = get_terms('product_tag', 'orderby=count&hide_empty=0');
     454       
     455        foreach ($ptag_terms as $pterm) {
     456            $product_tags[] = array("id" => $pterm->slug, "title" => $pterm->name);
     457        }
     458       
     459        return apply_filters( 'wcff_product_tags', $product_tags );
     460    }
     461   
     462    /**
     463    *
     464    * Used to load all woocommerce product types<br/>
     465    * Used in "Conditions" Widget
     466    *
     467    * @return  ARRAY of product types ( slugs & titles )
     468    *
     469    */
     470    public function load_product_types() {
     471        $product_types = array();
     472        $all_types = array (
     473            'simple'   => __( 'Simple product', 'woocommerce' ),
     474            'grouped'  => __( 'Grouped product', 'woocommerce' ),
     475            'external' => __( 'External/Affiliate product', 'woocommerce' ),
     476            'variable' => __( 'Variable product', 'woocommerce' )
     477        );
     478       
     479        foreach ($all_types as $key => $value) {
     480            $product_types[] = array("id" => $key, "title" => $value);
     481        }
     482       
     483        return apply_filters( 'wcff_product_types', $product_types );
     484    }
     485   
     486    /**
     487    *
     488    * Used to load all woocommerce product types<br/>
     489    * Used in "Conditions" Widget
     490    *
     491    * @return  ARRAY of product types ( slugs & titles )
     492    *
     493    */
     494    public function load_product_variations($parent = 0) {
     495        $products_variation_list = array();
     496        $variations = array();
     497        $arg = array (
     498            'post_type' => 'product_variation',
     499            'posts_per_page' => -1,
     500            'order' => 'ASC'
     501        );
     502        if ($parent != 0) {
     503            $arg['post_parent']  = $parent;
     504        }
     505        $variations = get_posts($arg);
     506        foreach ($variations as $product) {
     507            $products_variation_list[] = array("id" => $product->ID, "title" => $product->post_title);
     508        }
     509        return apply_filters( 'wcff_product_variations', $products_variation_list );
     510    }
     511   
     512    /**
     513    *
     514    * Used to load all woocommerce product tabs<br/>
     515    * Used in "Location" Widget
     516    *
     517    * @return  ARRAY of product tabs ( titles & tab slugs )
     518    *
     519    */
     520    public function load_product_tabs() {
     521        return apply_filters( 'wcff_product_tabs', array (
     522            "General Tab" => "woocommerce_product_options_general_product_data",
     523            "Inventory Tab" => "woocommerce_product_options_inventory_product_data",
     524            "Shipping Tab" => "woocommerce_product_options_shipping",
     525            "Attributes Tab" => "woocommerce_product_options_attributes",
     526            "Related Tab" => "woocommerce_product_options_related",
     527            "Advanced Tab" => "woocommerce_product_options_advanced",
     528            "Variable Tab" => "woocommerce_product_after_variable_attributes"
     529        ));
     530    }
     531   
     532    /**
     533    *
     534    * Used to load all wp context used for meta box<br/>
     535    * Used for laying Admin Fields
     536    *
     537    * @return  ARRAY of meta contexts ( slugs & titles )
     538    *
     539    */
     540    public function load_metabox_contexts() {
     541        return apply_filters( 'wcff_metabox_contexts', array (
     542            "normal" => __( "Normal", "wc-fields-factory" ),
     543            "advanced" => __( "Advanced", "wc-fields-factory" ),
     544            "side" => __( "Side", "wc-fields-factory" )
     545        ));
     546    }
     547   
     548    /**
     549    *
     550    * Used to load all wp priorities used for meta box<br/>
     551    * Used for laying Admin Fields
     552    *
     553    * @return  ARRAY of meta priorities ( slugs & titles )
     554    *
     555    */
     556    public function load_metabox_priorities() {
     557        return apply_filters( 'wcff_metabox_priorities', array (
     558            "low" => __( "Low", "wc-fields-factory" ),
     559            "high" => __( "High", "wc-fields-factory" ),
     560            "core" => __( "Core", "wc-fields-factory" ),
     561            "default" => __( "Default", "wc-fields-factory" )
     562        ));
     563    }
     564   
     565    /**
     566    *
     567    * Used to load all woocommerce form fields validation types, to built Checkout Fields
     568    *
     569    * @return ARRAY of validation types
     570    *
     571    */
     572    public function load_wcccf_validation_types() {
     573        return apply_filters( 'wcccf_validation_types', array (
     574            "required" => __( "Required", "wc-fields-factory" ),
     575            "phone" => __( "Phone", "wc-fields-factory" ),
     576            "email" => __( "Email", "wc-fields-factory" ),
     577            "postcode" => __( "Post Code", "wc-fields-factory" )
     578        ));
     579    }
     580   
     581    public function load_target_contexts() {
     582        return apply_filters( "wcff_target_context", array (
     583            array("id" => "product", "title" => __("Product", "wc-fields-factory")),
     584            array("id" => "product_cat", "title" => __("Product Category", "wc-fields-factory")),
     585            array("id" => "product_tag", "title" => __("Product Tag", "wc-fields-factory")),
     586            array("id" => "product_type", "title" => __("Product Type", "wc-fields-factory")),
     587            array("id" => "product_variation", "title" => __("Product Variation", "wc-fields-factory"))
     588        ));
     589    }
     590   
     591    public function load_target_logics() {
     592        return apply_filters( "wcff_target_logic", array (
     593            array("id"=>"==", "title"=>__("is equal to", "wc-fields-factory")),
     594            array("id"=>"!=", "title"=>__("is not equal to", "wc-fields-factory"))
     595        ));
     596    }
     597   
     598    public function search_posts($_payload = array()) {
     599       
     600        global $wpdb;
     601        $res = array();
     602        $posts = array();
     603       
     604        $parent = isset($_payload["parent"]) ? $_payload["parent"] : 0;
     605        $search = isset($_payload["search"]) ? $_payload["search"] : "";
     606        $post_type = isset($_payload["post_type"]) ? $_payload["post_type"] : "";
     607       
     608        if (absint($parent) != 0) {
     609            $posts = $wpdb->get_results($wpdb->prepare("SELECT ID, post_title FROM $wpdb->posts WHERE post_type='%s' AND post_parent=%d AND post_status='publish' AND post_excerpt LIKE '%s'", $post_type, $parent, '%'. $wpdb->esc_like($search) .'%'));
     610        } else {
     611            $posts = $wpdb->get_results($wpdb->prepare("SELECT ID, post_title FROM $wpdb->posts WHERE post_type='%s' AND post_status='publish' AND post_title LIKE '%s'", $post_type, '%'. $wpdb->esc_like($search) .'%'));
     612        }
     613       
     614        if ($post_type != "product") {
     615            foreach ($posts as $post) {
     616                $res[] = array( "id" => $post->{"ID"}, "title" => $post->{"post_title"});
     617            }
     618        } else {
     619            $wcG3 = version_compare(WC()->version, '2.2.0', '<');
     620            foreach ($posts as $post) {
     621                $product = $wcG3 ? get_product($post->{"ID"}) : wc_get_product($post->{"ID"});
     622                if ($product->is_type('variable')) {
     623                    $res[] = array( "id" => $post->{"ID"}, "title" => $post->{"post_title"});
     624                }
     625            }
     626        }
     627        return $res;
     628    }
     629   
     630    public function insert_wccvf_map_varioation_level($_payload = array()) {
     631       
     632        $res = false;
     633       
     634        if (!isset($_payload["rules"]) || !is_array($_payload["rules"]) || empty($_payload["rules"])) {
     635            return false;
     636        }
     637       
     638        foreach ($_payload["rules"] as $gpid => $new_rules) {
     639            $all_rules = $this->load_target_products_rules($gpid);
     640            if (!is_array($all_rules)) {
     641                $all_rules = array();
     642            }
     643            /* Append the new rule entry */
     644            foreach ($new_rules as $new_rule) {
     645                if (!in_array($new_rule, $all_rules)) {
     646                    $all_rules[] =$new_rule;
     647                }
     648            }
     649            /* Update the condition rules */
     650            delete_post_meta($gpid, $this->wcff_key_prefix .'condition_rules');
     651            $res = add_post_meta($gpid, $this->wcff_key_prefix .'condition_rules', json_encode($all_rules));
     652        }
     653        
     654        return $res ? true : false;
     655       
     656    }
     657   
     658    public function remove_wccvf_map_variation_level($_payload = array()) {
     659       
     660        if (!isset($_payload["pid"]) && empty($_payload["pid"])) {
     661            return false;
     662        }
     663        if (!isset($_payload["vid"]) || empty($_payload["vid"])) {
     664            return false;
     665        }
     666       
     667        /* Retrive the current condition  rules */
     668        $all_rules = $this->load_target_products_rules($_payload["pid"]);
     669       
     670        if (is_array($all_rules)) {
     671            foreach ($all_rules as $aIndex => $rules) {
     672                foreach ($rules as $rIndex => $rule) {
     673                    if ($rule["endpoint"] == $_payload["vid"]) {
     674                        unset($all_rules[$aIndex][$rIndex]);
     675                    }
     676                }
     677                /* Remove the group if it is empty */
     678                if (empty($all_rules[$aIndex])) {
     679                    unset($all_rules[$aIndex]);
     680                }
     681            }
     682        }
     683       
     684        /* Update the condition rules */
     685        delete_post_meta($_payload["pid"], $this->wcff_key_prefix .'condition_rules');
     686        return add_post_meta($_payload["pid"], $this->wcff_key_prefix .'condition_rules', json_encode($all_rules));
     687       
     688    }
     689   
     690    /**
     691     *
     692    * This routine does some reverse pulkling data extraction
     693     *
     694    * @return array
     695    */
     696    public function load_map_wccvf_variations() {
     697       
     698        $flag = false;
     699        $result = array();
     700        $vproducts = array();
     701       
     702        $all_rules = array();
     703        $wccvf_rules = array();
     704       
     705        $wcG3 = version_compare(WC()->version, '2.2.0', '<');
     706        $products = get_posts(array('post_type' => 'product', 'posts_per_page' => -1));
     707        $wccvfs = get_posts(array('post_type' => "wccvf", 'posts_per_page' => -1));
     708       
     709        /**
     710         *
     711         * Step 1.
     712         * Consolidating all rules, from all wccvf post
     713         *
     714         */
     715        foreach ($wccvfs as $wccvf) {
     716           
     717            $wccvf_rules = get_post_meta($wccvf->ID, 'wccvf_condition_rules', true);
     718            if ($wccvf_rules != null) {
     719                $wccvf_rules = json_decode($wccvf_rules, true);
     720               
     721                /* Well this is a two dimentional array */
     722                foreach ($wccvf_rules as $rules) {
     723                    if (is_array($rules)) {
     724                        foreach ($rules as $rule) {
     725                            if (is_array($rule)) {
     726                               
     727                                $rule["group_id"] = $wccvf->ID;
     728                                $rule["group_title"] = $wccvf->post_title;
     729                                $all_rules[] = $rule;
     730                               
     731                            }
     732                        }
     733                    }
     734                }
     735            }
     736           
     737        }
     738       
     739        /**
     740         *
     741        * Step 2.
     742        * Fetching all products with variations.
     743         *
     744        */
     745        foreach ($products as $post) {
     746           
     747            $product = $wcG3 ? get_product($post->ID) : wc_get_product($post->ID);
     748            if ($product->is_type( 'variable' )) {
     749                $wp_query = new WP_Query(array(
     750                    'post_type'         => 'product_variation',
     751                    'post_status'       => 'publish',
     752                    'post_parent'       => $post->ID,
     753                    'posts_per_page'    => -1,
     754                    'fields'            => array('ID', 'post_title')
     755                ));
     756                $vproducts[] = array("id" => $post->ID, "title" => $post->post_title, "variations" => $wp_query->posts);
     757            }
     758           
     759        }
     760       
     761        foreach ($vproducts as $product) {
     762            if (is_array($product["variations"])) {
     763                $variations = array();
     764               
     765                foreach ($product["variations"] as $variation) {
     766                    $flag = false;
     767                    $fgroups = array();
     768                   
     769                    foreach ($all_rules as $rule) {
     770                        if (absint($rule["endpoint"]) == absint($variation->ID)) {
     771                            $flag = true;
     772                            $fgroups[] = array("gid" => $rule["group_id"], "gtitle" => $rule["group_title"]);
     773                        }
     774                        if ($flag) {
     775                            $variations[$variation->ID] = array("variation_title" => $variation->post_excerpt, "groups" => $fgroups);
     776                        }
     777                    }
     778                    if (!empty($variations)) {
     779                        $result[$product["id"]] = array("product_title" => $product["title"], "variations" => $variations);
     780                    }
     781                }
     782               
     783            }
     784        }
     785       
     786        return $result;
     787       
     788    }
     789   
     790    public function check_product_for_variation_mappings($_pid, $_type) {
     791       
     792        if ($_pid) {
     793            
     794            $_pid = absint($_pid);
     795            $this->wcff_key_prefix = $_type . "_";
     796           
     797            $wp_query = new WP_Query(array(
     798                'post_type'         => 'product_variation',
     799                'post_status'       => 'publish',
     800                'post_parent'       => $_pid,
     801                'posts_per_page'    => -1,
     802                'fields'            => array('ID', 'post_title')
     803            ));
     804           
     805            $wccvfs = get_posts(array('post_type' => $_type, 'posts_per_page' => -1));
     806            foreach ($wccvfs as $wccvf) {
     807               
     808                $wccvf_rules = get_post_meta($wccvf->ID, $_type .'_condition_rules', true);
     809                if ($wccvf_rules != null) {
     810                    $wccvf_rules = json_decode($wccvf_rules, true);
     811                   
     812                    /* Well this is a two dimentional array */
     813                    foreach ($wccvf_rules as $rules) {
     814                        if (is_array($rules)) {
     815                            foreach ($rules as $rule) {
     816                                if (is_array($rule)) {
     817                                    foreach ($wp_query->posts as $variation) {
     818                                        if (isset($rule["endpoint"]) && absint($rule["endpoint"]) == absint($variation->ID)) {
     819                                            $this->has_variable_tab_fields = true;
     820                                            return true;
     821                                        }
     822                                    }
     823                                }
     824                            }
     825                        }
     826                    }
     827                }
     828            }
     829        }
     830       
     831        return false;
     832       
     833    }
     834   
     835    /**
     836    *
     837    * This function is used to load all wcff fields (actualy post meta) for a single WCFF post<br/>
     838    * Mostly used in editing wccpf fields in admin screen
     839    *
     840    * @param   integer $pid    - WCFF Post Id
     841    * @param  boolean  $sort   - Whether returning fields should be sorted
     842    * @return  array
     843    *
     844    */
     845    public function load_fields($_pid = 0, $_sort = true) {
     846       
     847        $fields = array();
     848        if ($_pid) {
     849            $_pid = absint($_pid);
     850            $meta = get_post_meta($_pid);
     851           
     852            $excluded_keys = $this->prepare_special_keys();
     853            foreach ($meta as $key => $val) {
     854                /* Exclude special purpose custom meta */
     855                if (!in_array($key, $excluded_keys) && (strpos($key, $this->wcff_key_prefix) === 0)) {
     856                    $fields[$key] = json_decode($val[0], true);
     857                }
     858            }
     859           
     860            if ($_sort) {
     861                $this->usort_by_column($fields, "order");
     862            }
     863        }
     864       
     865        return apply_filters( $this->wcff_key_prefix .'fields', $fields, $_pid, $_sort );
     866       
     867    }
     868   
     869    /**
     870    *
     871    * Loads all fields of the given Fields Group Post
     872    *
     873    * @param number $_pid
     874    * @param string $_mkey
     875    * @return mixed
     876    *
     877    */
     878    public function load_field($_pid = 0, $_mkey = "") {
     879        $_pid = absint($_pid);
     880        $post = get_post($_pid);
     881        $field = get_post_meta($_pid, $_mkey, true);
     882        if ($field === "") {
     883            $field = "{}";
     884        }
     885        $field = json_decode($field, true);
     886        return apply_filters( $post->post_type .'_field', $field, $_pid, $_mkey );
     887    }
     888   
     889    /**
     890     *
     891    * Create a Unique ID for the field and store with initial data
     892     *
     893    * @param number $_pid
     894    * @param string $_type
     895    * @return string|boolean
     896    */
     897    public function create_field($_pid, $_type, $_order) {
     898        $_pid = absint($_pid);
     899       
     900        $id = $this->generate_unique_id();
     901        $id = apply_filters("wcff_new_field_id", $id, $_pid, $_type);
     902       
     903        $meta = array (
     904            "id" => $id,
     905            "type" => $_type,
     906            "label" => "",
     907            "order" => $_order,
     908            "status" => true
     909        );
     910        if (add_post_meta($_pid, ($this->wcff_key_prefix . $id), wp_slash(json_encode($meta)))) {
     911            return ($this->wcff_key_prefix . $id);
     912        }
     913        return false;
     914    }
     915   
     916    /**
     917    *
     918    * Save the given field's config meta as the post meta on a given Fields Group Post.
     919    *
     920    * @param number $_pid
     921    * @param object $_payload
     922    * @return number|false
     923    *
     924    */
     925    public function save_field($_pid, $_payload) {
     926        $_pid = absint($_pid);
     927        $_payload= apply_filters( 'wcff_before_save_'. $this->wcff_key_prefix .'field', $_payload, $_pid );
     928        if (!isset($_payload["name"]) || $_payload["name"] == "_" || $_payload["name"] != "") {
     929            $_payload["key"] = $this->wcff_key_prefix . $this->url_slug($_payload["name"], array('delimiter' => '_'));
     930        }
     931        $flg = add_post_meta($_pid,  $_payload["key"], wp_slash(json_encode($_payload))) == false ? false : true;
     932        return $flg;
     933    }
     934   
     935    public function update_field($_pid, $_payload) {
     936        $msg = "";
     937        $res = true;
     938        $_pid = absint($_pid);
     939        if (isset($_payload["key"])) {
     940            delete_post_meta($_pid, $_payload["key"]);
     941            if (add_post_meta($_pid,  $_payload["key"], wp_slash(json_encode($_payload))) == false) {
     942                $res = false;
     943                $msg = __( "Failed to update the custom field", "wc-fields-factory" );
     944            }
     945        }
     946        return array("res" => $res, "msg" => $msg);
     947    }
     948   
     949    public function toggle_field($_pid, $_key, $_status) {
     950        $msg = "";
     951        $res = true;
     952        $meta_val = get_post_meta($_pid, $_key, true);
     953        if ($meta_val && !empty($meta_val)) {
     954            $field = json_decode(wp_unslash($meta_val), true);
     955            if (isset($field["is_enable"])) {
     956                $field["is_enable"] = $_status;
     957                delete_post_meta($_pid, $_key);
     958                if (add_post_meta($_pid, $_key, wp_slash(json_encode($field))) == false) {
     959                    $res = false;
     960                    $msg = __( "Failed to update.!", "wc-fields-factory" );
     961                }
     962            } else {
     963                $res = false;
     964                $msg = __( "Failed to update, Key is missing.!", "wc-fields-factory" );
     965            }
     966        } else {
     967            $res = false;
     968            $msg = __( "Failed to update, Meta is empty.!", "wc-fields-factory" );
     969        }
     970        return array("res" => $res, "msg" => $msg);
     971    }
     972   
     973    public function clone_group($_pid = 0, $_post_type = "") {
     974        global $wpdb;
     975        $_pid = ($_pid == 0) ? (isset($_REQUEST["post"]) ? $_REQUEST["post"] : 0) : 0;
     976        $_post_type = ($_post_type == "") ? (isset($_REQUEST["post_type"]) ? $_REQUEST["post_type"] : "") : "";
     977        if (isset($_pid) && $_pid > 0) {
     978            $post = get_post($_pid);
     979            $new_post_id = wp_insert_post(array(
     980                'comment_status' => $post->comment_status,
     981                'ping_status'    => $post->ping_status,
     982                'post_author'    => $post->post_author,
     983                'post_content'   => $post->post_content,
     984                'post_excerpt'   => $post->post_excerpt,
     985                'post_name'      => $post->post_name,
     986                'post_parent'    => $post->post_parent,
     987                'post_password'  => $post->post_password,
     988                'post_status'    => 'publish',
     989                'post_title'     => "Copy - ". $post->post_title,
     990                'post_type'      => $post->post_type,
     991                'to_ping'        => $post->to_ping,
     992                'menu_order'     => $post->menu_order
     993            ));
     994           
     995            $post_meta_infos = $wpdb->get_results("SELECT meta_key, meta_value FROM $wpdb->postmeta WHERE post_id=$_pid");
     996            if (count($post_meta_infos)!=0) {
     997                $sql_query_sel = array();
     998                $sql_query = "INSERT INTO $wpdb->postmeta (post_id, meta_key, meta_value) ";
     999                foreach ($post_meta_infos as $meta_info) {
     1000                    $meta_key = $meta_info->meta_key;
     1001                    if( $meta_key == '_wp_old_slug' ) continue;
     1002                    $meta_value = addslashes($meta_info->meta_value);
     1003                    $sql_query_sel[]= "SELECT $new_post_id, '$meta_key', '$meta_value'";
     1004                }
     1005                $sql_query.= implode(" UNION ALL ", $sql_query_sel);
     1006                $wpdb->query($sql_query);
     1007            }
     1008        }
     1009        if ($_post_type != "wccvf") {
     1010            wp_redirect( admin_url('edit.php?post_type='. $_post_type));
     1011        } else {
     1012            wp_redirect( admin_url('edit.php?post_type=wccpf&page=variation_fields_config'));
     1013        }
     1014        exit;
     1015    }
     1016   
     1017    public function clone_field($_pid, $_fkey) {
     1018        $_pid = absint($_pid);
     1019        $id = $this->generate_unique_id();
     1020        $id = apply_filters("wcff_new_field_id", $id, $_pid, null);
     1021        $cloned = $this->load_field($_pid, $_fkey);
     1022        if (is_array($cloned)) {
     1023            $cloned["id"] = $id;
     1024            $cloned["label"] = "Copy - ". $cloned["label"];
     1025            if (add_post_meta($_pid, ($this->wcff_key_prefix . $id), wp_slash(json_encode($cloned)))) {
     1026                return ($this->wcff_key_prefix . $id);
     1027            }
     1028        }
     1029        return false;
     1030    }
     1031   
     1032    /**
     1033    *
     1034    * Remove the given field from Fields Group Post
     1035    *
     1036    * @param number $_pid
     1037    * @param string $_mkey
     1038    * @return boolean
     1039    *
     1040    */
     1041    public function remove_field($_pid, $_mkey) {
     1042        if ($_pid) {
     1043            $_pid = absint($_pid);
     1044            $post = get_post($_pid);
     1045            do_action($post->post_type .'_before_remove_field', $_mkey, $_pid);
     1046            /* Update the layout meta */
     1047            $layout = $this->load_layout_meta($_pid);
     1048            if (!empty($layout)) {
     1049                /* Row update */
     1050                foreach ($layout["rows"] as $rIndex => $row) {
     1051                    foreach($row as $fIndex => $fkey) {
     1052                        if ($_mkey == $fkey) {
     1053                            if (count($row) == 1) {
     1054                                /* Could be only one field */
     1055                                unset($layout["rows"][$rIndex]);
     1056                            } else {
     1057                                $current_field_width = floatval($layout["columns"][$_mkey]["width"]);
     1058                                /* Could be first field */
     1059                                if ($fIndex == 0) {
     1060                                    $next_field_width = floatval($layout["columns"][$layout["rows"][$rIndex][$fIndex+1]]["width"]);
     1061                                    $layout["columns"][$layout["rows"][$rIndex][$fIndex+1]]["width"] = ($current_field_width + $next_field_width);
     1062                                } else {
     1063                                    /* Could be last or middle */
     1064                                    $prev_field_width = floatval($layout["columns"][$layout["rows"][$rIndex][$fIndex-1]]["width"]);
     1065                                    $layout["columns"][$layout["rows"][$rIndex][$fIndex-1]]["width"] = ($current_field_width + $prev_field_width);
     1066                                }
     1067                                unset($layout["rows"][$rIndex][$fIndex]);
     1068                            }
     1069                        }
     1070                    }
     1071                }
     1072                /* Column update */
     1073                unset($layout["columns"][$_mkey]);
     1074               
     1075                delete_post_meta($_pid, $this->wcff_key_prefix .'layout_meta');
     1076                add_post_meta($_pid, $this->wcff_key_prefix .'layout_meta', json_encode($layout));
     1077            }
     1078           
     1079            return delete_post_meta($_pid, $_mkey);
     1080        }
     1081       
     1082        return false;
     1083    }
     1084   
     1085    /**
     1086     *
     1087    * @param integer $_pid
     1088    * @param string $_type
     1089    * @param string $_template
     1090    * @param string $_fields_location
     1091     *
     1092    */
     1093    public function load_fields_groups_for_product($_pid, $_type = "wccpf", $_template = "single-product", $_fields_location = "", $_is_variation_template = false) {
     1094        /* Holds custom post meta */
     1095        $meta = array();
     1096        /* Holds the fields list */
     1097        $fields = array();
     1098        /**/
     1099        $groups = array();
     1100        /* Holds the final list of fields */
     1101        $all_fields = array();
     1102        /* Location rules flag */
     1103        $location_passed = false;
     1104        /* Condition rules flag */
     1105        $target_product_passed = false;
     1106        /**/
     1107        $admin_target_location = array();
     1108       
     1109        $_pid = absint($_pid);
     1110        $this->wcff_key_prefix = $_type . "_";
     1111        $wcff_options = wcff()->option->get_options();
     1112       
     1113        /* Reset variable tab field flaq */
     1114        $this->has_variable_tab_fields = false;
     1115       
     1116        /* Special keys that is not part of fields meta */
     1117        $excluded_keys = $this->prepare_special_keys();
     1118       
     1119        /* Fields on archive template Flaq */
     1120        $fields_on_archive = isset($wcff_options["fields_on_archive"]) ? $wcff_options["fields_on_archive"] : "no";
     1121       
     1122        /* Fields location on single product page */
     1123        $global_location_single = isset($wcff_options["field_location"]) ? $wcff_options["field_location"] : "woocommerce_before_add_to_cart_button";
     1124        /* Check user wants custom location */
     1125        if ($global_location_single == "woocommerce_product_custom_location") {
     1126            $global_location_single = isset($wcff_options["custom_product_fields_location"]) ? $wcff_options["custom_product_fields_location"] : "";
     1127        }
     1128       
     1129        /* Fields location for archive product */
     1130        $global_location_archive = isset($wcff_options["field_archive_location"]) ? $wcff_options["field_archive_location"] : "woocommerce_before_shop_loop_item";
     1131        /* Check user wants custom location */
     1132        if ($global_location_archive == "woocommerce_archive_custom_location") {
     1133            $global_location_archive = isset($wcff_options["custom_archive_fields_location"]) ? $wcff_options["custom_archive_fields_location"] : "";
     1134        }
     1135       
     1136        /* Check whether the request for Archive template and fields on archive is enabled */
     1137        if ($_template == "archive-product" && $fields_on_archive == "no") {
     1138            /* No need to go further */
     1139            return apply_filters( 'wcff_fields_for_product', array(), $_pid, $_type, $_template, $_fields_location );
     1140        }
     1141       
     1142        /* Fetch the group posts */
     1143        $group_posts = get_posts(
     1144            array(
     1145                "post_type" => $_type,
     1146                "posts_per_page" => -1,
     1147                "order" => "ASC",
     1148                "post_status" => array('publish')
     1149            )
     1150            );
     1151       
     1152        if (count($group_posts) > 0) {
     1153            /* Loop through all group posts */
     1154            foreach ($group_posts as $g_post) {
     1155               
     1156                $all_fields = array();
     1157                /* Get all custom meta */
     1158                $fields = get_post_meta($g_post->ID);
     1159               
     1160                /* Check whether this group is for Authorized users only */
     1161                $authorized_only = get_post_meta($g_post->ID, $this->wcff_key_prefix."is_this_group_for_authorized_only", true);
     1162                $authorized_only = (!$authorized_only || $authorized_only == "") ? "no" : $authorized_only;
     1163                if ($authorized_only == "yes" && !is_user_logged_in()) {
     1164                    continue;
     1165                }
     1166               
     1167                /* Retrive the group level role assignment */
     1168                $targeted_roles = get_post_meta($g_post->ID, $this->wcff_key_prefix ."wcff_group_preference_target_roles", true);
     1169               
     1170                if ($targeted_roles) {
     1171                    $targeted_roles = json_decode($targeted_roles, true);
     1172                } else {
     1173                    $targeted_roles = array();
     1174                }
     1175               
     1176                /* If it is for authorized only fields, then check for the roles */
     1177                if ($authorized_only == "yes" && !$this->check_for_roles($targeted_roles)) {
     1178                    continue;
     1179                }
     1180               
     1181                if ($_template != "any" && $_template != "variable") {
     1182                    /* Check for single-product location rule */
     1183                    if ($_template == "single-product") {
     1184                        /* Group level Location */
     1185                        $field_group_location_single = get_post_meta($g_post->ID, $this->wcff_key_prefix."field_location_on_product", true);
     1186                        $field_group_location_single = empty($field_group_location_single) ? "use_global_setting" : $field_group_location_single;
     1187                       
     1188                        if ($field_group_location_single == "use_global_setting") {
     1189                            if ($_fields_location == "any" || $global_location_single == $_fields_location) {
     1190                                $location_passed = true;
     1191                            }
     1192                        } else if ($_fields_location == "any" || $field_group_location_single == $_fields_location) {
     1193                            $location_passed = true;
     1194                        } else {
     1195                            /* Ignore */
     1196                        }
     1197                    } else if ($_template == "archive-product") {
     1198                        /* Check for archive-product location rule */
     1199                        $field_group_location_archive = get_post_meta($g_post->ID, $this->wcff_key_prefix."field_location_on_archive", true);
     1200                        $field_group_location_archive = empty( $field_group_location_archive ) ? "none" : $field_group_location_archive;
     1201                       
     1202                        if ($field_group_location_archive == "use_global_setting") {
     1203                            if ($_fields_location == "any" || $global_location_archive == $_fields_location) {
     1204                                $location_passed = true;
     1205                            }
     1206                        } else if ($_fields_location == "any" || $global_location_archive == $_fields_location) {
     1207                            $location_passed = true;
     1208                        } else {
     1209                            /* Ignore */
     1210                        }
     1211                    } else if ($_template == "admin") {
     1212                        $location_passed = true;
     1213                        $field_group_locations_admin = get_post_meta($g_post->ID, $this->wcff_key_prefix."location_rules", true);
     1214                        $field_group_locations_admin = json_decode( $field_group_locations_admin, true );
     1215                        if ($_fields_location != "any") {
     1216                            $location_passed = $this->check_for_location($field_group_locations_admin, $_fields_location);
     1217                        }
     1218                    }
     1219                } else {
     1220                    $location_passed = true;
     1221                }
     1222               
     1223                if ($_type == "wccaf") {
     1224                    $admin_target_location = get_post_meta($g_post->ID, $_type .'_location_rules', true);
     1225                    $admin_target_location = json_decode($admin_target_location, true);
     1226                }
     1227               
     1228                /* Check for 'variation_tab' location, needs to exclude admin fields which has location of variable tab */
     1229                if ($_type == "wccaf" && ($_template == "single-product" || $_template == "archive-product")) {
     1230                    if ($admin_target_location["endpoint"] == "woocommerce_product_after_variable_attributes") {
     1231                        $location_passed = false;
     1232                        $this->has_variable_tab_fields = true;
     1233                    }
     1234                }
     1235               
     1236                /* Needs to includes admin fields which has variable tab as target location */
     1237                if ($_type == "wccaf" && $_is_variation_template) {
     1238                    $location_passed = false;
     1239                    if ($admin_target_location["endpoint"] == "woocommerce_product_after_variable_attributes") {
     1240                        $location_passed = true;
     1241                    }
     1242                }
     1243               
     1244                /* Finally check for the target products */
     1245                $product_map_rules = $this->load_target_products_rules($g_post->ID);
     1246               
     1247                if (is_array($product_map_rules)) {
     1248                    $target_product_passed = true;
     1249                    if ($_pid > 0) {
     1250                        $target_product_passed = $this->check_for_product($_pid, $product_map_rules);
     1251                    }
     1252                } else {
     1253                    $target_product_passed = false;
     1254                }
     1255               
     1256                /* By passing flaq for variation fields (especially from admin fields group - variable tab) */
     1257                if (($target_product_passed || $_is_variation_template) && $location_passed) {
     1258                    /* Well prepare the field list */
     1259                    foreach ($fields as $key => $meta) {
     1260                        /* Exclude special purpose custom meta */
     1261                        if (!in_array($key, $excluded_keys) && (strpos($key, $this->wcff_key_prefix) === 0)) {
     1262                           
     1263                            $field = json_decode($meta[0], true);
     1264                            if (!isset($field["key"])) {
     1265                                continue;
     1266                            }
     1267                           
     1268                            /* If it is admin field and the template is for front end, then check for the "show_on_product_page" flaq */
     1269                            if (($_type == "wccaf" && isset($field["show_on_product_page"])) && ($_template == "single-product" || $_template == "archive-product" || $_template == "variable")) {
     1270                                if ($field["show_on_product_page"] == "no") {
     1271                                    continue;
     1272                                }
     1273                            }
     1274                           
     1275                            /* Check for authorized user only flaq */
     1276                            $authorized_only = isset($field["login_user_field"]) ? $field["login_user_field"] : "no";
     1277                            if ($authorized_only == "yes") {
     1278                                $targeted_roles = isset($field["show_for_roles"]) ? $field["show_for_roles"] : array();
     1279                                /* If it is for authorized only fields, then check for the roles */
     1280                                if (!$this->check_for_roles($targeted_roles)) {
     1281                                    continue;
     1282                                }
     1283                            }
     1284                           
     1285                            if(isset($field["is_enable"])) {
     1286                                if ($field["is_enable"]) {
     1287                                    $all_fields[] = $field;
     1288                                }
     1289                            } else {
     1290                                $all_fields[] = $field;
     1291                            }
     1292                        }
     1293                    }
     1294                   
     1295                    /* Sort the fields */
     1296                    $this->usort_by_column($all_fields, "order");
     1297                   
     1298                    $groups[] = array(
     1299                        "id" => $g_post->ID,
     1300                        "type" => $_type,
     1301                        "fields" => $all_fields,
     1302                        "title" =>  get_the_title($g_post->ID),
     1303                        "layout" => $this->load_layout_meta($g_post->ID),
     1304                        "use_custom_layout" => $this->load_use_custom_layout($g_post->ID),
     1305                        "show_title" => get_post_meta($g_post->ID, ($this->wcff_key_prefix ."show_group_title"), true),
     1306                        "is_clonable" => get_post_meta($g_post->ID, ($this->wcff_key_prefix ."is_this_group_clonable"), true),
     1307                        "label_alignment" => get_post_meta($g_post->ID, ($this->wcff_key_prefix ."fields_label_alignement"), true),
     1308                        "template_single_location" => get_post_meta($g_post->ID, ($this->wcff_key_prefix ."field_location_on_product"), true),
    13091309                        "template_archive_location" => get_post_meta($g_post->ID, ($this->wcff_key_prefix ."field_location_on_archive"), true)
    1310                     );
    1311                 }
    1312                
    1313             }
    1314         }   
    1315         return apply_filters('wcff_fields_for_product', $groups, $_pid, $_type, $_template, $_fields_location);             
    1316     }
    1317    
    1318    
    1319     /**
    1320     *
    1321     * WCFF Product Mapping Rules Engine, This is function used to determine whether or not to include<br/>
    1322     * a particular wccpf group fields to a particular Product
    1323     *
    1324     * @param   integer     $_pid   - Product Id
    1325     * @param   array       $_groups
    1326     * @return  boolean
    1327     *
    1328     */
    1329     public function check_for_product($_pid, $_groups) {
    1330        
    1331         $matches = array();
    1332         $final_matches = array();
    1333 
    1334         $post_type = "";
    1335         $p = get_post($_pid);
    1336         if ($p && $p->post_type) {
    1337             $post_type = $p->post_type;
    1338         }
    1339 
    1340         foreach ($_groups as $rules) {
    1341 
    1342             $ands = array();
    1343             foreach ($rules as $rule) {
    1344                
    1345                 /* Special case scenario only for Product Variations */
    1346                 if (wcff()->request && $rule["context" ] != "product_variation" && wcff()->request["context"] == "wcff_variation_fields") {
    1347                     return false;
    1348                 }
    1349 
    1350                 if ($rule["context"] == "product" && $post_type == "product") {
    1351                     if ($rule["endpoint"] == -1) {
    1352                         $ands[] = ($rule["logic"] == "==");
    1353                     } else {
    1354                         if ($rule["logic"] == "==") {
    1355                             $ands[] = ($_pid == $rule["endpoint"]);
    1356                         } else {
    1357                             $ands[] = ($_pid != $rule["endpoint"]);
    1358                         }
    1359                     }
    1360                 } else if ($rule["context"] == "product_variation" && $post_type == "product_variation") {
    1361                     if ($rule["endpoint"] == -1) {
    1362                         if (get_post_type($_pid) == "product_variation") {
    1363                             $ands[] = ($rule["logic"] == "==");
    1364                         } else {
    1365                             $ands[] = false;
    1366                         }
    1367                     } else {
    1368                         if ($rule["logic"] == "==") {
    1369                             if (get_post_type($_pid) == "product_variation") {
    1370                                 $ands[] = ($_pid == $rule["endpoint"]);
    1371                             } else {
    1372                                 $ands[] = false;
    1373                             }
    1374                         } else {
    1375                             if (get_post_type($_pid) == "product_variation") {
    1376                                 $ands[] = ($_pid != $rule["endpoint"]);
    1377                             } else {
    1378                                 $ands[] = false;
    1379                             }
    1380                         }
    1381                     }
    1382                 } else if ($rule["context"] == "product_cat") {
    1383                     if ($rule["endpoint"] == -1) {
    1384                         $ands[] = ($rule["logic"] == "==");
    1385                     } else {
    1386                         if ($rule["logic"] == "==") {
    1387                             $ands[] = has_term($rule["endpoint"], 'product_cat', $_pid);
    1388                         } else {
    1389                             $ands[] = !has_term($rule["endpoint"], 'product_cat', $_pid);
    1390                         }
    1391                     }
    1392                 } else if ($rule["context"] == "product_tag") {
    1393                     if ($rule["endpoint"] == -1) {
    1394                         $ands[] = ($rule["logic"] == "==");
    1395                     } else {
    1396                         if ($rule["logic"] == "==") {
    1397                             $ands[] = has_term($rule["endpoint"], 'product_tag', $_pid);
    1398                         } else {
    1399                             $ands[] = !has_term($rule["endpoint"], 'product_tag', $_pid);
    1400                         }
    1401                     }
    1402                 } else if ($rule["context"] == "product_type") {
    1403                     if ($rule["endpoint"] == -1) {
    1404                         $ands[] = ($rule["logic"] == "==");
    1405                     } else {
    1406                         $ptype = wp_get_object_terms($_pid, 'product_type');
    1407                         if (!empty($ptype)) {
    1408                             $ands[] = ($ptype[0]->slug == $rule["endpoint"]);
    1409                         }                       
    1410                     }
    1411                 }
    1412 
    1413             }
    1414 
    1415             $matches[] = $ands;
    1416 
    1417         }       
    1418 
    1419         foreach ($matches as $match) {
    1420             if (!empty($match)) {
    1421                 $final_matches[] = !in_array(false, $match);
    1422             }           
    1423         }   
    1424        
    1425         return in_array(true, $final_matches);
    1426 
    1427     }
    1428    
    1429     /**
    1430     *
    1431     * WCFF Location Rules Engine, This is function used to determine where does the  particular wccaf fields group<br/>
    1432     * to be placed. in the product view, product cat view or one of any product data sections ( Tabs )<br/>
    1433     * applicable only for wccaf post_type.
    1434     *
    1435     * @param integer $_pid
    1436     * @param array $_groups
    1437     * @param string $_location
    1438     *
    1439     */
    1440     public function check_for_location($_rule, $_location) {
    1441            
    1442         if ($_rule["context"] == "location_product_data") {
    1443             if ($_rule["endpoint"] == $_location) {
    1444                 return true;
    1445             }
    1446         }
    1447         if ($_rule["context"] == "location_product" && $_location == "admin_head-post.php") {
    1448             return true; 
    1449         }
    1450         if ($_rule["context"] == "location_product_cat" && ($_location == "product_cat_add_form_fields" || $_location == "product_cat_edit_form_fields"))  {
    1451             return true;
    1452         }
    1453                
    1454         return false;
    1455     }
    1456    
    1457     private function check_for_roles($_targeted_roles) {       
    1458        
    1459         global $wp_roles;
    1460        
    1461         $all_roles = array();
    1462         foreach ($wp_roles->roles as $handle => $role) {
    1463             $all_roles[] = $handle;
    1464         }
    1465        
    1466         if (!$_targeted_roles || empty($_targeted_roles)) {
    1467             $_targeted_roles = $all_roles;
    1468         }
    1469        
    1470         $user = wp_get_current_user();     
    1471         $intersect = array_intersect($_targeted_roles, (array) $user->roles);
    1472         return (count($intersect) > 0);
    1473        
    1474     }
    1475    
    1476     /**
    1477     *
    1478     * Order the array for the given property.
    1479     *
    1480     * @param array $_arr
    1481     * @param string $_col
    1482     * @param string $_dir
    1483     *
    1484     */
    1485     public function usort_by_column(&$_arr, $_col, $_dir = SORT_ASC) {
    1486         $sort_col = array();
    1487         foreach ($_arr as $key=> $row) {
    1488             $sort_col[$key] = $row[$_col];
    1489         }
    1490         array_multisort($sort_col, $_dir, $_arr);
    1491     }
    1492 
    1493     /**
    1494      *
    1495     */
    1496     public function migrate_for_version_4xxx() {
    1497        
    1498         /* Check wccpf */       
    1499         $this->migrate_fields("wccpf");     
    1500         /* Check wccaf */
    1501         $this->migrate_fields("wccaf");
    1502         /* Check wccvf */
    1503         $this->migrate_fields("wccvf");
    1504         /* Check wcccf */
    1505         //$this->migrate_fields("wcccf");
    1506 
    1507         wcff()->option->update_option("version", wcff()->info["version"]);
    1508         wcff()->option->update_option("enable_custom_pricing", "yes");
    1509 
    1510     }
    1511 
    1512     private function migrate_fields($_ptype = "") {
    1513        
    1514         $this->wcff_key_prefix = $_ptype . "_";
    1515         /* Special keys that is not part of fields meta */
    1516         $excluded_keys = $this->prepare_special_keys();
    1517 
    1518         /* Fetch the group posts */
    1519         $group_posts = get_posts(
    1520             array(
    1521                 "post_type" => $_ptype,
    1522                 "posts_per_page" => -1,
    1523                 "order" => "ASC"               
    1524             )
    1525         );     
    1526                
    1527         if (count($group_posts) > 0) {
    1528             /* Loop through all group posts */
    1529             foreach ($group_posts as $g_post) {
    1530                     
    1531                 /* Get all custom meta */
    1532                 $fields = get_post_meta($g_post->ID);
    1533 
    1534                 foreach ($fields as $fkey => $meta) {   
    1535                     /* Exclude special purpose custom meta */
    1536                     if (!in_array($fkey, $excluded_keys) && (strpos($fkey, $this->wcff_key_prefix) === 0)) {
    1537                        
    1538                         $field = json_decode($meta[0], true);
    1539 
    1540                         /* Check is_enabled property */
    1541                         if (!isset($field["is_enable"]) || !$field["is_enable"]) {                     
    1542                             $field["is_enable"] = true;
    1543                         }
    1544                         /* Check key property */
    1545                         if (!isset($field["key"]) && isset($field["name"])) {
    1546                             $field["key"] = $field["name"];
    1547                         }
    1548 
    1549                         if ($field["type"] == "checkbox" && isset($field["pricing_rules"]) && is_array($field["pricing_rules"])) { 
    1550                             foreach ($field["pricing_rules"] as $pkey => $rule) {
    1551                                 $field["pricing_rules"][$pkey]["old_logic"] = $field["pricing_rules"][$pkey]["logic"];
    1552                                 $field["pricing_rules"][$pkey]["logic"] = "has-options";
    1553                             }
    1554                         }
    1555                         if ($field["type"] == "checkbox" && isset($field["fee_rules"]) && is_array($field["fee_rules"])) {         
    1556                             foreach ($field["fee_rules"] as $pkey => $rule) {
    1557                                 $field["fee_rules"][$pkey]["old_logic"] = $field["fee_rules"][$pkey]["logic"];
    1558                                 $field["fee_rules"][$pkey]["logic"] = "has-options";
    1559                             }
    1560                         }
    1561                         if ($field["type"] == "checkbox" && isset($field["field_rules"]) && is_array($field["field_rules"])) {
    1562                             foreach ($field["field_rules"] as $pkey => $rule) {
    1563                                 $field["field_rules"][$pkey]["old_logic"] = $field["field_rules"][$pkey]["logic"];
    1564                                 $field["field_rules"][$pkey]["logic"] = "has-options";
    1565                             }
    1566                         }
    1567 
    1568                         if (isset($field["field_rules"]) && is_array($field["field_rules"])) {
    1569                             foreach ($field["field_rules"] as $pkey => $rule) {
    1570                                 if (isset($rule["field_rules"])) {
    1571                                     foreach ($rule["field_rules"] as $frkey => $fval) {
    1572 
    1573                                         $fname = $frkey;
    1574                                         /* Prior to V4 check box key has suffix of [] - so we need to remove this */
    1575                                         if ($this->endsWith($frkey, "[]")) {
    1576                                             $fname = substr($frkey, 0, strlen($frkey) - 2);
    1577                                         }                               
    1578                                        
    1579                                         $field["field_rules"][$pkey]["field_rules"][ $this->wcff_key_prefix . $fname ] = $fval;
    1580                                         unset($field["field_rules"][$pkey]["field_rules"][$frkey]);
    1581 
    1582                                     }
    1583                                 }
    1584                             }
    1585                         }
    1586                
    1587                         update_post_meta($g_post->ID, $fkey, wp_slash(json_encode($field)));                       
    1588                        
    1589                     }
    1590                 }
    1591 
    1592                 /* Update the admin location rules for wccaf */
    1593                 if ($_ptype == "wccaf" && isset($fields["wccaf_location_rules"])) {
    1594 
    1595                     $lrules = json_decode($fields["wccaf_location_rules"][0], true);
    1596                     if (is_array($lrules[0]) && is_array($lrules[0][0])) {
    1597                         update_post_meta($g_post->ID, "wccaf_location_rules", wp_slash(json_encode($lrules[0][0])));
    1598                     }                   
    1599 
    1600                 }
    1601 
    1602             }
    1603         }
    1604 
    1605     }
    1606    
    1607     private function get_fields_count($_pid) {
    1608         $count =0;
    1609         $keys = get_post_custom_keys($_pid);       
    1610         if ($keys) {
    1611             foreach ($keys as $key) {
    1612                 if ((strpos($key, 'wccpf_') !== false ||
    1613                 strpos($key, 'wccaf_') !== false ||
    1614                 strpos($key, 'wccvf_') !== false) &&
    1615                 (strpos($key, 'group_rules') === false &&
    1616                         strpos($key, 'condition_rules') === false &&
    1617                         strpos($key, 'fee_rules') === false &&
    1618                         strpos($key, 'field_rules') === false &&
    1619                         strpos($key, 'location_rules') === false &&
    1620                         strpos($key, 'product_tab_title') === false &&
    1621                         strpos($key, 'product_tab_priority') === false &&
    1622                         strpos($key, 'field_location_on_product') === false &&
    1623                         strpos($key, 'field_location_on_archive') === false &&
    1624                         strpos($key, 'is_this_group_clonable') === false)) {
    1625                             $count++;
    1626                         }
    1627             }
    1628         }
    1629         return $count;
    1630     }
    1631 
    1632     function endsWith($haystack, $needle) {
    1633         return substr_compare($haystack, $needle, -strlen($needle)) === 0;
    1634     }
    1635    
    1636     /**
    1637      *
    1638     * @return string
    1639     */
    1640     private function generate_unique_id() {
    1641         $token = '';
    1642         $token_length = 12;
    1643         $alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    1644         $alphabet .= "abcdefghijklmnopqrstuvwxyz";
    1645         $alphabet .= "0123456789";
    1646         $alphabetLength = strlen($alphabet);       
    1647         for ($i = 0; $i < $token_length; $i++) {
    1648             $randomKey = $this->get_random_number(0, $alphabetLength);
    1649             $token .= $alphabet[$randomKey];
    1650         }
    1651         return $token;
    1652     }
    1653    
    1654     /**
    1655      *
    1656     * @param number $_min
    1657     * @param number $_max
    1658     * @return number
    1659     */
    1660     private function get_random_number($_min = 0, $_max = 0) {
    1661         $range = ($_max - $_min);
    1662         if ($range < 0) {
    1663             return $_min;
    1664         }
    1665         $log = log($range, 2);
    1666         $bytes = (int) ($log / 8) + 1;
    1667         $bits = (int) $log + 1;
    1668         $filter = (int) (1 << $bits) - 1;
    1669         do {
    1670             $rnd = hexdec(bin2hex(openssl_random_pseudo_bytes($bytes)));
    1671             $rnd = $rnd & $filter;
    1672         } while ($rnd >= $range);
    1673         return ($_min + $rnd);
    1674     }
    1675    
    1676     private function prepare_special_keys() {
    1677         $excluded_keys = array();
    1678         if ($this->wcff_key_prefix != "") {
    1679             foreach ($this->special_keys as $key) {
    1680                 $excluded_keys[] = $this->wcff_key_prefix . $key;
    1681             }
    1682         }
    1683         return $excluded_keys;
    1684     }
    1685    
    1686     /**
    1687     *
    1688     * Create a web friendly URL slug from a string.
    1689     *
    1690     * @author Sean Murphy <sean@iamseanmurphy.com>
    1691     * @copyright Copyright 2012 Sean Murphy. All rights reserved.
    1692     * @license http://creativecommons.org/publicdomain/zero/1.0/
    1693     *
    1694     * @param string $str
    1695     * @param array $options
    1696     * @return string
    1697     *
    1698     */
    1699     function url_slug($_str, $_options = array()) {     
    1700         // Make sure string is in UTF-8 and strip invalid UTF-8 characters
    1701         $_str = mb_convert_encoding((string) $_str, 'UTF-8', mb_list_encodings());
    1702        
    1703         $defaults = array (
    1704             'delimiter' => '-',
    1705             'limit' => null,
    1706             'lowercase' => true,
    1707             'replacements' => array(),
    1708             'transliterate' => false,
    1709         );
    1710        
    1711         // Merge options
    1712         $_options = array_merge($defaults, $_options);
    1713        
    1714         $char_map = array (
    1715             // Latin
    1716             'À' => 'A', '�' => 'A', 'Â' => 'A', 'Ã' => 'A', 'Ä' => 'A', 'Ã…' => 'A', 'Æ' => 'AE', 'Ç' => 'C',
    1717             'È' => 'E', 'É' => 'E', 'Ê' => 'E', 'Ë' => 'E', 'ÃŒ' => 'I', '�' => 'I', 'ÃŽ' => 'I', '�' => 'I',
    1718             '�' => 'D', 'Ñ' => 'N', 'Ã’' => 'O', 'Ó' => 'O', '�' => 'O', 'Õ' => 'O', 'Ö' => 'O', '�' => 'O',
    1719             'Ø' => 'O', 'Ù' => 'U', 'Ú' => 'U', 'Û' => 'U', 'Ü' => 'U', 'Ű' => 'U', '�' => 'Y', 'Þ' => 'TH',
    1720             'ß' => 'ss',
    1721             'à' => 'a', 'á' => 'a', 'â' => 'a', 'ã' => 'a', 'ä' => 'a', 'Ã¥' => 'a', 'æ' => 'ae', 'ç' => 'c',
    1722             'è' => 'e', 'é' => 'e', 'ê' => 'e', 'ë' => 'e', 'ì' => 'i', 'í' => 'i', 'î' => 'i', 'ï' => 'i',
    1723             'ð' => 'd', 'ñ' => 'n', 'ò' => 'o', 'ó' => 'o', 'ô' => 'o', 'õ' => 'o', 'ö' => 'o', 'Å‘' => 'o',
    1724             'ø' => 'o', 'ù' => 'u', 'ú' => 'u', 'û' => 'u', 'ü' => 'u', 'ű' => 'u', 'ý' => 'y', 'þ' => 'th',
    1725             'ÿ' => 'y',
    1726             // Latin symbols
    1727             '©' => '(c)',
    1728             // Greek
    1729             'Α' => 'A', 'Î’' => 'B', 'Γ' => 'G', '�' => 'D', 'Ε' => 'E', 'Ζ' => 'Z', 'ÃŽâ€â€�' => 'H', 'ÃŽËœ' => '8',
    1730             'ÃŽâ„¢' => 'I', 'ÃŽÅ¡' => 'K', 'Λ' => 'L', 'ÃŽÅ“' => 'M', '�' => 'N', 'Ξ' => '3', 'Ο' => 'O', 'Π' => 'P',
    1731             'Ρ' => 'R', 'Σ' => 'S', 'Τ' => 'T', 'ÃŽÂ¥' => 'Y', 'Φ' => 'F', 'Χ' => 'X', 'Ψ' => 'PS', 'Ω' => 'W',
    1732             'Ά' => 'A', 'Έ' => 'E', 'ÃŽÅ ' => 'I', 'ÃŽÅ’' => 'O', 'ÎŽ' => 'Y', 'Ή' => 'H', '�' => 'W', 'Ϊ' => 'I',
    1733             'Ϋ' => 'Y',
    1734             'α' => 'a', 'β' => 'b', 'γ' => 'g', 'δ' => 'd', 'ε' => 'e', 'ζ' => 'z', 'η' => 'h', 'θ' => '8',
    1735             'ι' => 'i', 'κ' => 'k', 'λ' => 'l', 'μ' => 'm', 'ν' => 'n', 'ξ' => '3', 'ο' => 'o', '�€' => 'p',
    1736             '��' => 'r', '�ƒ' => 's', '�„' => 't', '�…' => 'y', '�†' => 'f', '�‡' => 'x', '�ˆ' => 'ps', '�‰' => 'w',
    1737             'ά' => 'a', 'έ' => 'e', 'ί' => 'i', '�Œ' => 'o', '��' => 'y', 'ή' => 'h', '�Ž' => 'w', '�‚' => 's',
    1738             '�Š' => 'i', 'ΰ' => 'y', '�‹' => 'y', '�' => 'i',
    1739             // Turkish
    1740             'Åž' => 'S', 'İ' => 'I', 'Ç' => 'C', 'Ü' => 'U', 'Ö' => 'O', 'Äž' => 'G',
    1741             'ÅŸ' => 's', 'ı' => 'i', 'ç' => 'c', 'ü' => 'u', 'ö' => 'o', 'ÄŸ' => 'g',
    1742             // Russian
    1743             '��' => 'A', '�‘' => 'B', '�’' => 'V', '�“' => 'G', '��' => 'D', '�•' => 'E', '��' => 'Yo', '�–' => 'Zh',
    1744             'Ã�â€â€�' => 'Z', '�˜' => 'I', '�™' => 'J', '�š' => 'K', '�›' => 'L', '�œ' => 'M', '��' => 'N', '�ž' => 'O',
    1745             '�Ÿ' => 'P', '� ' => 'R', '�¡' => 'S', '�¢' => 'T', '�£' => 'U', '�¤' => 'F', '�¥' => 'H', '�¦' => 'C',
    1746             '�§' => 'Ch', '�¨' => 'Sh', '�©' => 'Sh', '�ª' => '', '�«' => 'Y', '�¬' => '', '�­' => 'E', '�®' => 'Yu',
    1747             '�¯' => 'Ya',
    1748             '�°' => 'a', '�±' => 'b', '�²' => 'v', '�³' => 'g', '�´' => 'd', '�µ' => 'e', 'Ñ‘' => 'yo', '�¶' => 'zh',
    1749             '�·' => 'z', '�¸' => 'i', '�¹' => 'j', '�º' => 'k', '�»' => 'l', '�¼' => 'm', '�½' => 'n', '�¾' => 'o',
    1750             '�¿' => 'p', 'Ñ€' => 'r', '�' => 's', 'Ñ‚' => 't', 'у' => 'u', 'Ñ„' => 'f', 'Ñ…' => 'h', 'ц' => 'c',
    1751             'ч' => 'ch', 'ш' => 'sh', 'щ' => 'sh', 'ÑŠ' => '', 'Ñ‹' => 'y', 'ÑŒ' => '', '�' => 'e', 'ÑŽ' => 'yu',
    1752             '�' => 'ya',
    1753             // Ukrainian
    1754             '�„' => 'Ye', '�†' => 'I', '�‡' => 'Yi', 'Ò�' => 'G',
    1755             '�' => 'ye', 'Ñ–' => 'i', 'Ñâ€â€�' => 'yi', 'Ò‘' => 'g',
    1756             // Czech
    1757             'ÄŒ' => 'C', 'ÄŽ' => 'D', 'Äš' => 'E', 'Ň' => 'N', 'Ã…Ëœ' => 'R', 'Å ' => 'S', 'Ť' => 'T', 'Å®' => 'U',
    1758             'Ž' => 'Z',
    1759             '�' => 'c', '�' => 'd', 'Ä›' => 'e', 'ň' => 'n', 'Ã…â„¢' => 'r', 'Å¡' => 's', 'Ã…Â¥' => 't', 'ů' => 'u',
    1760             'ž' => 'z',
    1761             // Polish
    1762             'Ä„' => 'A', 'Ć' => 'C', 'Ę' => 'e', '�' => 'L', 'Ã…Æ’' => 'N', 'Ó' => 'o', 'Ã…Å¡' => 'S', 'Ź' => 'Z',
    1763             'Å»' => 'Z',
    1764             'Ä…' => 'a', 'ć' => 'c', 'Ä™' => 'e', 'Å‚' => 'l', 'Å„' => 'n', 'ó' => 'o', 'Å›' => 's', 'ź' => 'z',
    1765             'ż' => 'z',
    1766             // Latvian
    1767             'Ä€' => 'A', 'ÄŒ' => 'C', 'Ä’' => 'E', 'Ä¢' => 'G', 'Ī' => 'i', 'Ķ' => 'k', 'Ä»' => 'L', 'Å…' => 'N',
    1768             'Å ' => 'S', 'Ū' => 'u', 'Ž' => 'Z',
    1769             '�' => 'a', '�' => 'c', 'Ä“' => 'e', 'Ä£' => 'g', 'Ä«' => 'i', 'Ä·' => 'k', 'ļ' => 'l', 'ņ' => 'n',
    1770             'Å¡' => 's', 'Å«' => 'u', 'ž' => 'z'
    1771         );
    1772        
    1773         // Make custom replacements
    1774         $_str = preg_replace(array_keys($_options['replacements']), $_options['replacements'], $_str);
    1775        
    1776         // Transliterate characters to ASCII
    1777         if ($_options['transliterate']) {
    1778             $_str = str_replace(array_keys($char_map), $char_map, $_str);
    1779         }
    1780        
    1781         // Replace non-alphanumeric characters with our delimiter
    1782         $_str = preg_replace('/[^\p{L}\p{Nd}]+/u', $_options['delimiter'], $_str);
    1783        
    1784         // Remove duplicate delimiters
    1785         $_str = preg_replace('/('. preg_quote($_options['delimiter'], '/') .'){2,}/', '$1', $_str);
    1786        
    1787         // Truncate slug to max. characters
    1788         $_str= mb_substr($_str, 0, ($_options['limit'] ? $_options['limit'] : mb_strlen($_str, 'UTF-8')), 'UTF-8');
    1789        
    1790         // Remove delimiter from ends
    1791         $_str = trim($_str, $_options['delimiter']);
    1792        
    1793         return $_options['lowercase'] ? mb_strtolower($_str, 'UTF-8') : $_str;     
    1794     }
    1795 
     1310                    );
     1311                }
     1312               
     1313            }
     1314        }
     1315        return apply_filters('wcff_fields_for_product', $groups, $_pid, $_type, $_template, $_fields_location);
     1316    }
     1317   
     1318   
     1319    /**
     1320    *
     1321    * WCFF Product Mapping Rules Engine, This is function used to determine whether or not to include<br/>
     1322    * a particular wccpf group fields to a particular Product
     1323    *
     1324    * @param   integer     $_pid   - Product Id
     1325    * @param   array       $_groups
     1326    * @return  boolean
     1327    *
     1328    */
     1329    public function check_for_product($_pid, $_groups) {
     1330       
     1331        $matches = array();
     1332        $final_matches = array();
     1333       
     1334        $post_type = "";
     1335        $p = get_post($_pid);
     1336        if ($p && $p->post_type) {
     1337            $post_type = $p->post_type;
     1338        }
     1339       
     1340        foreach ($_groups as $rules) {
     1341           
     1342            $ands = array();
     1343            foreach ($rules as $rule) {
     1344               
     1345                /* Special case scenario only for Product Variations */
     1346                if (wcff()->request && $rule["context" ] != "product_variation" && wcff()->request["context"] == "wcff_variation_fields") {
     1347                    return false;
     1348                }
     1349               
     1350                if ($rule["context"] == "product" && $post_type == "product") {
     1351                    if ($rule["endpoint"] == -1) {
     1352                        $ands[] = ($rule["logic"] == "==");
     1353                    } else {
     1354                        if ($rule["logic"] == "==") {
     1355                            $ands[] = ($_pid == $rule["endpoint"]);
     1356                        } else {
     1357                            $ands[] = ($_pid != $rule["endpoint"]);
     1358                        }
     1359                    }
     1360                } else if ($rule["context"] == "product_variation" && $post_type == "product_variation") {
     1361                    if ($rule["endpoint"] == -1) {
     1362                        if (get_post_type($_pid) == "product_variation") {
     1363                            $ands[] = ($rule["logic"] == "==");
     1364                        } else {
     1365                            $ands[] = false;
     1366                        }
     1367                    } else {
     1368                        if ($rule["logic"] == "==") {
     1369                            if (get_post_type($_pid) == "product_variation") {
     1370                                $ands[] = ($_pid == $rule["endpoint"]);
     1371                            } else {
     1372                                $ands[] = false;
     1373                            }
     1374                        } else {
     1375                            if (get_post_type($_pid) == "product_variation") {
     1376                                $ands[] = ($_pid != $rule["endpoint"]);
     1377                            } else {
     1378                                $ands[] = false;
     1379                            }
     1380                        }
     1381                    }
     1382                } else if ($rule["context"] == "product_cat") {
     1383                    if ($rule["endpoint"] == -1) {
     1384                        $ands[] = ($rule["logic"] == "==");
     1385                    } else {
     1386                        if ($rule["logic"] == "==") {
     1387                            $ands[] = has_term($rule["endpoint"], 'product_cat', $_pid);
     1388                        } else {
     1389                            $ands[] = !has_term($rule["endpoint"], 'product_cat', $_pid);
     1390                        }
     1391                    }
     1392                } else if ($rule["context"] == "product_tag") {
     1393                    if ($rule["endpoint"] == -1) {
     1394                        $ands[] = ($rule["logic"] == "==");
     1395                    } else {
     1396                        if ($rule["logic"] == "==") {
     1397                            $ands[] = has_term($rule["endpoint"], 'product_tag', $_pid);
     1398                        } else {
     1399                            $ands[] = !has_term($rule["endpoint"], 'product_tag', $_pid);
     1400                        }
     1401                    }
     1402                } else if ($rule["context"] == "product_type") {
     1403                    if ($rule["endpoint"] == -1) {
     1404                        $ands[] = ($rule["logic"] == "==");
     1405                    } else {
     1406                        $ptype = wp_get_object_terms($_pid, 'product_type');
     1407                        if (!empty($ptype)) {
     1408                            $ands[] = ($ptype[0]->slug == $rule["endpoint"]);
     1409                        }
     1410                    }
     1411                }
     1412               
     1413            }
     1414           
     1415            $matches[] = $ands;
     1416           
     1417        }
     1418       
     1419        foreach ($matches as $match) {
     1420            if (!empty($match)) {
     1421                $final_matches[] = !in_array(false, $match);
     1422            }
     1423        }
     1424       
     1425        return in_array(true, $final_matches);
     1426       
     1427    }
     1428   
     1429    /**
     1430    *
     1431    * WCFF Location Rules Engine, This is function used to determine where does the  particular wccaf fields group<br/>
     1432    * to be placed. in the product view, product cat view or one of any product data sections ( Tabs )<br/>
     1433    * applicable only for wccaf post_type.
     1434    *
     1435    * @param integer $_pid
     1436    * @param array $_groups
     1437    * @param string $_location
     1438    *
     1439    */
     1440    public function check_for_location($_rule, $_location) {
     1441       
     1442        if ($_rule["context"] == "location_product_data") {
     1443            if ($_rule["endpoint"] == $_location) {
     1444                return true;
     1445            }
     1446        }
     1447        if ($_rule["context"] == "location_product" && $_location == "admin_head-post.php") {
     1448            return true;
     1449        }
     1450        if ($_rule["context"] == "location_product_cat" && ($_location == "product_cat_add_form_fields" || $_location == "product_cat_edit_form_fields"))  {
     1451            return true;
     1452        }
     1453       
     1454        return false;
     1455    }
     1456   
     1457    private function check_for_roles($_targeted_roles) {
     1458       
     1459        global $wp_roles;
     1460       
     1461        $all_roles = array();
     1462        foreach ($wp_roles->roles as $handle => $role) {
     1463            $all_roles[] = $handle;
     1464        }
     1465       
     1466        if (!$_targeted_roles || empty($_targeted_roles)) {
     1467            $_targeted_roles = $all_roles;
     1468        }
     1469       
     1470        $user = wp_get_current_user();
     1471        $intersect = array_intersect($_targeted_roles, (array) $user->roles);
     1472        return (count($intersect) > 0);
     1473       
     1474    }
     1475   
     1476    /**
     1477    *
     1478    * Order the array for the given property.
     1479    *
     1480    * @param array $_arr
     1481    * @param string $_col
     1482    * @param string $_dir
     1483    *
     1484    */
     1485    public function usort_by_column(&$_arr, $_col, $_dir = SORT_ASC) {
     1486        $sort_col = array();
     1487        foreach ($_arr as $key=> $row) {
     1488            $sort_col[$key] = $row[$_col];
     1489        }
     1490        array_multisort($sort_col, $_dir, $_arr);
     1491    }
     1492   
     1493    /**
     1494     *
     1495    */
     1496    public function migrate_for_version_4xxx() {
     1497       
     1498        /* Check wccpf */
     1499        $this->migrate_fields("wccpf");
     1500        /* Check wccaf */
     1501        $this->migrate_fields("wccaf");
     1502        /* Check wccvf */
     1503        $this->migrate_fields("wccvf");
     1504        /* Check wcccf */
     1505        //$this->migrate_fields("wcccf");
     1506       
     1507        wcff()->option->update_option("version", wcff()->info["version"]);
     1508        wcff()->option->update_option("enable_custom_pricing", "yes");
     1509       
     1510    }
     1511   
     1512    private function migrate_fields($_ptype = "") {
     1513       
     1514        $this->wcff_key_prefix = $_ptype . "_";
     1515        /* Special keys that is not part of fields meta */
     1516        $excluded_keys = $this->prepare_special_keys();
     1517       
     1518        /* Fetch the group posts */
     1519        $group_posts = get_posts(
     1520            array(
     1521                "post_type" => $_ptype,
     1522                "posts_per_page" => -1,
     1523                "order" => "ASC"
     1524            )
     1525            );
     1526       
     1527        if (count($group_posts) > 0) {
     1528            /* Loop through all group posts */
     1529            foreach ($group_posts as $g_post) {
     1530               
     1531                /* Get all custom meta */
     1532                $fields = get_post_meta($g_post->ID);
     1533               
     1534                foreach ($fields as $fkey => $meta) {
     1535                    /* Exclude special purpose custom meta */
     1536                    if (!in_array($fkey, $excluded_keys) && (strpos($fkey, $this->wcff_key_prefix) === 0)) {
     1537                       
     1538                        $field = json_decode($meta[0], true);
     1539                       
     1540                        /* Check is_enabled property */
     1541                        if (!isset($field["is_enable"]) || !$field["is_enable"]) {
     1542                            $field["is_enable"] = true;
     1543                        }
     1544                        /* Check key property */
     1545                        if (!isset($field["key"]) && isset($field["name"])) {
     1546                            $field["key"] = $field["name"];
     1547                        }
     1548                       
     1549                        if ($field["type"] == "checkbox" && isset($field["pricing_rules"]) && is_array($field["pricing_rules"])) {
     1550                            foreach ($field["pricing_rules"] as $pkey => $rule) {
     1551                                $field["pricing_rules"][$pkey]["old_logic"] = $field["pricing_rules"][$pkey]["logic"];
     1552                                $field["pricing_rules"][$pkey]["logic"] = "has-options";
     1553                            }
     1554                        }
     1555                        if ($field["type"] == "checkbox" && isset($field["fee_rules"]) && is_array($field["fee_rules"])) {
     1556                            foreach ($field["fee_rules"] as $pkey => $rule) {
     1557                                $field["fee_rules"][$pkey]["old_logic"] = $field["fee_rules"][$pkey]["logic"];
     1558                                $field["fee_rules"][$pkey]["logic"] = "has-options";
     1559                            }
     1560                        }
     1561                        if ($field["type"] == "checkbox" && isset($field["field_rules"]) && is_array($field["field_rules"])) {
     1562                            foreach ($field["field_rules"] as $pkey => $rule) {
     1563                                $field["field_rules"][$pkey]["old_logic"] = $field["field_rules"][$pkey]["logic"];
     1564                                $field["field_rules"][$pkey]["logic"] = "has-options";
     1565                            }
     1566                        }
     1567                       
     1568                        if (isset($field["field_rules"]) && is_array($field["field_rules"])) {
     1569                            foreach ($field["field_rules"] as $pkey => $rule) {
     1570                                if (isset($rule["field_rules"])) {
     1571                                    foreach ($rule["field_rules"] as $frkey => $fval) {
     1572                                       
     1573                                        $fname = $frkey;
     1574                                        /* Prior to V4 check box key has suffix of [] - so we need to remove this */
     1575                                        if ($this->endsWith($frkey, "[]")) {
     1576                                            $fname = substr($frkey, 0, strlen($frkey) - 2);
     1577                                        }
     1578                                       
     1579                                        $field["field_rules"][$pkey]["field_rules"][ $this->wcff_key_prefix . $fname ] = $fval;
     1580                                        unset($field["field_rules"][$pkey]["field_rules"][$frkey]);
     1581                                       
     1582                                    }
     1583                                }
     1584                            }
     1585                        }
     1586                       
     1587                        update_post_meta($g_post->ID, $fkey, wp_slash(json_encode($field)));
     1588                       
     1589                    }
     1590                }
     1591               
     1592                /* Update the admin location rules for wccaf */
     1593                if ($_ptype == "wccaf" && isset($fields["wccaf_location_rules"])) {
     1594                   
     1595                    $lrules = json_decode($fields["wccaf_location_rules"][0], true);
     1596                    if (is_array($lrules[0]) && is_array($lrules[0][0])) {
     1597                        update_post_meta($g_post->ID, "wccaf_location_rules", wp_slash(json_encode($lrules[0][0])));
     1598                    }
     1599                   
     1600                }
     1601               
     1602            }
     1603        }
     1604       
     1605    }
     1606   
     1607    private function get_fields_count($_pid) {
     1608        $count =0;
     1609        $keys = get_post_custom_keys($_pid);
     1610        if ($keys) {
     1611            foreach ($keys as $key) {
     1612                if ((strpos($key, 'wccpf_') !== false ||
     1613                    strpos($key, 'wccaf_') !== false ||
     1614                    strpos($key, 'wccvf_') !== false) &&
     1615                    (strpos($key, 'group_rules') === false &&
     1616                        strpos($key, 'condition_rules') === false &&
     1617                        strpos($key, 'fee_rules') === false &&
     1618                        strpos($key, 'field_rules') === false &&
     1619                        strpos($key, 'location_rules') === false &&
     1620                        strpos($key, 'product_tab_title') === false &&
     1621                        strpos($key, 'product_tab_priority') === false &&
     1622                        strpos($key, 'field_location_on_product') === false &&
     1623                        strpos($key, 'field_location_on_archive') === false &&
     1624                        strpos($key, 'is_this_group_clonable') === false)) {
     1625                            $count++;
     1626                        }
     1627            }
     1628        }
     1629        return $count;
     1630    }
     1631   
     1632    function endsWith($haystack, $needle) {
     1633        return substr_compare($haystack, $needle, -strlen($needle)) === 0;
     1634    }
     1635   
     1636    /**
     1637     *
     1638    * @return string
     1639    */
     1640    private function generate_unique_id() {
     1641        $token = '';
     1642        $token_length = 12;
     1643        $alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
     1644        $alphabet .= "abcdefghijklmnopqrstuvwxyz";
     1645        $alphabet .= "0123456789";
     1646        $alphabetLength = strlen($alphabet);
     1647        for ($i = 0; $i < $token_length; $i++) {
     1648            $randomKey = $this->get_random_number(0, $alphabetLength);
     1649            $token .= $alphabet[$randomKey];
     1650        }
     1651        return $token;
     1652    }
     1653   
     1654    /**
     1655     *
     1656    * @param number $_min
     1657    * @param number $_max
     1658    * @return number
     1659    */
     1660    private function get_random_number($_min = 0, $_max = 0) {
     1661        $range = ($_max - $_min);
     1662        if ($range < 0) {
     1663            return $_min;
     1664        }
     1665        $log = log($range, 2);
     1666        $bytes = (int) ($log / 8) + 1;
     1667        $bits = (int) $log + 1;
     1668        $filter = (int) (1 << $bits) - 1;
     1669        do {
     1670            $rnd = hexdec(bin2hex(openssl_random_pseudo_bytes($bytes)));
     1671            $rnd = $rnd & $filter;
     1672        } while ($rnd >= $range);
     1673        return ($_min + $rnd);
     1674    }
     1675   
     1676    private function prepare_special_keys() {
     1677        $excluded_keys = array();
     1678        if ($this->wcff_key_prefix != "") {
     1679            foreach ($this->special_keys as $key) {
     1680                $excluded_keys[] = $this->wcff_key_prefix . $key;
     1681            }
     1682        }
     1683        return $excluded_keys;
     1684    }
     1685   
     1686    /**
     1687    *
     1688    * Create a web friendly URL slug from a string.
     1689    *
     1690    * @author Sean Murphy <sean@iamseanmurphy.com>
     1691    * @copyright Copyright 2012 Sean Murphy. All rights reserved.
     1692    * @license http://creativecommons.org/publicdomain/zero/1.0/
     1693    *
     1694    * @param string $str
     1695    * @param array $options
     1696    * @return string
     1697    *
     1698    */
     1699    function url_slug($_str, $_options = array()) {
     1700        // Make sure string is in UTF-8 and strip invalid UTF-8 characters
     1701        $_str = mb_convert_encoding((string) $_str, 'UTF-8', mb_list_encodings());
     1702       
     1703        $defaults = array (
     1704            'delimiter' => '-',
     1705            'limit' => null,
     1706            'lowercase' => true,
     1707            'replacements' => array(),
     1708            'transliterate' => false,
     1709        );
     1710       
     1711        // Merge options
     1712        $_options = array_merge($defaults, $_options);
     1713       
     1714        $char_map = array (
     1715            // Latin
     1716            'À' => 'A', '�' => 'A', 'Â' => 'A', 'Ã' => 'A', 'Ä' => 'A', 'Ã…' => 'A', 'Æ' => 'AE', 'Ç' => 'C',
     1717            'È' => 'E', 'É' => 'E', 'Ê' => 'E', 'Ë' => 'E', 'ÃŒ' => 'I', '�' => 'I', 'ÃŽ' => 'I', '�' => 'I',
     1718            '�' => 'D', 'Ñ' => 'N', 'Ã’' => 'O', 'Ó' => 'O', '�' => 'O', 'Õ' => 'O', 'Ö' => 'O', '�' => 'O',
     1719            'Ø' => 'O', 'Ù' => 'U', 'Ú' => 'U', 'Û' => 'U', 'Ü' => 'U', 'Ű' => 'U', '�' => 'Y', 'Þ' => 'TH',
     1720            'ß' => 'ss',
     1721            'à' => 'a', 'á' => 'a', 'â' => 'a', 'ã' => 'a', 'ä' => 'a', 'Ã¥' => 'a', 'æ' => 'ae', 'ç' => 'c',
     1722            'è' => 'e', 'é' => 'e', 'ê' => 'e', 'ë' => 'e', 'ì' => 'i', 'í' => 'i', 'î' => 'i', 'ï' => 'i',
     1723            'ð' => 'd', 'ñ' => 'n', 'ò' => 'o', 'ó' => 'o', 'ô' => 'o', 'õ' => 'o', 'ö' => 'o', 'Å‘' => 'o',
     1724            'ø' => 'o', 'ù' => 'u', 'ú' => 'u', 'û' => 'u', 'ü' => 'u', 'ű' => 'u', 'ý' => 'y', 'þ' => 'th',
     1725            'ÿ' => 'y',
     1726            // Latin symbols
     1727            '©' => '(c)',
     1728            // Greek
     1729            'Α' => 'A', 'Î’' => 'B', 'Γ' => 'G', '�' => 'D', 'Ε' => 'E', 'Ζ' => 'Z', 'ÃŽâ€â€�' => 'H', 'ÃŽËœ' => '8',
     1730            'ÃŽâ„¢' => 'I', 'ÃŽÅ¡' => 'K', 'Λ' => 'L', 'ÃŽÅ“' => 'M', '�' => 'N', 'Ξ' => '3', 'Ο' => 'O', 'Π' => 'P',
     1731            'Ρ' => 'R', 'Σ' => 'S', 'Τ' => 'T', 'ÃŽÂ¥' => 'Y', 'Φ' => 'F', 'Χ' => 'X', 'Ψ' => 'PS', 'Ω' => 'W',
     1732            'Ά' => 'A', 'Έ' => 'E', 'ÃŽÅ ' => 'I', 'ÃŽÅ’' => 'O', 'ÎŽ' => 'Y', 'Ή' => 'H', '�' => 'W', 'Ϊ' => 'I',
     1733            'Ϋ' => 'Y',
     1734            'α' => 'a', 'β' => 'b', 'γ' => 'g', 'δ' => 'd', 'ε' => 'e', 'ζ' => 'z', 'η' => 'h', 'θ' => '8',
     1735            'ι' => 'i', 'κ' => 'k', 'λ' => 'l', 'μ' => 'm', 'ν' => 'n', 'ξ' => '3', 'ο' => 'o', '�€' => 'p',
     1736            '��' => 'r', '�ƒ' => 's', '�„' => 't', '�…' => 'y', '�†' => 'f', '�‡' => 'x', '�ˆ' => 'ps', '�‰' => 'w',
     1737            'ά' => 'a', 'έ' => 'e', 'ί' => 'i', '�Œ' => 'o', '��' => 'y', 'ή' => 'h', '�Ž' => 'w', '�‚' => 's',
     1738            '�Š' => 'i', 'ΰ' => 'y', '�‹' => 'y', '�' => 'i',
     1739            // Turkish
     1740            'Åž' => 'S', 'İ' => 'I', 'Ç' => 'C', 'Ü' => 'U', 'Ö' => 'O', 'Äž' => 'G',
     1741            'ÅŸ' => 's', 'ı' => 'i', 'ç' => 'c', 'ü' => 'u', 'ö' => 'o', 'ÄŸ' => 'g',
     1742            // Russian
     1743            '��' => 'A', '�‘' => 'B', '�’' => 'V', '�“' => 'G', '��' => 'D', '�•' => 'E', '��' => 'Yo', '�–' => 'Zh',
     1744            'Ã�â€â€�' => 'Z', '�˜' => 'I', '�™' => 'J', '�š' => 'K', '�›' => 'L', '�œ' => 'M', '��' => 'N', '�ž' => 'O',
     1745            '�Ÿ' => 'P', '� ' => 'R', '�¡' => 'S', '�¢' => 'T', '�£' => 'U', '�¤' => 'F', '�¥' => 'H', '�¦' => 'C',
     1746            '�§' => 'Ch', '�¨' => 'Sh', '�©' => 'Sh', '�ª' => '', '�«' => 'Y', '�¬' => '', '�­' => 'E', '�®' => 'Yu',
     1747            '�¯' => 'Ya',
     1748            '�°' => 'a', '�±' => 'b', '�²' => 'v', '�³' => 'g', '�´' => 'd', '�µ' => 'e', 'Ñ‘' => 'yo', '�¶' => 'zh',
     1749            '�·' => 'z', '�¸' => 'i', '�¹' => 'j', '�º' => 'k', '�»' => 'l', '�¼' => 'm', '�½' => 'n', '�¾' => 'o',
     1750            '�¿' => 'p', 'Ñ€' => 'r', '�' => 's', 'Ñ‚' => 't', 'у' => 'u', 'Ñ„' => 'f', 'Ñ…' => 'h', 'ц' => 'c',
     1751            'ч' => 'ch', 'ш' => 'sh', 'щ' => 'sh', 'ÑŠ' => '', 'Ñ‹' => 'y', 'ÑŒ' => '', '�' => 'e', 'ÑŽ' => 'yu',
     1752            '�' => 'ya',
     1753            // Ukrainian
     1754            '�„' => 'Ye', '�†' => 'I', '�‡' => 'Yi', 'Ò�' => 'G',
     1755            '�' => 'ye', 'Ñ–' => 'i', 'Ñâ€â€�' => 'yi', 'Ò‘' => 'g',
     1756            // Czech
     1757            'ÄŒ' => 'C', 'ÄŽ' => 'D', 'Äš' => 'E', 'Ň' => 'N', 'Ã…Ëœ' => 'R', 'Å ' => 'S', 'Ť' => 'T', 'Å®' => 'U',
     1758            'Ž' => 'Z',
     1759            '�' => 'c', '�' => 'd', 'Ä›' => 'e', 'ň' => 'n', 'Ã…â„¢' => 'r', 'Å¡' => 's', 'Ã…Â¥' => 't', 'ů' => 'u',
     1760            'ž' => 'z',
     1761            // Polish
     1762            'Ä„' => 'A', 'Ć' => 'C', 'Ę' => 'e', '�' => 'L', 'Ã…Æ’' => 'N', 'Ó' => 'o', 'Ã…Å¡' => 'S', 'Ź' => 'Z',
     1763            'Å»' => 'Z',
     1764            'Ä…' => 'a', 'ć' => 'c', 'Ä™' => 'e', 'Å‚' => 'l', 'Å„' => 'n', 'ó' => 'o', 'Å›' => 's', 'ź' => 'z',
     1765            'ż' => 'z',
     1766            // Latvian
     1767            'Ä€' => 'A', 'ÄŒ' => 'C', 'Ä’' => 'E', 'Ä¢' => 'G', 'Ī' => 'i', 'Ķ' => 'k', 'Ä»' => 'L', 'Å…' => 'N',
     1768            'Å ' => 'S', 'Ū' => 'u', 'Ž' => 'Z',
     1769            '�' => 'a', '�' => 'c', 'Ä“' => 'e', 'Ä£' => 'g', 'Ä«' => 'i', 'Ä·' => 'k', 'ļ' => 'l', 'ņ' => 'n',
     1770            'Å¡' => 's', 'Å«' => 'u', 'ž' => 'z'
     1771        );
     1772       
     1773        // Make custom replacements
     1774        $_str = preg_replace(array_keys($_options['replacements']), $_options['replacements'], $_str);
     1775       
     1776        // Transliterate characters to ASCII
     1777        if ($_options['transliterate']) {
     1778            $_str = str_replace(array_keys($char_map), $char_map, $_str);
     1779        }
     1780       
     1781        // Replace non-alphanumeric characters with our delimiter
     1782        $_str = preg_replace('/[^\p{L}\p{Nd}]+/u', $_options['delimiter'], $_str);
     1783       
     1784        // Remove duplicate delimiters
     1785        $_str = preg_replace('/('. preg_quote($_options['delimiter'], '/') .'){2,}/', '$1', $_str);
     1786       
     1787        // Truncate slug to max. characters
     1788        $_str= mb_substr($_str, 0, ($_options['limit'] ? $_options['limit'] : mb_strlen($_str, 'UTF-8')), 'UTF-8');
     1789       
     1790        // Remove delimiter from ends
     1791        $_str = trim($_str, $_options['delimiter']);
     1792       
     1793        return $_options['lowercase'] ? mb_strtolower($_str, 'UTF-8') : $_str;
     1794    }
     1795   
    17961796}
    17971797
  • wc-fields-factory/trunk/includes/wcff_dao.php

    r2739039 r2739048  
    899899
    900900        $id = $this->generate_unique_id();
    901         $id = apply_filters("wcff_new_field_id", $id);
     901        $id = apply_filters("wcff_new_field_id", $id, $_pid, $_type);
    902902
    903903        $meta = array (
     
    10181018        $_pid = absint($_pid);
    10191019        $id = $this->generate_unique_id();
    1020         $id = apply_filters("wcff_new_field_id", $id);
     1020        $id = apply_filters("wcff_new_field_id", $id, $_pid, null);
    10211021        $cloned = $this->load_field($_pid, $_fkey);     
    10221022        if (is_array($cloned)) {
Note: See TracChangeset for help on using the changeset viewer.