plugin_name = $plugin_name; $this->version = $version; $this->textdomain = 'atr-woo-global-price-options'; } /* * Loads both the general and advanced settings from * the database into their respective arrays. Uses * array_merge to merge with default values if they're * missing. */ /** * Initialise settings * @return void */ public function init() { $this->settings = $this->settings_fields(); $this->options = $this->get_options(); $this->register_settings(); } /** * Add settings page to admin menu * @return void */ public function add_menu_item() { //$page = add_options_page( $this->plugin_name, $this->plugin_name, 'manage_options' , $this->plugin_name, array( $this, 'settings_page' ) ); $page = add_submenu_page( 'woocommerce', // The slug for this menu parent item __( 'ATR Woo Global Price Options', $this->textdomain ), // The title to be displayed in the browser window for this page. __( 'ATR Woo GPO', $this->textdomain ),// The text to be displayed for this menu item 'manage_options', // Which type of users can see this menu item $this->plugin_name,// The unique ID - that is, the slug - for this menu item array( $this, 'settings_page'));// The name of the function to call when rendering this menu's page } /** * Add settings link to plugin list table * @param array $links Existing links * @return array Modified links */ public function add_action_links( $links ) { $links[] = '' . __('Settings', $this->textdomain) . ''; $links[] = 'More plugins by Yehuda Tiram'; return $links; } /** * Build settings fields * @return array Fields to be displayed on settings page */ private function settings_fields() { $post_ttls_count = 0; $options = get_option($this->plugin_name); if ($this->check_isset_post('p_0_ttl_1')){ foreach($_POST as $key => $val){ if (strpos($key, 'p_0_ttl_') === 0) { $post_ttls_count = $post_ttls_count++; } } } else{ if ( $options ) { if ( is_array( $options ) ){ foreach($options as $key => $val){ if (strpos($key, 'p_0_ttl_') === 0) { $post_ttls_count = $post_ttls_count + 2; } } } } else{ $post_ttls_count = 2; } } $populate_main_fields = array (); $list_control = []; $list_control['id'] = 'list_control'; $list_control['label'] = __('Price list display', $this->textdomain); $list_control['description'] = __('Select price list display format, select box or radio buttons', $this->textdomain); $list_control['type'] = 'select'; $list_control['options'] = array( 'ddl' => __('Dropdown list', $this->textdomain), 'radio' => __('Radio buttons list', $this->textdomain) ); $list_control['default'] = 'radio'; $list_control['gpo_type'] = 'gpo_list_control'; $populate_main_fields[] = $list_control; for ($x = 1; $x <= ($post_ttls_count); $x += 2) { $p_0_ttl_id = 'p_0_ttl_' . ( ( $x + 1 ) / 2 ); $p_0_price_id = 'p_0_price_' . ( ( $x + 1 ) / 2 ); $ttl_index = ( $x + 1 ) / 2; $temp_field = []; $temp_field['id'] = $p_0_ttl_id; $temp_field['label'] = __('Option title ', $this->textdomain) . '' . ( $ttl_index ) . ''; $temp_field['description'] = __('Do not use semi collon ";".', $this->textdomain); $temp_field['type'] = 'text'; $temp_field['default'] = ''; $temp_field['placeholder'] = ''; $temp_field['gpo_type'] = 'gpo_option_ttl'; $populate_main_fields[] = $temp_field; $temp_field['id'] = $p_0_price_id; $temp_field['label'] = __('Option price', $this->textdomain) . ' ' . ( $ttl_index ) . ' (' . get_woocommerce_currency_symbol() . ')'; $temp_field['description'] = __('Decimals or integers. e.g. xx or xx.xx', $this->textdomain); $temp_field['type'] = 'text'; $temp_field['default'] = ''; $temp_field['placeholder'] = ''; $temp_field['gpo_type'] = 'gpo_option_price'; $populate_main_fields[] = $temp_field; } $settings['main'] = array( 'title' => __( 'Manage your price list', $this->textdomain ), 'description' => __( 'Please add option title and price in the textboxes.', $this->textdomain ), 'fields' => $populate_main_fields ); $settings['extra'] = array( 'title' => __( 'Other options', $this->textdomain ), 'description' => __( 'Select options.', $this->textdomain ), 'fields' => array( array( 'id' => 'before_price_options', 'label' => __( 'Header text for price options list', $this->textdomain ), 'description' => __( 'Write the text to display before the price options list. Leave empty for none', $this->textdomain ), 'type' => 'text', 'default' => __('Please select an option to purchase this product.', $this->textdomain), 'placeholder' => __('List header text', $this->textdomain), ), array( 'id' => 'after_price_options', 'label' => __( 'Footer text for price options list', $this->textdomain ), 'description' => __( 'Write the text to display after the price options list. Leave empty for none', $this->textdomain ), 'type' => 'text', 'default' => __('You can select more than one option to purchase the product. Just add it again with another option.', $this->textdomain), 'placeholder' => __('List footer text', $this->textdomain), ), array( 'id' => 'add_to_cart_btn_txt', 'label' => __( 'Text on "View details" product button', $this->textdomain ), 'description' => __( 'Write the text to display on shop and archives "View details" button for the products.', $this->textdomain ), 'type' => 'text', 'default' => __('Select options', $this->textdomain), 'placeholder' => __('"View details" text', $this->textdomain), ), array( 'id' => 'cart_item_option_label', 'label' => __( 'Text label for selected option in the cart.', $this->textdomain ), 'description' => __( 'Write the text to display on the label for the selected option in the cart ( This text is displayed after the customer adds to cart.).', $this->textdomain ), 'type' => 'text', 'default' => __('Select option', $this->textdomain), 'placeholder' => __('label for selected option in the cart', $this->textdomain), ), array( 'id' => 'make_product_empty_price_purchasable', 'label' => __( 'Make products with empty price purchasable', $this->textdomain ), 'description' => __( 'Force products with no price to be purchasable. If you select this you can save yourself the work of setting price to each product affected by the plugin. (You set the options price by the plugin.)', $this->textdomain ), 'type' => 'checkbox', 'default' => 'on' ), array( 'id' => 'categories_checkboxes', 'label' => __( 'Select categories', $this->textdomain ), 'description' => __( 'Select multiple product categories to apply the price options.', $this->textdomain ), 'type' => 'categories_checkbox_multi_select', 'options' => array( $this->get_product_categories()), 'default' => array( ) ), ) ); $settings = apply_filters( 'plugin_settings_fields', $settings ); return $settings; } public function get_product_categories(){ if ( $this->check_wp_version( '4.5.0' ) ){ $terms = get_terms( 'product_cat', array( 'hide_empty' => false, ) ); } else{ $terms = get_terms( array( 'taxonomy' => 'product_cat', 'hide_empty' => false, 'orderby' => 'term_group', ) ); } return $terms; } public function check_wp_version( $ver_num ){ $wp_version = get_bloginfo('version'); if ($wp_version < $ver_num) { return true; } else { return false; } } /** * Options getter * @return array Options, either saved or default ones. */ public function get_options() { $options = get_option($this->plugin_name); if ( !$options && is_array( $this->settings ) ) { $options = Array(); foreach( $this->settings as $section => $data ) { foreach( $data['fields'] as $field ) { $options[ $field['id'] ] = $field['default']; } } add_option( $this->plugin_name, $options ); } return $options; } /** * Register plugin settings * @return void */ public function register_settings() { if( is_array( $this->settings ) ) { register_setting( $this->plugin_name, $this->plugin_name, array( $this, 'validate_fields' ) ); foreach( $this->settings as $section => $data ) { // Add section to page add_settings_section( $section, $data['title'], array( $this, 'settings_section' ), $this->plugin_name ); foreach( $data['fields'] as $field ) { // Add field to page add_settings_field( $field['id'], $field['label'], array( $this, 'display_field' ), $this->plugin_name, $section, array( 'field' => $field ) ); } } } } public function settings_section( $section ) { $html = '

' . $this->settings[ $section['id'] ]['description'] . '

' . "\n"; echo $html; } /** * Generate HTML for displaying fields * @param array $args Field data * @return void */ public function display_field( $args ) { $field = $args['field']; $html = ''; $option_name = $this->plugin_name ."[". $field['id']. "]"; $data = (isset($this->options[$field['id']])) ? $this->options[$field['id']] : ''; switch( $field['type'] ) { case 'text': if ( array_key_exists ( 'gpo_type' , $field ) ){ if ( $field['gpo_type'] == 'gpo_option_ttl'){ $html .= '
'; } elseif( $field['gpo_type'] == 'gpo_option_price'){ $remove_option = 'Remove this option'; $html .= '
' . $remove_option . '
'; } else { $html .= '' . "\n"; } } else { $html .= '' . "\n"; } break; case 'password': case 'number': $html .= '' . "\n"; break; case 'text_secret': $html .= '' . "\n"; break; case 'textarea': $html .= '
'. "\n"; break; case 'checkbox': $checked = ''; if( $data && 'on' == $data ){ $checked = 'checked="checked"'; } $html .= '' . "\n"; break; case 'categories_checkbox_multi_select': foreach( $field['options'] as $k => $v ) { $html .= 'Expand allClose all'; $html .= ''; } break; case 'checkbox_multi': foreach( $field['options'] as $k => $v ) { $checked = false; if( is_array($data) && in_array( $k, $data ) ) { $checked = true; } $html .= ' '; } break; case 'radio': foreach( $field['options'] as $k => $v ) { $checked = false; if( $k == $data ) { $checked = true; } $html .= ' '; } break; case 'select': if ( array_key_exists ( 'gpo_type' , $field ) ){ if ( $field['gpo_type'] == 'gpo_list_control'){ $html .= '
'; $html .= ' '; $html .= '
'; } } else{ $html .= ' '; } break; case 'select_multi': $html .= ' '; break; } switch( $field['type'] ) { case 'checkbox_multi': case 'radio': case 'select_multi': $html .= '
' . $field['description'] . ''; break; default: $html .= '' . "\n"; break; } echo $html; } /** * Validate individual settings field * @param string $data Inputted value * @return string Validated value */ function validate_fields( $data ) { if ( $data['add_to_cart_btn_txt'] != '' ) { $data['add_to_cart_btn_txt'] = sanitize_text_field($data['add_to_cart_btn_txt']); } if ( $data['before_price_options'] != '' ) { $data['before_price_options'] = sanitize_text_field($data['before_price_options']); } if ( $data['after_price_options'] != '' ) { $data['after_price_options'] = sanitize_text_field($data['after_price_options']); } if ( $data['list_control'] != '' ) { $valid_values = array( 'radio', 'ddl' ); $value = sanitize_text_field( $data['list_control'] ); if( in_array( $value, $valid_values ) ) { $data['list_control'] = $value; } else{ add_settings_error( $this->plugin_name, esc_attr( 'Price_list_display_error' ) , __('Price list display format selection is not valid! Default radio button is used', $this->textdomain), 'error' ); $data['list_control'] = 'radio'; } } //Sanitize and validate the price options rows foreach($_POST as $key => $val){ if( $key === 'atr-woo-global-price-options' ){ foreach( $val as $key1 => $val1){ $original_val = $data[$key1]; // Field value before sanitization $ttl_row = strpos($key1, 'p_0_ttl_'); // The option title $price_row = strpos($key1, 'p_0_price_'); // The option price if ( $ttl_row === 0 ){ // We check p_0_ttl_X $key1_index = str_replace('p_0_ttl_', '', $key1); $data[$key1] = sanitize_text_field($data[$key1]); $data[$key1] = str_replace( ';', ',', $data[$key1]); // We use ; as a delimiter in \public\class-atr-woo-global-price-options-public.phpadd_cart_item_data() if ( $data[$key1] == '' ){ add_settings_error( $this->plugin_name, esc_attr( 'title_not_entered' ) , __('No title was entered in field ' . $key1_index . '! Price in that row was also removed. (Faulty content might be removed by the plugin.)', $this->textdomain), 'error' ); $data[$key1] = ''; $price_key1 = str_replace('p_0_ttl_', 'p_0_price_', $key1); $data[$price_key1] = ''; unset($data[$key1]); unset($data[$price_key1]); //return false; } } elseif( $price_row === 0 ){ // We check p_0_price_X $key1_index = str_replace('p_0_price_', '', $key1); $data[$key1] = sanitize_text_field($data[$key1]); if ( $data[$key1] == '' ){ add_settings_error( $this->plugin_name, esc_attr( 'price_not_entered' ), __('No price was entered in field ' . $key1_index . '!. Title in that row was also removed. (Faulty content might be removed by the plugin.)', $this->textdomain), 'error' ); $data[$key1] = ''; $ttl_key1 = str_replace('p_0_price_', 'p_0_ttl_', $key1); $data[$ttl_key1] = ''; unset($data[$key1]); unset($data[$ttl_key1]); } else{ $data[$key1] = filter_var($data[$key1],FILTER_SANITIZE_NUMBER_FLOAT,FILTER_FLAG_ALLOW_FRACTION); $data[$key1] = wc_format_decimal( $data[$key1], '', false ); if ( $original_val != $data[$key1] ) add_settings_error( $this->plugin_name, esc_attr( 'price_changed' ) , __('The price you entered in field ' . $key1_index . ' was changed on saving. Please review again. (Faulty content might be removed by the plugin.)', $this->textdomain), 'error' ); } } } } } return $data; } public function display_gpo_settings_notices() { settings_errors( $this->plugin_name ); } /** * Load settings page content * @return void */ public function settings_page() { // Build page HTML output // If you don't need tabbed navigation just strip out everything between the tags. ?>

textdomain); ?>

textdomain); ?>

do_script_for_tabbed_nav(); ?>
plugin_name ); ?>
plugin_name ); ?>