Files
formipay/includes/Coupon.php
dwindown d1de0015be feat: add React metabox island for coupon editor
- Create CouponMetabox React component with WPCFTO design system
- Add MetaboxLayout with vertical tabs (Rules, Restrictions)
- Implement Rules tab: active toggle, type radio, amount fields, multi-currency support
- Implement Restrictions tab: usage limit, date limit, autocomplete for forms/products/customers
- Add metabox registration in Coupon.php for formipay-coupon post type
- Update ReactAdmin to load assets on post.php edit screens
- Add autocomplete AJAX handler for relation fields
- Disable old WPCFTO metabox in favor of React island
2026-04-19 07:08:54 +07:00

1101 lines
40 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace Formipay;
use Formipay\Traits\SingletonTrait;
if ( ! defined( 'ABSPATH' ) ) exit;
class Coupon {
use SingletonTrait;
/**
* Initializes the plugin by setting filters and administration functions.
*/
protected function __construct() {
add_action( 'init', [$this, 'cpt'] );
add_action( 'admin_menu', [$this, 'add_submenu'] );
add_action( 'admin_enqueue_scripts', [$this, 'enqueue_admin'] );
add_filter( 'stm_wpcfto_boxes', [$this, 'cpt_post_fields_box'] );
add_filter( 'stm_wpcfto_fields', [$this, 'cpt_post_fields_content'] );
add_filter( 'formipay/coupon-config', [$this, 'rule_config'] );
add_filter( 'formipay/coupon-config', [$this, 'restriction_config'] );
add_filter( 'formipay/admin-editor/layout/static-elements-sort', [$this, 'add_static_element'] );
add_action( 'formipay/render/static-element', [$this, 'render_static_element'] );
add_action( 'wp_ajax_check_coupon_code', [$this, 'check_coupon_code'] );
add_action( 'wp_ajax_nopriv_check_coupon_code', [$this, 'check_coupon_code'] );
// Admin Page
add_action( 'wp_ajax_formipay_coupon_get_products', [$this, 'formipay_coupon_get_products'] );
add_action( 'wp_ajax_formipay-tabledata-coupons', [$this, 'formipay_tabledata_coupons'] );
add_action( 'wp_ajax_formipay-create-coupon-post', [$this, 'formipay_create_coupon_post'] );
add_action( 'wp_ajax_formipay-delete-coupon', [$this, 'formipay_delete_coupon'] );
add_action( 'wp_ajax_formipay-bulk-delete-coupon', [$this, 'formipay_bulk_delete_coupon'] );
add_action( 'wp_ajax_formipay-duplicate-coupon', [$this, 'formipay_duplicate_coupon'] );
add_action( 'wp_ajax_formipay-get-coupon', [$this, 'formipay_get_coupon'] );
add_action( 'wp_ajax_formipay-save-coupon', [$this, 'formipay_save_coupon'] );
add_action( 'wp_ajax_formipay-autocomplete-search', [$this, 'formipay_autocomplete_search'] );
// React Metabox
add_action( 'add_meta_boxes', [$this, 'add_react_metabox'] );
add_action( 'admin_footer-post.php', [$this, 'render_react_metabox_template'] );
// Order
add_filter( 'formipay/order/order-details', [$this, 'order_details'], 99, 3 );
// Paypal
add_filter( 'formipay/order/paypal/payload/breakdown', [$this, 'add_discount_item'], 99, 3 );
}
public function cpt() {
$labels = array(
'name' => __('Coupons', 'formipay'),
'singular_name' => __('Coupon', 'formipay'),
// 'menu_name' => 'Formipay',
'add_new' => __('Add New', 'formipay'),
'add_new_item' => __('Add New Coupon', 'formipay'),
'edit' => __('Edit', 'formipay'),
'edit_item' => __('Edit Coupon', 'formipay'),
'new_item' => __('New Coupon', 'formipay'),
'view' => __('View', 'formipay'),
'view_item' => __('View Coupon', 'formipay'),
'search_items' => __('Search Coupon', 'formipay'),
'not_found' => __('No coupons found', 'formipay'),
'not_found_in_trash' => __('No coupons found in trash', 'formipay'),
'parent' => __('Coupon Parent', 'formipay')
);
$args = array(
'label' => 'Coupons',
'description' => __('Coupon for marketing campaign', 'formipay'),
'labels' => $labels,
'public' => false,
'supports' => array( 'title' ),
'hierarchical' => false,
'has_archive' => false,
'show_ui' => true,
'show_in_menu' => false,
'show_in_rest' => false,
'query_var' => true
);
register_post_type( 'formipay-coupon', $args );
}
public function add_submenu() {
add_submenu_page(
'formipay',
__( 'Coupons', 'formipay' ),
__( 'Coupons', 'formipay' ),
'manage_options',
'formipay-coupons',
[$this, 'formipay_coupon'],
);
}
public function formipay_coupon() {
// React admin
\Formipay\Admin\ReactAdmin::render_mount_point('coupons');
}
public function enqueue_admin() {
$screen = get_current_screen();
// Enqueue SweetAlert2 for coupon post edit screen
if ($screen && $screen->post_type === 'formipay-coupon' && $screen->base === 'post') {
wp_enqueue_style('sweetalert2', FORMIPAY_URL . 'vendor/SweetAlert2/sweetalert2.min.css', [], '11.14.4', 'all');
wp_enqueue_script('sweetalert2', FORMIPAY_URL . 'vendor/SweetAlert2/sweetalert2.min.js', ['jquery'], '11.14.4', true);
// Localize admin data
wp_localize_script('formipay-admin', 'formipayAdmin', [
'ajaxUrl' => admin_url('admin-ajax.php'),
'siteUrl' => site_url(),
'nonce' => wp_create_nonce('formipay-admin'),
]);
}
}
public function cpt_post_fields_box($boxes) {
// Disabled - using React metabox instead
// $boxes['formipay_coupon_settings'] = array(
// 'post_type' => array('formipay-coupon'),
// 'label' => __('Details', 'formipay'),
// );
return $boxes;
}
public function cpt_post_fields_content($fields) {
$fields['formipay_coupon_settings'] = array();
$fields = apply_filters( 'formipay/coupon-config', $fields );
return $fields;
}
public function rule_config($fields) {
$multicurrency = formipay_is_multi_currency_active();
$all_currencies = formipay_currency_as_options();
$global_selected_currencies = formipay_global_currency_options();
$global_currencies = formipay_global_currency_options('raw');
$default_currency = formipay_default_currency();
// Group : Rules
$rules_group_1 = array(
'rules_general_group' => array(
'type' => 'group_title',
'group' => 'started'
),
'active' => array(
'type' => 'checkbox',
'label' => __( 'Active this coupon', 'formipay' ),
'value' => true,
),
'type' => array(
'type' => 'radio',
'label' => __( 'Type', 'formipay' ),
'required' => true,
'options' => array(
'fixed' => __( 'Fixed', 'formipay' ),
'percentage' => __( 'Percentage', 'formipay' )
),
),
'amount_percentage' => array(
'type' => 'number',
'label' => __( 'Amount', 'formipay' ),
'required' => true,
'dependency' => array(
'key' => 'type',
'value' => 'percentage'
),
'group' => 'ended'
)
);
$rules_group_2 = [];
$global_currencies = get_global_currency_array();
$default_currency = formipay_default_currency();
$rules_group_2['discount_amount_wrapper'] = array(
'type' => 'group_title',
'label' => __( 'Discount Amount', 'formipay' ),
'dependency' => array(
'key' => 'type',
'value' => 'fixed'
),
'group' => 'started',
);
$rules_group_max['discount_max_amount_wrapper'] = array(
'type' => 'group_title',
'label' => __( 'Max Discount Amount', 'formipay' ),
'description' => __( 'Leave empty to not limit the max discount amount.', 'formipay' ),
'group' => 'started',
);
foreach($global_currencies as $currency){
$default_currency_symbol = formipay_get_currency_data_by_value($default_currency, 'symbol');
$currency_symbol = formipay_get_currency_data_by_value($currency['currency'], 'symbol');
$currency_title = ucwords(formipay_get_currency_data_by_value($currency['currency'], 'title'));
$decimal_digits = intval($currency['decimal_digits']);
$step = $decimal_digits * 10;
$step = $step > 0 ? 1 / $step : 1;
$rules_group_2['amount_fixed_'.$currency_symbol] = array(
'type' => 'number',
'label' => sprintf(
__( '<img src="%s" width="18" /> Amount in %s', 'formipay' ),
formipay_get_flag_by_currency($currency['currency']),
$currency_symbol
),
'step' => $step,
'min' => 0,
'required' => true,
'placeholder' => __( 'Enter Amount...', 'formipay' ),
'dependency' => array(
'key' => 'type',
'value' => 'fixed'
)
);
$rules_group_max['max_amount_'.$currency_symbol] = array(
'type' => 'number',
'label' => sprintf(
__( '<img src="%s" width="18" /> Max Amount in %s', 'formipay' ),
formipay_get_flag_by_currency($currency['currency']),
$currency_symbol
),
'step' => $step,
'min' => 0,
'placeholder' => __( 'Enter Max Amount...', 'formipay' )
);
}
$last_rules_group_2 = array_key_last($rules_group_2);
$rules_group_2[$last_rules_group_2]['group'] = 'ended';
$last_rules_group_max = array_key_last($rules_group_max);
$rules_group_max[$last_rules_group_max]['group'] = 'ended';
$rules_group_3 = array(
'rules_group' => array(
'type' => 'group_title',
'label' => __( 'Rules', 'formipay' ),
'description' => __( 'Define the rules of this coupon.', 'formipay' ),
'group' => 'started'
),
'case_sensitive' => array(
'type' => 'checkbox',
'label' => __( 'Case Sensitive', 'formipay' ),
'description' => __( 'If this activated, coupon codes must be entered with the exact capitalization as specified. <br>
For example code <B>SAVE10</b>:<br>
- <b>SAVE10</b> is valid<br>
- <b>save10</b> is invalid<br>
- <b>Save10</b> is invalid.', 'formipay' )
),
'free_shipping' => array(
'type' => 'checkbox',
'label' => __( 'Free Shipping', 'formipay' ),
'description' => __( 'Shipping cost will be free when this coupon applied.', 'formipay' )
),
'quantity_active' => array(
'type' => 'checkbox',
'label' => __( 'Influenced by Quantity', 'formipay' ),
'description' => __( 'Example: when buyer buy 4 pcs of item, 4 × discount amount will be implemented.', 'formipay' ),
'dependency' => array(
'key' => 'type',
'value' => 'fixed'
)
),
// 'max_discount' => array(
// 'type' => 'number',
// 'label' => __( 'Max Discount Amount', 'formipay' ),
// 'description' => __( 'Leave it empty to not limit the max discount amount.', 'formipay' )
// ),
);
$rules_group = $rules_group_1 + $rules_group_2 + $rules_group_max + $rules_group_3;
$rules_group = apply_filters( 'formipay/coupon-settings/tab:rules/group:rules', $rules_group );
$last_rules_group = array_key_last($rules_group);
$rules_group[$last_rules_group]['group'] = 'ended';
$all_group_merged = $rules_group;
$settings_all_fields = apply_filters( 'formipay/coupon-settings/tab:rules', $all_group_merged );
$settings_fields = [];
if(!empty($settings_all_fields)){
foreach($settings_all_fields as $key => $value){
$settings_fields[$key] = $value;
}
}
$fields['formipay_coupon_settings']['rules'] = array(
'name' => __('Rules', 'formipay'),
'fields' => $settings_fields
);
return $fields;
}
public function restriction_config($fields) {
// Group : Restrictions
$restriction_group = array(
'restriction_group' => array(
'type' => 'group_title',
'label' => __( 'Restrictions', 'formipay' ),
'group' => 'started'
),
'use_limit' => array(
'type' => 'number',
'label' => __( 'Usage Limit', 'formipay' ),
'description' => __( 'Leave it empty or 0 (zero) to set it as unlimited usage.', 'formipay' )
),
'date_limit' => array(
'type' => 'date',
'label' => __( 'Date Limit', 'formipay' ),
'description' => __( 'Chosen date is the last day the coupon can be used. Leave it empty tio set it as no-limit date.', 'formipay' )
),
'forms' => array(
'type' => 'autocomplete',
'post_type' => array('formipay-form'),
'label' => __( 'Forms', 'formipay' ),
'description' => __( 'Only selected form(s) can use the coupon. Leave empty to apply to all forms.', 'formipay' )
),
'products' => array(
'type' => 'autocomplete',
'post_type' => array('formipay-product'),
'label' => __( 'Products', 'formipay' ),
'description' => __( 'Only selected product(s) can use the coupon. Leave empty to apply to all products.', 'formipay' )
),
'customers' => array(
'type' => 'autocomplete',
'post_type' => array('formipay-product'),
'label' => __( 'Customers', 'formipay' ),
'description' => __( 'Only selected customer(s) can use the coupon. Leave empty to apply to all customers.', 'formipay' )
)
);
$restriction_group = apply_filters( 'formipay/coupon-settings/tab:restriction/group:restrictions', $restriction_group );
$last_restriction_group = array_key_last($restriction_group);
$restriction_group[$last_restriction_group]['group'] = 'ended';
$details_all_fields = apply_filters( 'formipay/coupon-settings/tab:restriction', $restriction_group );
$details_fields = [];
if(!empty($details_all_fields)){
foreach($details_all_fields as $key => $value){
$details_fields[$key] = $value;
}
}
$fields['formipay_coupon_settings']['restriction'] = array(
'name' => __('Restrictions', 'formipay'),
'fields' => $details_fields
);
return $fields;
}
public function add_static_element($elements) {
$elements[] = [
'id' => 'coupon_field',
'label' => __( 'Coupon Field', 'formipay' )
];
return $elements;
}
public function render_static_element($element_id) {
if($element_id == 'coupon_field'){
?>
<div class="formipay-field-group">
<div class="formipay-coupon-field-group">
<input type="text" name="coupon_code"
class="formipay-input formipay-code-input"
value="<?php echo
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
isset($_GET['coupon']) ? esc_attr( sanitize_text_field( wp_unslash($_GET['coupon']) ) ) : ''
?>" placeholder="<?php echo esc_attr__('Your coupon code', 'formipay'); ?>"
data-label="<?php echo esc_attr__('Coupon Code', 'formipay'); ?>">
<button type="button" data-text="<?php echo esc_attr__( 'Apply', 'formipay' ); ?>" data-checking="<?php echo esc_attr__( 'Checking...', 'formipay' ); ?>" id="apply_coupon_code"><?php echo esc_attr__( 'Apply', 'formipay' ); ?></button>
</div>
<div class="formipay-coupon-alert-message"></div>
</div>
<?php
}
}
public function check_coupon_code() {
check_ajax_referer( 'formipay-frontend-nonce', 'security' );
if ( ! current_user_can( 'manage_options' ) ) {
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
}
$code = isset($_REQUEST['code']) ? sanitize_text_field( wp_unslash($_REQUEST['code']) ) : '';
$form_id = isset($_REQUEST['form']) ? intval( $_REQUEST['form'] ) : 0;
$check_code = formipay_get_coupon_id_by_code($code, $form_id);
if(false == $check_code){
wp_send_json_error( [
'message' => __( 'Coupon code is not valid', 'formipay' )
] );
}
wp_send_json_success();
}
public function order_details($details, $form_id, $order_data) {
if( isset($order_data['coupon_code']) && !empty($order_data['coupon_code']) ) {
$coupon_id = formipay_get_coupon_id_by_code( sanitize_text_field( $order_data['coupon_code'] ), $form_id );
if(false !== $coupon_id) {
$amount = floatval( formipay_get_post_meta( $coupon_id, 'amount' ) );
$discount = $amount;
$coupon_type = formipay_get_post_meta( $coupon_id, 'type' );
$qty = 1;
if( formipay_get_post_meta( $form_id, 'product_quantity_toggle' ) == 'on' ){
$qty = intval($order_data['qty']);
}
if( $coupon_type == 'percentage' ){
$product_price = floatval( formipay_get_post_meta( $form_id, 'product_price' ) );
$amount = $amount / 100;
$discount = $product_price * $amount;
}
$amount = $discount * $qty;
$amount = $amount * -1;
$details[] = [
'item' => esc_html( $order_data['coupon_code'] ),
'amount' => floatval($amount),
'subtotal' => floatval($amount),
'context' => 'sub'
];
}
}
return $details;
}
public function count_order_by_coupon_code($coupon_code) {
global $wpdb;
$table = $wpdb->prefix .'formipay_orders';
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$data = $wpdb->get_results(
$wpdb->prepare(
"SELECT COUNT(id) as count FROM %i WHERE `items` LIKE %s", $table, '%' . $wpdb->esc_like($coupon_code) . '%'
)
);
return $data[0]->count;
}
public function add_discount_item($breakdown, $currency, $order_data) {
if( isset($order_data['form_data']['coupon_code']) && !empty($order_data['form_data']['coupon_code']) ) {
$form_id = $order_data['form_id'];
$coupon_id = formipay_get_coupon_id_by_code( sanitize_text_field( $order_data['form_data']['coupon_code'] ), $form_id );
if(false !== $coupon_id) {
$amount = floatval( formipay_get_post_meta( $coupon_id, 'amount' ) );
$discount = $amount;
$coupon_type = formipay_get_post_meta( $coupon_id, 'type' );
$qty = 1;
if( formipay_get_post_meta( $form_id, 'product_quantity_toggle' ) == 'on' ){
$qty = intval($order_data['form_data']['qty']);
}
if( $coupon_type == 'percentage' ){
$product_price = floatval( formipay_get_post_meta( $form_id, 'product_price' ) );
$amount = $amount / 100;
$discount = $product_price * $amount;
}
$breakdown['item_total']['value'] += $discount;
$breakdown['discount'] = array(
"currency_code" => $currency,
"value" => $discount
);
}
}
return $breakdown;
}
public function formipay_tabledata_coupons() {
check_ajax_referer( 'formipay-admin', '_wpnonce' );
if ( ! current_user_can( 'manage_options' ) ) {
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
}
$args = [
'post_type' => 'formipay-coupon',
'posts_per_page' => -1,
'post_status' => array( 'pending', 'draft', 'publish' )
];
$get_total_coupons = get_posts($args);
$coupon_status = [
'all' => 0,
'active' => 0,
'inactive' => 0
];
if(!empty($get_total_coupons)){
foreach($get_total_coupons as $coupon){
$status = (formipay_get_post_meta($coupon->ID, 'active') == 'on') ? 'active' : 'inactive';
$coupon_status['all'] = intval($coupon_status['all']) + 1;
if($status == 'active'){
$coupon_status['active'] = intval($coupon_status['active']) + 1;
}elseif($status == 'inactive'){
$coupon_status['inactive'] = intval($coupon_status['inactive']) + 1;
}
}
}
if(isset($_REQUEST['limit'])){
$args['posts_per_page'] = intval($_REQUEST['limit']);
}
if(isset($_REQUEST['offset'])){
$args['offset'] = intval($_REQUEST['offset']);
}
if(!empty($_REQUEST['search'])){
$args['s'] = sanitize_text_field( wp_unslash($_REQUEST['search']) );
}
// Handle status filtering (active/inactive)
$status_filter = isset($_REQUEST['status']) ? sanitize_text_field($_REQUEST['status']) : 'all';
$get_coupons = get_posts($args);
$global_currencies = get_global_currency_array();
$coupons = [];
if(!empty($get_coupons)){
foreach($get_coupons as $key => $coupon){
$is_active = formipay_get_post_meta($coupon->ID, 'active') == 'on';
// Apply status filter
if ($status_filter !== 'all') {
if ($status_filter === 'active' && !$is_active) continue;
if ($status_filter === 'inactive' && $is_active) continue;
}
$date_limit = formipay_get_post_meta($coupon->ID, 'date_limit');
$type = formipay_get_post_meta($coupon->ID, 'type');
$amount_meta_key = "amount_$type";
if($type == 'fixed'){
$amount_value = [];
foreach($global_currencies as $currency){
$raw = $currency['currency'];
$decimal_digits = $currency['decimal_digits'];
$decimal_symbol = $currency['decimal_symbol'];
$thousand_separator = $currency['thousand_separator'];
$parse_currency = explode(':::', $raw);
$currency_code = $parse_currency[0];
$amount_in_currency = formipay_get_post_meta($coupon->ID, 'amount_fixed_'.$currency_code);
$amount_value[] = [
'raw' => $raw,
'amount' => number_format($amount_in_currency, $decimal_digits, $decimal_symbol, $thousand_separator),
'flag' => formipay_get_flag_by_currency($raw)
];
}
}else{
$amount_value = floatval(formipay_get_post_meta($coupon->ID, $amount_meta_key));
}
$coupons[] = [
'ID' => $coupon->ID,
'code' => get_the_title($coupon->ID),
'amount' => $amount_value,
'type' => ucfirst(formipay_get_post_meta($coupon->ID, 'type')),
'case_sensitive' => formipay_get_post_meta($coupon->ID, 'case_sensitive'),
'usage_count' => $this->count_order_by_coupon_code(get_the_title($coupon->ID)),
'usages' => $this->count_order_by_coupon_code(get_the_title($coupon->ID)),
'date_limit' => false !== $date_limit ? formipay_date('Y-m-d', intval(formipay_get_post_meta($coupon->ID, 'date_limit')) / 1000) : 'none',
'active' => $is_active ? 'on' : 'off',
'post_status' => $is_active ? 'active' : 'inactive',
'status' => $is_active ? 'active' : 'inactive'
];
}
}
$response = [
'results' => $coupons,
'total' => count($get_total_coupons), // Total number of forms
'posts_report' => array_map('intval', (array)$coupon_status)
];
wp_send_json($response);
}
public function formipay_coupon_get_products() {
check_ajax_referer( 'formipay-admin', '_wpnonce' );
if ( ! current_user_can( 'manage_options' ) ) {
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
}
if (!isset($_POST['search']) || empty($_POST['search'])) {
wp_send_json_error( __('No search term provided.', 'formipay') );
}
$search_term = sanitize_text_field( wp_unslash($_POST['search']) );
$query = get_posts([
'post_type' => 'formipay-form',
's' => $search_term,
'posts_per_page' => -1,
]);
$results = [];
if(!empty($query)){
foreach($query as $post){
$results[] = [
'value' => $post->ID,
'label' => $post->post_title,
];
}
}
wp_send_json($results);
}
public function formipay_create_coupon_post() {
check_ajax_referer( 'formipay-admin', '_wpnonce' );
if ( ! current_user_can( 'manage_options' ) ) {
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
}
$code = isset($_REQUEST['title']) ? sanitize_text_field( wp_unslash($_REQUEST['title']) ) : '';
if( !empty($code) && '' !== $code ){
$post_id = wp_insert_post( [
'post_title' => $code,
'post_type' => 'formipay-coupon',
], true );
if(is_wp_error($post_id)){
wp_send_json_error( [
'message' => $post_id->get_error_message()
] );
}
update_post_meta($post_id, 'type', 'percentage');
update_post_meta($post_id, 'amount', 0);
wp_send_json_success( [
'edit_post_url' => admin_url('post.php?post='.$post_id.'&action=edit')
] );
}
wp_send_json_error( [
'message' => esc_html__( 'Coupon code is empty.', 'formipay' )
] );
}
public function formipay_delete_coupon() {
check_ajax_referer( 'formipay-admin', '_wpnonce' );
if ( ! current_user_can( 'manage_options' ) ) {
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
}
$post_id = isset($_REQUEST['id']) ? intval($_REQUEST['id']) : 0;
$delete = wp_delete_post($post_id, true);
if(is_wp_error( $delete )){
wp_send_json_error( [
'title' => esc_html__( 'Failed', 'formipay' ),
'message' => esc_html__( 'Failed to delete coupon. Please try again.', 'formipay' ),
'icon' => 'error'
] );
}
wp_send_json_success( [
'title' => esc_html__( 'Deleted', 'formipay' ),
'message' => esc_html__( 'Coupon is deleted permanently.', 'formipay' ),
'icon' => 'success'
] );
}
public function formipay_bulk_delete_coupon() {
check_ajax_referer( 'formipay-admin', '_wpnonce' );
if ( ! current_user_can( 'manage_options' ) ) {
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
}
if( empty($_REQUEST['ids']) ){
wp_send_json_error( [
'title' => esc_html__( 'Failed', 'formipay' ),
'message' => esc_html__( 'There is no coupon selected. Please try again.', 'formipay' ),
'icon' => 'error'
] );
}
$ids = isset($_REQUEST['ids']) ? $_REQUEST['ids'] : [];
$success = 0;
$failed = 0;
$report = __( 'Done.', 'formipay' );
if(!empty($ids)){
foreach($ids as $id){
$delete = wp_delete_post($id, true);
if(is_wp_error( $delete )){
$failed++;
}else{
$success++;
}
}
}
if($success > 0){
$report .= sprintf( __( ' Deleted %d coupon(s).', 'formipay' ), $success);
}
if($failed > 0){
$report .= sprintf( __( ' Failed %d coupon(s).', 'formipay' ), $failed);
}
wp_send_json_success( [
'title' => esc_html__( 'Done!', 'formipay' ),
'message' => $report,
'icon' => 'info'
] );
}
public function formipay_duplicate_coupon() {
check_ajax_referer( 'formipay-admin', '_wpnonce' );
if ( ! current_user_can( 'manage_options' ) ) {
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
}
$post_id = isset($_REQUEST['id']) ? intval($_REQUEST['id']) : 0;
$post = get_post($post_id);
if (!$post) {
wp_send_json_error( [
'title' => esc_html__('Failed', 'formipay'),
'message' => esc_html__( 'Coupon is not defined.', 'formipay' ),
'icon' => 'error'
] );
}
if (!in_array($post->post_type, ['formipay-coupon'])) {
wp_send_json_error( [
'title' => esc_html__('Failed', 'formipay'),
'message' => esc_html__( 'Wrong Post Type.', 'formipay' ),
'icon' => 'error'
] );
}
$duplicate_post = [
'post_title' => $post->post_title . ' ' . __('Copy', 'formipay'),
'post_content' => $post->post_content,
'post_status' => 'draft', // Set sebagai draft
'post_type' => $post->post_type,
'post_author' => $post->post_author,
];
// Masukkan duplikat ke database
$new_post_id = wp_insert_post($duplicate_post);
if (is_wp_error($new_post_id)) {
wp_send_json_error( [
'title' => esc_html__('Failed', 'formipay'),
'message' => esc_html__( 'Something happened. Please try again.', 'formipay' ),
'icon' => 'error'
] );
}
// Salin semua meta data
$meta_data = get_post_meta($post_id);
foreach ($meta_data as $key => $values) {
if($key !== 'forms'){
foreach ($values as $value) {
add_post_meta($new_post_id, $key, maybe_unserialize($value));
}
}
}
wp_send_json_success( [
'title' => esc_html__('Duplicated!', 'formipay'),
'message' => esc_html__( 'Coupon is successfully duplicated.', 'formipay' ),
'icon' => 'success'
] );
}
/**
* Get coupon data for React editor
*/
public function formipay_get_coupon() {
check_ajax_referer( 'formipay-admin', '_wpnonce' );
if ( ! current_user_can( 'manage_options' ) ) {
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
}
$post_id = isset($_REQUEST['id']) ? intval($_REQUEST['id']) : 0;
if ( empty($post_id) ) {
wp_send_json_error( [ 'message' => esc_html__( 'Coupon ID is required.', 'formipay' ) ] );
}
$post = get_post($post_id);
if ( ! $post || $post->post_type !== 'formipay-coupon' ) {
wp_send_json_error( [ 'message' => esc_html__( 'Coupon not found.', 'formipay' ) ] );
}
$global_currencies = get_global_currency_array();
// Build coupon data
$coupon_data = [
'ID' => $post_id,
'post_title' => $post->post_title,
'active' => formipay_get_post_meta($post_id, 'active'),
'type' => formipay_get_post_meta($post_id, 'type'),
'amount_percentage' => formipay_get_post_meta($post_id, 'amount_percentage'),
'case_sensitive' => formipay_get_post_meta($post_id, 'case_sensitive'),
'free_shipping' => formipay_get_post_meta($post_id, 'free_shipping'),
'quantity_active' => formipay_get_post_meta($post_id, 'quantity_active'),
'use_limit' => formipay_get_post_meta($post_id, 'use_limit'),
'date_limit' => formipay_get_post_meta($post_id, 'date_limit'),
'amounts_fixed' => [],
'max_amounts' => [],
'forms' => formipay_get_post_meta($post_id, 'forms') ?: [],
'products' => formipay_get_post_meta($post_id, 'products') ?: [],
'customers' => formipay_get_post_meta($post_id, 'customers') ?: [],
];
// Get fixed amounts for each currency
foreach ($global_currencies as $currency) {
$currency_raw = $currency['currency'];
$currency_parts = explode(':::', $currency_raw);
$currency_code = $currency_parts[0] ?? '';
$symbol = formipay_get_currency_data_by_value($currency_raw, 'symbol');
$amount_fixed = formipay_get_post_meta($post_id, 'amount_fixed_' . $symbol);
if ( $amount_fixed ) {
$coupon_data['amounts_fixed'][] = [
'currency' => $currency_code,
'symbol' => $symbol,
'amount' => $amount_fixed,
];
}
$max_amount = formipay_get_post_meta($post_id, 'max_amount_' . $symbol);
if ( $max_amount ) {
$coupon_data['max_amounts'][] = [
'currency' => $currency_code,
'symbol' => $symbol,
'amount' => $max_amount,
];
}
}
wp_send_json_success( $coupon_data );
}
/**
* Save coupon data from React editor
*/
public function formipay_save_coupon() {
check_ajax_referer( 'formipay-admin', '_wpnonce' );
if ( ! current_user_can( 'manage_options' ) ) {
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
}
$post_id = isset($_REQUEST['id']) ? intval($_REQUEST['id']) : 0;
$title = isset($_REQUEST['title']) ? sanitize_text_field(wp_unslash($_REQUEST['title'])) : '';
if ( empty($title) ) {
wp_send_json_error( [ 'message' => esc_html__( 'Coupon code is required.', 'formipay' ) ] );
}
$global_currencies = get_global_currency_array();
// Prepare post data
$post_data = [
'post_title' => $title,
'post_type' => 'formipay-coupon',
'post_status' => 'publish',
];
if ( $post_id > 0 ) {
$post_data['ID'] = $post_id;
$post_data['post_status'] = get_post_status($post_id);
$new_post_id = wp_update_post($post_data);
} else {
$new_post_id = wp_insert_post($post_data);
}
if ( is_wp_error($new_post_id) ) {
wp_send_json_error( [ 'message' => $new_post_id->get_error_message() ] );
}
// Save meta fields
$meta_fields = [
'active',
'type',
'amount_percentage',
'case_sensitive',
'free_shipping',
'quantity_active',
'use_limit',
'date_limit',
];
foreach ($meta_fields as $field) {
$value = isset($_REQUEST[$field]) ? wp_unslash($_REQUEST[$field]) : '';
update_post_meta($new_post_id, $field, $value);
}
// Save fixed amounts
foreach ($global_currencies as $currency) {
$symbol = formipay_get_currency_data_by_value($currency['currency'], 'symbol');
if ( isset($_REQUEST['amount_fixed_' . $symbol]) ) {
update_post_meta($new_post_id, 'amount_fixed_' . $symbol, wp_unslash($_REQUEST['amount_fixed_' . $symbol]));
}
if ( isset($_REQUEST['max_amount_' . $symbol]) ) {
update_post_meta($new_post_id, 'max_amount_' . $symbol, wp_unslash($_REQUEST['max_amount_' . $symbol]));
}
}
// Save relation fields
$relation_fields = ['forms', 'products', 'customers'];
foreach ($relation_fields as $field) {
if ( isset($_REQUEST[$field]) ) {
$values = is_array($_REQUEST[$field]) ? array_map('intval', $_REQUEST[$field]) : [];
update_post_meta($new_post_id, $field, $values);
}
}
wp_send_json_success( [
'message' => esc_html__( 'Coupon saved successfully.', 'formipay' ),
'id' => $new_post_id,
] );
}
/**
* Add React metabox for coupon editor
*/
public function add_react_metabox() {
add_meta_box(
'formipay_coupon_reactor_metabox',
__( 'Coupon Settings', 'formipay' ),
[$this, 'render_react_metabox'],
'formipay-coupon',
'normal',
'high'
);
}
/**
* Render React metabox container
*/
public function render_react_metabox($post) {
?>
<div
data-formipay-metabox="coupon"
data-post-id="<?php echo esc_attr($post->ID); ?>"
class="formipay-react-metabox-container"
>
<div class="formipay-loading">
<div class="formipay-spinner"></div>
</div>
</div>
<?php
}
/**
* Render React metabox template (hidden)
*/
public function render_react_metabox_template() {
global $post;
if (!$post || $post->post_type !== 'formipay-coupon') {
return;
}
// Get global currencies
$global_currencies = get_global_currency_array();
?>
<script type="text/javascript">
window.formipayGlobalCurrencies = <?php echo wp_json_encode($global_currencies); ?>;
window.formipayGetFlag = function(currencyRaw) {
<?php
foreach ($global_currencies as $currency) {
echo 'if (currencyRaw === "' . esc_js($currency['currency']) . '") return "' . esc_url(formipay_get_flag_by_currency($currency['currency'])) . '";';
}
?>
return '';
};
</script>
<?php
}
/**
* Autocomplete search for relation fields
*/
public function formipay_autocomplete_search() {
check_ajax_referer( 'formipay-admin', '_wpnonce' );
if ( ! current_user_can( 'manage_options' ) ) {
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
}
$post_type = isset($_REQUEST['post_type']) ? sanitize_text_field(wp_unslash($_REQUEST['post_type'])) : '';
$search = isset($_REQUEST['search']) ? sanitize_text_field(wp_unslash($_REQUEST['search'])) : '';
if (empty($post_type) || strlen($search) < 2) {
wp_send_json_error( [ 'message' => 'Invalid request' ] );
}
$query = get_posts([
'post_type' => $post_type,
's' => $search,
'posts_per_page' => 20,
'post_status' => ['publish', 'draft'],
]);
$results = [];
if (!empty($query)) {
foreach ($query as $post) {
$results[] = [
'value' => $post->ID,
'label' => $post->post_title,
];
}
}
wp_send_json_success($results);
}
}