SettingsPage.php
235 lines
| 1 | <?php |
| 2 | |
| 3 | namespace ProfilePress\Core\Admin\SettingsPages\Membership\TaxSettings; |
| 4 | |
| 5 | use ProfilePress\Core\Admin\SettingsPages\AbstractSettingsPage; |
| 6 | use ProfilePress\Custom_Settings_Page_Api; |
| 7 | |
| 8 | class SettingsPage |
| 9 | { |
| 10 | public function __construct() |
| 11 | { |
| 12 | add_filter('ppress_settings_page_submenus_tabs', [$this, 'header_sub_menu_tab']); |
| 13 | |
| 14 | add_action('ppress_admin_settings_submenu_page_payments_taxes', [$this, 'taxes_page']); |
| 15 | |
| 16 | add_action('ppress_register_menu_page_payments_taxes', function () { |
| 17 | |
| 18 | add_filter('ppress_general_settings_admin_page_title', function () { |
| 19 | return esc_html__('Taxes ‹ Payments', 'wp-user-avatar'); |
| 20 | }); |
| 21 | |
| 22 | add_action('admin_enqueue_scripts', [$this, 'enqueue_script']); |
| 23 | |
| 24 | add_action('admin_footer', [$this, 'js_template']); |
| 25 | }); |
| 26 | } |
| 27 | |
| 28 | public function header_sub_menu_tab($tabs) |
| 29 | { |
| 30 | $tabs[175] = ['parent' => 'payments', 'id' => 'taxes', 'label' => esc_html__('Taxes', 'wp-user-avatar')]; |
| 31 | |
| 32 | return $tabs; |
| 33 | } |
| 34 | |
| 35 | public function tax_rate_setup_ui() |
| 36 | { |
| 37 | ob_start(); |
| 38 | require dirname(dirname(__FILE__)) . '/views/tax-rates-setup.php'; |
| 39 | |
| 40 | return ob_get_clean(); |
| 41 | } |
| 42 | |
| 43 | public function taxes_page() |
| 44 | { |
| 45 | $instance = Custom_Settings_Page_Api::instance(); |
| 46 | $instance->option_name(PPRESS_TAXES_OPTION_NAME); |
| 47 | $instance->page_header(esc_html__('Taxes', 'wp-user-avatar')); |
| 48 | $instance->add_view_classes('ppress-tax-rate-list'); |
| 49 | |
| 50 | add_action('wp_cspa_after_settings_tab', function ($option_name) { |
| 51 | if ($option_name !== PPRESS_TAXES_OPTION_NAME) return; |
| 52 | echo '<div class="notice notice-info">'; |
| 53 | echo '<p>'; |
| 54 | echo sprintf(__('%1$sDisclaimer %2$s- By using this feature, you\'ve agreed that the use of this feature cannot be considered as tax advice. We recommend consulting a local tax professional for tax compliance or if you have any tax specific questions.', 'wp-user-avatar'), '<strong>', '</strong>'); |
| 55 | echo '</p>'; |
| 56 | echo '</div>'; |
| 57 | }); |
| 58 | |
| 59 | $settings = [ |
| 60 | [ |
| 61 | 'enable_tax' => [ |
| 62 | 'label' => esc_html__('Set up Taxes', 'wp-user-avatar'), |
| 63 | 'checkbox_label' => esc_html__('Enable Taxes', 'wp-user-avatar'), |
| 64 | 'description' => esc_html__('With taxes enabled, customers will be taxed based on the rates you define, and are required to input their address on checkout so rates can be calculated accordingly.', 'wp-user-avatar'), |
| 65 | 'type' => 'checkbox' |
| 66 | ], |
| 67 | 'prices_include_tax' => [ |
| 68 | 'label' => esc_html__('Prices Include Tax', 'wp-user-avatar'), |
| 69 | 'type' => 'select', |
| 70 | 'options' => [ |
| 71 | 'no' => esc_html__('No, I will enter prices exclusive of tax', 'wp-user-avatar'), |
| 72 | 'yes' => esc_html__('Yes, I will enter prices inclusive of tax', 'wp-user-avatar'), |
| 73 | ] |
| 74 | ], |
| 75 | 'tax_based_on' => [ |
| 76 | 'label' => esc_html__('Calculate Tax Based On', 'wp-user-avatar'), |
| 77 | 'type' => 'select', |
| 78 | 'options' => [ |
| 79 | 'billing' => esc_html__('Customer Billing Address', 'wp-user-avatar'), |
| 80 | 'base' => esc_html__('Shop Base Address', 'wp-user-avatar'), |
| 81 | ], |
| 82 | 'description' => sprintf( |
| 83 | esc_html__('If "Shop Base Address" is selected, Tax will be calculated based on the location of your %sbusiness in Settings%s.', 'wp-user-avatar'), |
| 84 | '<a target="_blank" href="' . PPRESS_SETTINGS_SETTING_GENERAL_PAGE . '#business_info">', '</a>' |
| 85 | ) |
| 86 | ] |
| 87 | ], |
| 88 | [ |
| 89 | 'section_title' => esc_html__('EU VAT Settings', 'wp-user-avatar'), |
| 90 | 'enable_eu_vat' => [ |
| 91 | 'type' => 'checkbox', |
| 92 | 'label' => esc_html__('Enable EU VAT', 'wp-user-avatar'), |
| 93 | 'description' => esc_html__('When this is checked, VAT taxes will be calculated for any customers who are located in the European Union. The plugin comes with the current standard VAT rate for each EU country. You can change these as required in the Tax Rates section below.', 'wp-user-avatar'), |
| 94 | ], |
| 95 | 'eu_vat_disable_validation' => [ |
| 96 | 'type' => 'checkbox', |
| 97 | 'checkbox_label' => esc_html__('Disable Validation', 'wp-user-avatar'), |
| 98 | 'label' => esc_html__('Disable VAT Number Validation', 'wp-user-avatar'), |
| 99 | 'description' => esc_html__('When this option is checked, the VAT number will not be validated by VIES online service.', 'wp-user-avatar'), |
| 100 | ], |
| 101 | 'eu_vat_same_country_rule' => [ |
| 102 | 'type' => 'select', |
| 103 | 'label' => esc_html__('Same Country Rule', 'wp-user-avatar'), |
| 104 | 'description' => esc_html__('What should happen if a customer is from the same EU country as your business?.', 'wp-user-avatar'), |
| 105 | 'options' => [ |
| 106 | 'no_charge' => esc_html__('Do not charge tax', 'wp-user-avatar'), |
| 107 | 'charge_unvalidated' => esc_html__('Charge tax unless VAT number is validated', 'wp-user-avatar'), |
| 108 | 'charge_always' => esc_html__('Charge tax even if VAT number is validated', 'wp-user-avatar'), |
| 109 | ] |
| 110 | ], |
| 111 | 'eu_vat_number_label' => [ |
| 112 | 'type' => 'text', |
| 113 | 'value' => esc_html__('VAT Number', 'wp-user-avatar'), |
| 114 | 'label' => esc_html__('VAT Number Field Label', 'wp-user-avatar'), |
| 115 | 'description' => esc_html__('The label that appears at checkout for the VAT number field.', 'wp-user-avatar'), |
| 116 | ], |
| 117 | ], |
| 118 | [ |
| 119 | 'section_title' => esc_html__('Tax Rates', 'wp-user-avatar'), |
| 120 | 'tax_rates' => [ |
| 121 | 'label' => esc_html__('Set up Tax Rates', 'wp-user-avatar'), |
| 122 | 'description' => esc_html__('Add rates for each region you wish to collect tax in. Enter a percentage, such as 6.5 for 6.5%.', 'wp-user-avatar'), |
| 123 | 'type' => 'custom_field_block', |
| 124 | 'data' => $this->tax_rate_setup_ui() |
| 125 | ], |
| 126 | 'fallback_tax_rate' => [ |
| 127 | 'label' => esc_html__('Fallback Tax Rate', 'wp-user-avatar'), |
| 128 | 'description' => esc_html__('Customers not in a specific rate will be charged this tax rate. Enter a percentage, such as 6.5 for 6.5%. ', 'wp-user-avatar'), |
| 129 | 'type' => 'text', |
| 130 | ] |
| 131 | ] |
| 132 | ]; |
| 133 | |
| 134 | $instance->main_content($settings); |
| 135 | $instance->remove_white_design(); |
| 136 | AbstractSettingsPage::register_core_settings($instance, true); |
| 137 | $instance->build(true); |
| 138 | } |
| 139 | |
| 140 | public static function tax_rate_row($index = '0', $country = '', $state = '', $global = '', $rate = '') |
| 141 | { |
| 142 | $country_states = ! empty($country) ? ppress_array_of_world_states($country) : []; |
| 143 | ?> |
| 144 | <tr data-row-index="<?= $index ?>"> |
| 145 | <td class="ppress-tax-rate-table-country"> |
| 146 | <select name="ppress_taxes[tax_rates][<?= $index ?>][country]"> |
| 147 | <option value=""><?= esc_html__('Choose a Country', 'wp-user-avatar') ?></option> |
| 148 | <?php foreach (ppress_array_of_world_countries() as $id => $label): ?> |
| 149 | <option value="<?= $id ?>" <?php selected($id, $country) ?>> |
| 150 | <?= $label ?> |
| 151 | </option> |
| 152 | <?php endforeach; ?> |
| 153 | </select> |
| 154 | </td> |
| 155 | <td class="ppress-tax-rate-table-state"> |
| 156 | <?php if ( ! empty($country_states)) : ?> |
| 157 | <select name="ppress_taxes[tax_rates][<?= $index ?>][state]"> |
| 158 | <option value="">———</option> |
| 159 | <?php foreach ($country_states as $key => $value) : ?> |
| 160 | <option value="<?= $key ?>" <?php selected($key, $state) ?>><?= $value ?></option> |
| 161 | <?php endforeach; ?> |
| 162 | </select> |
| 163 | <?php else : ?> |
| 164 | <input type="text" name="ppress_taxes[tax_rates][<?= $index ?>][state]" value="<?= esc_attr($state) ?>"> |
| 165 | <?php endif; ?> |
| 166 | </td> |
| 167 | <td class="ppress-tax-rate-table-country-wide"> |
| 168 | <input type="hidden" name="ppress_taxes[tax_rates][<?= $index ?>][global]" value="0"> |
| 169 | <input type="checkbox" name="ppress_taxes[tax_rates][<?= $index ?>][global]" id="ppress_taxes[tax_rates][<?= $index ?>][global]" value="1" <?php checked($global, '1') ?>> |
| 170 | <label for="ppress_taxes[tax_rates][<?= $index ?>][global]"> |
| 171 | <?= esc_html__('Apply to whole country', 'wp-user-avatar') ?> |
| 172 | </label> |
| 173 | </td> |
| 174 | <td class="ppress-tax-rate-table-rate"> |
| 175 | <input style="width:75px !important" type="number" class="small-text" min="0.0" step="any" name="ppress_taxes[tax_rates][<?= $index ?>][rate]" value="<?= esc_attr($rate) ?>"> |
| 176 | </td> |
| 177 | <td class="ppress-tax-rate-table-actions"> |
| 178 | <span class="ppress-tax-rate-icon"><span class="dashicons dashicons-no-alt"></span></span> |
| 179 | </td> |
| 180 | </tr> |
| 181 | <?php |
| 182 | } |
| 183 | |
| 184 | public function enqueue_script() |
| 185 | { |
| 186 | wp_enqueue_script( |
| 187 | 'ppress-admin-tax-rate', |
| 188 | PPRESS_ASSETS_URL . '/js/admin/tax-rate-repeater.js', |
| 189 | ['jquery', 'wp-util'] |
| 190 | ); |
| 191 | } |
| 192 | |
| 193 | public function js_template() |
| 194 | { |
| 195 | ?> |
| 196 | <script type="text/html" id="tmpl-ppress-tax-rate-row"> |
| 197 | <?php self::tax_rate_row('{{data.index}}'); ?> |
| 198 | </script> |
| 199 | |
| 200 | <script type="text/html" id="tmpl-ppress-tax-rate-empty-row"> |
| 201 | <tr class="ppress-tax-rate-row--is-empty"> |
| 202 | <td colspan="5"><?php esc_html_e('No rates found.', 'wp-user-avatar') ?></td> |
| 203 | </tr> |
| 204 | </script> |
| 205 | |
| 206 | <script type="text/html" id="tmpl-ppress-tax-rate-state-input"> |
| 207 | <input type="text" name="ppress_taxes[tax_rates][{{data.index}}][state]" value=""> |
| 208 | </script> |
| 209 | |
| 210 | <script type="text/html" id="tmpl-ppress-tax-rate-state-select"> |
| 211 | <select type="text" name="ppress_taxes[tax_rates][{{data.index}}][state]"> |
| 212 | <option value="">———</option> |
| 213 | <# jQuery.each(data.options, function(index, value) { #> |
| 214 | <option value="{{index}}">{{value}}</option> |
| 215 | <# }); #> |
| 216 | </select> |
| 217 | </script> |
| 218 | |
| 219 | <script type="text/javascript"> |
| 220 | var ppress_countries_states = <?php echo wp_json_encode(array_filter(ppress_array_of_world_states())); ?>; |
| 221 | </script> |
| 222 | <?php |
| 223 | } |
| 224 | |
| 225 | public static function get_instance() |
| 226 | { |
| 227 | static $instance = null; |
| 228 | |
| 229 | if (is_null($instance)) { |
| 230 | $instance = new self(); |
| 231 | } |
| 232 | |
| 233 | return $instance; |
| 234 | } |
| 235 | } |