Shipping Migration: - Move shipping configuration from product-level to form-level - Add form shipping tab in form settings (no_shipping, flat_rate, free_shipping) - Update FlatRate to register at form level instead of product level - Update checkout logic to read from form settings - Support percentage-based flat rate calculation - Simplify shipping method IDs (flat_rate, free_shipping) Currency Flags Integration: - Add formipay_get_all_currency_flags() to read from admin/assets/json/flags.json - Remove hardcoded CURRENCY_FLAGS emoji map from VariationField.js - Create CurrencyFlag component to render base64 flag images - Localize currency_flags to window.formipayProductDetails - Update shipping info display in admin order details Benefits: - Form-level shipping prevents multiplying shipping costs per product - Single source of truth for currency flags (flags.json) - Better support for future cart system - Consistent with e-commerce standards
1227 lines
52 KiB
PHP
1227 lines
52 KiB
PHP
<?php
|
|
namespace Formipay;
|
|
use Formipay\Traits\SingletonTrait;
|
|
|
|
if ( ! defined( 'ABSPATH' ) ) exit;
|
|
|
|
class Product {
|
|
|
|
use SingletonTrait;
|
|
|
|
/**
|
|
* Initializes the plugin by setting filters and administration functions.
|
|
*/
|
|
|
|
protected function __construct() {
|
|
|
|
add_action( 'init', [$this, 'cpt'] );
|
|
add_action( 'init', [$this, 'taxonomy'] );
|
|
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/product-config', [$this, 'general_config'], 20 );
|
|
add_filter( 'formipay/product-config', [$this, 'variations_config'], 40 );
|
|
add_filter( 'formipay/product-config', [$this, 'stock_config'], 60 );
|
|
|
|
add_action( 'wp_ajax_formipay-tabledata-products', [$this, 'formipay_tabledata_products'] );
|
|
add_action( 'wp_ajax_formipay-create-product-post', [$this, 'formipay_create_product_post'] );
|
|
add_action( 'wp_ajax_formipay-delete-product', [$this, 'formipay_delete_product'] );
|
|
add_action( 'wp_ajax_formipay-bulk-delete-product', [$this, 'formipay_bulk_delete_product'] );
|
|
add_action( 'wp_ajax_formipay-duplicate-product', [$this, 'formipay_duplicate_product'] );
|
|
|
|
add_action( 'wp_ajax_formipay_product_get_currencies', [$this, 'formipay_product_get_currencies'] );
|
|
add_action( 'wp_ajax_get_product_variables', [$this, 'get_product_variables'] );
|
|
add_action( 'wp_ajax_get_product_attributes', [$this, 'get_product_attributes'] );
|
|
|
|
add_action('save_post', [$this, 'save_product'], 10, 2);
|
|
|
|
}
|
|
|
|
public function cpt() {
|
|
|
|
$labels = array(
|
|
'name' => __('Products', 'formipay'),
|
|
'singular_name' => __('Product', 'formipay'),
|
|
'menu_name' => 'Formipay',
|
|
'add_new' => __('Add New', 'formipay'),
|
|
'add_new_item' => __('Add New Product', 'formipay'),
|
|
'edit' => __('Edit', 'formipay'),
|
|
'edit_item' => __('Edit Product', 'formipay'),
|
|
'new_item' => __('New Product', 'formipay'),
|
|
'view' => __('View', 'formipay'),
|
|
'view_item' => __('View Product', 'formipay'),
|
|
'search_items' => __('Search Product', 'formipay'),
|
|
'not_found' => __('No products found', 'formipay'),
|
|
'not_found_in_trash' => __('No products found in trash', 'formipay'),
|
|
'parent' => __('Product Parent', 'formipay')
|
|
);
|
|
|
|
$args = array(
|
|
'label' => 'Products',
|
|
'labels' => $labels,
|
|
'public' => true,
|
|
'supports' => array( 'title' ),
|
|
'hierarchical' => true,
|
|
'taxonomies' => array( 'formipay-product-category' ),
|
|
'has_archive' => true,
|
|
'rewrite' => array( 'slug' => 'product' ),
|
|
'show_ui' => true,
|
|
'show_in_menu' => false,
|
|
'show_in_rest' => true,
|
|
'query_var' => true
|
|
);
|
|
|
|
register_post_type( 'formipay-product', $args );
|
|
|
|
}
|
|
|
|
public function taxonomy() {
|
|
register_taxonomy( 'formipay-product-category', 'formipay-product', array(
|
|
'rewrite' => array( 'slug' => 'product/category' ),
|
|
'hierarchical' => true
|
|
) );
|
|
}
|
|
|
|
public function add_submenu() {
|
|
|
|
add_action( 'add_meta_boxes', [$this, 'add_react_metabox'] );
|
|
add_action( 'admin_footer-post.php', [$this, 'render_react_metabox_template'] );
|
|
add_action( 'admin_footer-post-new.php', [$this, 'render_react_metabox_template'] );
|
|
add_action( 'save_post', [$this, 'save_product_metabox_fields'], 10, 2 );
|
|
|
|
add_submenu_page(
|
|
'formipay',
|
|
__('Products', 'formipay'),
|
|
__('Products', 'formipay'),
|
|
'manage_options',
|
|
'formipay-products',
|
|
[$this, 'formipay_product'],
|
|
2
|
|
);
|
|
|
|
add_submenu_page(
|
|
'formipay',
|
|
__('Categories', 'formipay'),
|
|
'└ ' . __('Categories', 'formipay'),
|
|
'manage_options',
|
|
'edit-tags.php?taxonomy=formipay-product-category&post_type=formipay-product',
|
|
null,
|
|
5
|
|
);
|
|
|
|
}
|
|
|
|
public function formipay_product() {
|
|
\Formipay\Admin\ReactAdmin::render_mount_point('products');
|
|
}
|
|
|
|
public function enqueue_admin() {
|
|
// Assets now handled by ReactAdmin class
|
|
return;
|
|
|
|
if($current_screen->id == 'formipay_page_formipay-products') {
|
|
|
|
wp_enqueue_style( 'page-products', FORMIPAY_URL . 'admin/assets/css/page-products.css', [], FORMIPAY_VERSION, 'all' );
|
|
wp_enqueue_script( 'page-products', FORMIPAY_URL . 'admin/assets/js/page-products.js', ['jquery', 'gridjs'], FORMIPAY_VERSION, true );
|
|
|
|
wp_localize_script( 'page-products', 'formipay_products_page', [
|
|
'ajax_url' => admin_url('admin-ajax.php'),
|
|
'site_url' => site_url(),
|
|
'columns' => [
|
|
'id' => esc_html__( 'ID', 'formipay' ),
|
|
'title' => esc_html__( 'Title', 'formipay' ),
|
|
'price' => esc_html__( 'Price', 'formipay' ),
|
|
'type' => esc_html__( 'Type', 'formipay' ),
|
|
'stock' => esc_html__( 'Stock', 'formipay' ),
|
|
'status' => esc_html__( 'Status', 'formipay' ),
|
|
],
|
|
'filter_form' => [
|
|
'categories' => [
|
|
'placeholder' => esc_html__( 'Filter by Category', 'formipay' ),
|
|
'noresult_text' => esc_html__( 'No results found', 'formipay' )
|
|
],
|
|
'currencies' => [
|
|
'placeholder' => esc_html__( 'Filter by Currency', 'formipay' ),
|
|
'noresult_text' => esc_html__( 'No results found', 'formipay' )
|
|
]
|
|
],
|
|
'modal' => [
|
|
'form' => [
|
|
'currency_options' => formipay_currency_as_options()
|
|
],
|
|
'add' => [
|
|
'title' => esc_html__( 'Your New Product Data', 'formipay' ),
|
|
'validation' => esc_html__( '{{field}} is required', 'formipay' ),
|
|
'cancelButton' => esc_html__( 'Cancel', 'formipay' ),
|
|
'confirmButton' => esc_html__( 'Create New Product', 'formipay' )
|
|
],
|
|
'delete' => [
|
|
'question' => esc_html__( 'Do you want to delete the product?', 'formipay' ),
|
|
'cancelButton' => esc_html__( 'Cancel', 'formipay' ),
|
|
'confirmButton' => esc_html__( 'Delete Permanently', 'formipay' )
|
|
],
|
|
'bulk_delete' => [
|
|
'question' => esc_html__( 'Do you want to delete the selected the product(s)?', 'formipay' ),
|
|
'cancelButton' => esc_html__( 'Cancel', 'formipay' ),
|
|
'confirmButton' => esc_html__( 'Confirm', 'formipay' )
|
|
],
|
|
'duplicate' => [
|
|
'question' => esc_html__( 'Do you want to duplicate the product?', 'formipay' ),
|
|
'cancelButton' => esc_html__( 'Cancel', 'formipay' ),
|
|
'confirmButton' => esc_html__( 'Confirm', 'formipay' )
|
|
],
|
|
],
|
|
'nonce' => wp_create_nonce('formipay-admin')
|
|
] );
|
|
}
|
|
|
|
if($current_screen->base == 'post' && $current_screen->post_type == 'formipay-product'){
|
|
global $post;
|
|
$product_id = $post->ID;
|
|
// Get pricing method, default to 'auto' if not set
|
|
$pricing_method = formipay_get_post_meta($product_id, 'product_pricing_method') ?: 'auto';
|
|
$has_variation = (bool) formipay_get_post_meta($product_id, 'product_has_variation', true);
|
|
|
|
wp_enqueue_style( 'product-details', FORMIPAY_URL . 'admin/assets/css/admin-product-editor.css', [], FORMIPAY_VERSION, 'all' );
|
|
wp_enqueue_script( 'product-details', FORMIPAY_URL . 'admin/assets/js/admin-product-editor.js', ['jquery', 'vue.js'], FORMIPAY_VERSION, true );
|
|
wp_localize_script( 'product-details', 'product_details', [
|
|
'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(),
|
|
'product_type' => formipay_get_post_meta($product_id, 'product_type') ?: 'digital',
|
|
'product_is_physical' => formipay_get_post_meta($product_id, 'product_type') == 'physical',
|
|
'product_pricing_method' => $pricing_method, // Pass pricing method to JS
|
|
'product_has_variation' => $has_variation,
|
|
'variation_table' => [
|
|
'th_toggle' => __('Active', 'formipay'),
|
|
'th_name' => __('Title', 'formipay'),
|
|
'th_stock' => __('Stock', 'formipay'),
|
|
'th_price' => __('Regular Price', 'formipay'),
|
|
'th_sale' => __('Sale Price', 'formipay'),
|
|
'th_weight' => __('Weight', 'formipay'),
|
|
'th_prices_overall' => __('Prices', 'formipay'),
|
|
'manual_price_hint' => __('Prices set manually below', 'formipay'),
|
|
'child_th_currency' => __('Currency', 'formipay'),
|
|
'child_th_regular' => __('Regular Price', 'formipay'),
|
|
'child_th_sale' => __('Sale Price', 'formipay'),
|
|
'no_currencies' => __( 'No currencies available', 'formipay' ),
|
|
'no_variations' => __( 'No variations available', 'formipay' ),
|
|
'child_placeholder_regular' => __( 'Enter Regular Price', 'formipay' ),
|
|
'child_placeholder_sale' => __( 'Enter Sale Price', 'formipay' ),
|
|
'error_missing_default_price' => __( 'Please fill Regular Price for default currency (%1$s) in variation "%2$s".', 'formipay' ),
|
|
]
|
|
] );
|
|
}
|
|
|
|
$screen = get_current_screen();
|
|
if($current_screen->taxonomy == 'formipay-product-category') {
|
|
wp_enqueue_style( 'formipay-admin-pages', FORMIPAY_URL . 'admin/assets/css/admin-pages.css', [], FORMIPAY_VERSION, 'all' );
|
|
wp_enqueue_style( 'gridjs', FORMIPAY_URL . 'vendor/GridJS/gridjs.mermaid.min.css', [], '6.2.0', 'all' );
|
|
wp_enqueue_style( 'page-product-taxonomy', FORMIPAY_URL . 'admin/assets/css/page-product-taxonomy.css', [], FORMIPAY_VERSION, 'all' );
|
|
wp_enqueue_script( 'formipay-admin-pages', FORMIPAY_URL . 'admin/assets/js/admin-pages.js', ['jquery'], FORMIPAY_VERSION, true );
|
|
wp_enqueue_script( 'gridjs', FORMIPAY_URL . 'vendor/GridJS/gridjs.production.min.js', ['jquery'], '6.2.0', true );
|
|
wp_enqueue_script( 'page-product-taxonomy', FORMIPAY_URL . 'admin/assets/js/page-product-taxonomy.js', ['jquery', 'gridjs'], FORMIPAY_VERSION, true );
|
|
wp_localize_script( 'page-product-taxonomy', 'formipay_product_taxonomy_page', [
|
|
'site_url' => site_url(),
|
|
'page_title' => esc_html__( 'Product Categories', 'formipay' )
|
|
] );
|
|
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);
|
|
wp_localize_script( 'sweetalert2', 'formipay_admin', [
|
|
'ajax_url' => admin_url('admin-ajax.php'),
|
|
'site_url' => site_url(),
|
|
] );
|
|
}
|
|
|
|
}
|
|
|
|
public function formipay_products_react() {
|
|
|
|
ReactAdmin::render_mount_point('products');
|
|
}
|
|
|
|
public function add_react_metabox() {
|
|
add_meta_box(
|
|
'formipay_product_settings',
|
|
__('Settings', 'formipay'),
|
|
[$this, 'render_react_metabox'],
|
|
'formipay-product',
|
|
'normal',
|
|
'high'
|
|
);
|
|
}
|
|
|
|
public function render_react_metabox($post) {
|
|
echo '<div data-formipay-field-renderer="product" data-post-id="' . esc_attr($post->ID) . '"></div>';
|
|
}
|
|
|
|
public function render_react_metabox_template() {
|
|
global $post;
|
|
|
|
if (!$post || $post->post_type !== 'formipay-product') {
|
|
return;
|
|
}
|
|
|
|
$config = \Formipay\Admin\FieldConfigBridge::get_config_for_post($post->ID, $post->post_type);
|
|
|
|
// Get multi-currency settings from formipay_settings option
|
|
$settings = get_option('formipay_settings', []);
|
|
$is_multicurrency = !empty($settings['enable_multicurrency']);
|
|
$multicurrencies = $settings['multicurrencies'] ?? [];
|
|
|
|
// Build global_selected_currencies from multicurrencies array
|
|
$global_selected = [];
|
|
foreach ($multicurrencies as $currency) {
|
|
if (isset($currency['currency'])) {
|
|
$code = explode(':::', $currency['currency'])[0];
|
|
$global_selected[$code] = true;
|
|
}
|
|
}
|
|
|
|
// Use the same helper functions for consistency
|
|
$global_currencies = get_global_currency_array();
|
|
$default_currency = formipay_default_currency();
|
|
|
|
$product_details = [
|
|
'multicurrency' => $is_multicurrency,
|
|
'default_currency' => $default_currency,
|
|
'global_currencies' => $global_currencies,
|
|
'global_selected_currencies' => $global_selected,
|
|
'currency_flags' => formipay_get_all_currency_flags(),
|
|
];
|
|
?>
|
|
<script type="text/javascript">
|
|
window.formipayFieldConfig = <?php echo wp_json_encode($config); ?>;
|
|
window.formipayProductDetails = <?php echo wp_json_encode($product_details); ?>;
|
|
</script>
|
|
<?php
|
|
}
|
|
|
|
public function formipay_products() {
|
|
|
|
ReactAdmin::render_mount_point('products');
|
|
}
|
|
|
|
public function cpt_post_fields_box($boxes) {
|
|
$boxes['formipay_product_settings'] = array(
|
|
'post_type' => array('formipay-product'),
|
|
'label' => __('Config', 'formipay'),
|
|
);
|
|
|
|
return $boxes;
|
|
}
|
|
|
|
public function cpt_post_fields_content($fields) {
|
|
|
|
$fields['formipay_product_settings'] = array();
|
|
|
|
$fields = apply_filters( 'formipay/product-config', $fields );
|
|
|
|
return $fields;
|
|
}
|
|
|
|
public function save_product_metabox_fields($post_id, $post) {
|
|
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
|
|
return $post_id;
|
|
}
|
|
|
|
if (!current_user_can('manage_options')) {
|
|
return $post_id;
|
|
}
|
|
|
|
if (!isset($_POST['_wpnonce']) || !wp_verify_nonce($_POST['_wpnonce'], 'update-post_' . $post_id)) {
|
|
return $post_id;
|
|
}
|
|
|
|
if ($post->post_type !== 'formipay-product') {
|
|
return $post_id;
|
|
}
|
|
|
|
$meta_fields = [
|
|
'product_type',
|
|
'setting_product_price_regular',
|
|
'setting_product_price_sale',
|
|
'free_shipping',
|
|
// Shipping fields
|
|
'shipping_method',
|
|
'flat_rate_type',
|
|
'flat_rate_amount',
|
|
'flat_rate_label',
|
|
'free_shipping_label',
|
|
'free_shipping_add_to_order_review',
|
|
// Shipping dimensions (for carrier API calculation)
|
|
'product_weight',
|
|
'product_length',
|
|
'product_width',
|
|
'product_height',
|
|
// Access and status
|
|
'product_accesses',
|
|
'product_access_to_email',
|
|
'active',
|
|
];
|
|
|
|
$global_currencies = get_global_currency_array();
|
|
|
|
foreach ($meta_fields as $field) {
|
|
if (isset($_POST[$field])) {
|
|
$value = wp_unslash($_POST[$field]);
|
|
update_post_meta($post_id, $field, $value);
|
|
}
|
|
}
|
|
|
|
foreach ($global_currencies as $currency) {
|
|
$symbol = formipay_get_currency_data_by_value($currency['currency'], 'symbol');
|
|
|
|
if (isset($_POST['setting_product_price_regular_' . $symbol])) {
|
|
update_post_meta($post_id, 'setting_product_price_regular_' . $symbol, wp_unslash($_POST['setting_product_price_regular_' . $symbol]));
|
|
}
|
|
|
|
if (isset($_POST['max_amount_' . $symbol])) {
|
|
update_post_meta($post_id, 'max_amount_' . $symbol, wp_unslash($_POST['max_amount_' . $symbol]));
|
|
}
|
|
|
|
// Save flat rate amounts per currency
|
|
if (isset($_POST['flat_rate_amount_' . $symbol])) {
|
|
update_post_meta($post_id, 'flat_rate_amount_' . $symbol, wp_unslash($_POST['flat_rate_amount_' . $symbol]));
|
|
}
|
|
}
|
|
|
|
// Save product variations (JSON from VariationField)
|
|
if (isset($_POST['product_variations'])) {
|
|
$variations_json = wp_unslash($_POST['product_variations']);
|
|
$variations_data = json_decode($variations_json, true);
|
|
|
|
if (json_last_error() === JSON_ERROR_NONE && is_array($variations_data)) {
|
|
update_post_meta($post_id, 'product_variations', $variations_json);
|
|
|
|
// Also save the legacy format for backward compatibility
|
|
if (isset($variations_data['variations']) && is_array($variations_data['variations'])) {
|
|
$legacy_variations = $variations_data['variations'];
|
|
update_post_meta($post_id, 'product_variables', wp_json_encode($legacy_variations));
|
|
}
|
|
|
|
// Save attributes separately for legacy compatibility
|
|
if (isset($variations_data['attributes']) && is_array($variations_data['attributes'])) {
|
|
$legacy_attributes = [];
|
|
foreach ($variations_data['attributes'] as $attr) {
|
|
$legacy_attributes[] = [
|
|
'attribute_name' => $attr['attribute_name'] ?? '',
|
|
'attribute_type' => $attr['attribute_type'] ?? 'select',
|
|
'attribute_variations' => $attr['attribute_variations'] ?? [],
|
|
];
|
|
}
|
|
update_post_meta($post_id, 'product_variation_attributes', wp_json_encode($legacy_attributes));
|
|
}
|
|
} else {
|
|
delete_post_meta($post_id, 'product_variations');
|
|
}
|
|
}
|
|
|
|
return $post_id;
|
|
}
|
|
|
|
public function general_config($fields) {
|
|
|
|
// Product Details Group
|
|
$product_details_group = array(
|
|
'setting_product_details' => array(
|
|
'type' => 'group_title',
|
|
'label' => __( 'Product Details', 'formipay' ),
|
|
'description' => __( 'All details about the products sold using this form.', 'formipay' ),
|
|
'group' => 'started'
|
|
),
|
|
'product_type' => array(
|
|
'type' => 'radio',
|
|
'label' => __('Product Type', 'formipay'),
|
|
'options' => array(
|
|
'digital' => 'Digital',
|
|
'physical' => 'Physical'
|
|
),
|
|
'value' => 'digital',
|
|
'required' => true
|
|
),
|
|
'product_description' => array(
|
|
'type' => 'tinymce',
|
|
'label' => __('Description', 'formipay'),
|
|
)
|
|
);
|
|
|
|
$product_details_group = apply_filters( 'formipay/product-settings/tab:general/group:product-details', $product_details_group );
|
|
|
|
$last_product_details_group = array_key_last($product_details_group);
|
|
$product_details_group[$last_product_details_group]['group'] = 'ended';
|
|
|
|
// Product Currency Group
|
|
// $product_currency_group = array(
|
|
// 'setting_product_pricing' => array(
|
|
// 'type' => 'group_title',
|
|
// 'label' => __( 'Pricing', 'formipay' ),
|
|
// 'description' => __( 'Carefully set these options below.', 'formipay' ),
|
|
// 'group' => 'started',
|
|
// ),
|
|
// 'product_pricing_method' => array(
|
|
// 'type' => 'radio',
|
|
// 'label' => __('Product Pricing Method', 'formipay'),
|
|
// 'options' => array(
|
|
// 'manual' => 'Manual Price Set',
|
|
// 'auto' => 'Auto via Currency Exchange API'
|
|
// ),
|
|
// 'value' => 'manual',
|
|
// 'required' => true
|
|
// ),
|
|
// 'product_regular_price' => array(
|
|
// 'type' => 'number',
|
|
// 'label' => sprintf( __('Regular Price (%s)', 'formipay'), formipay_default_currency('symbol') ),
|
|
// 'value' => 0,
|
|
// 'step' => 0.01,
|
|
// 'required' => true,
|
|
// 'dependency' => [
|
|
// 'key' => 'product_pricing_method',
|
|
// 'value' => 'auto'
|
|
// ]
|
|
// ),
|
|
// 'product_sale_price' => array(
|
|
// 'type' => 'number',
|
|
// 'label' => sprintf( __('Sale Price (%s)', 'formipay'), formipay_default_currency('symbol') ),
|
|
// 'value' => 0,
|
|
// 'step' => 0.01,
|
|
// 'dependency' => [
|
|
// 'key' => 'product_pricing_method',
|
|
// 'value' => 'auto'
|
|
// ]
|
|
// ),
|
|
// 'product_prices' => [
|
|
// 'type' => 'repeater',
|
|
// 'label' => __( 'Prices', 'formipay' ),
|
|
// 'description' => __( 'You can set price with multiple currency', 'formipay' ),
|
|
// 'fields' => [
|
|
// 'regular_price' => array(
|
|
// 'type' => 'number',
|
|
// 'label' => __('Regular Price', 'formipay'),
|
|
// 'value' => 0,
|
|
// 'step' => 0.01,
|
|
// 'required' => true
|
|
// ),
|
|
// 'sale_price' => array(
|
|
// 'type' => 'number',
|
|
// 'label' => __('Sale Price', 'formipay'),
|
|
// 'value' => 0,
|
|
// 'step' => 0.01
|
|
// ),
|
|
// 'currency' => array(
|
|
// 'type' => 'select',
|
|
// 'label' => __('Currency', 'formipay'),
|
|
// 'value' => 'IDR:::Indonesian rupiah:::Rp',
|
|
// 'options' => formipay_currency_as_options(),
|
|
// 'required' => true,
|
|
// 'searchable' => true,
|
|
// 'is_group_title' => true
|
|
// ),
|
|
// 'currency_decimal_digits' => array(
|
|
// 'type' => 'number',
|
|
// 'label' => __('Decimal Digits', 'formipay'),
|
|
// 'value' => '2',
|
|
// 'required' => true
|
|
// ),
|
|
// 'currency_decimal_symbol' => array(
|
|
// 'type' => 'text',
|
|
// 'label' => __('Decimal Symbol', 'formipay'),
|
|
// 'value' => '.',
|
|
// 'required' => true
|
|
// ),
|
|
// 'currency_thousand_separator' => array(
|
|
// 'type' => 'text',
|
|
// 'label' => __('Thousand Separator Symbol', 'formipay'),
|
|
// 'value' => ',',
|
|
// 'required' => true
|
|
// ),
|
|
// ],
|
|
// 'dependency' => [
|
|
// 'key' => 'product_pricing_method',
|
|
// 'value' => 'manual'
|
|
// ]
|
|
// ],
|
|
// );
|
|
|
|
$global_currencies = get_global_currency_array();
|
|
$default_currency = formipay_default_currency();
|
|
|
|
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;
|
|
$product_currency_group['setting_product_pricing_'.$currency_symbol] = array(
|
|
'type' => 'group_title',
|
|
'label' => sprintf(
|
|
__( '<img src="%s" width="18" /> Pricing in %s (%s)', 'formipay' ),
|
|
formipay_get_flag_by_currency($currency['currency']),
|
|
$currency_title,
|
|
$currency_symbol
|
|
),
|
|
'group' => 'started',
|
|
);
|
|
$product_currency_group['setting_product_price_regular_'.$currency_symbol] = array(
|
|
'type' => 'number',
|
|
'label' => __( 'Regular Price', 'formipay' ),
|
|
'step' => $step,
|
|
'min' => 0,
|
|
'placeholder' => __( 'Auto', 'formipay' )
|
|
);
|
|
$product_currency_group['setting_product_price_sale_'.$currency_symbol] = array(
|
|
'type' => 'number',
|
|
'label' => __( '🎉 Sale Price', 'formipay' ),
|
|
'step' => $step,
|
|
'min' => 0,
|
|
'placeholder' => __( 'Auto', 'formipay' ),
|
|
'group' => 'ended'
|
|
);
|
|
|
|
if(count($global_currencies) > 1){
|
|
if($default_currency_symbol === $currency_symbol){
|
|
$product_currency_group['setting_product_pricing_'.$currency_symbol]['description'] = sprintf(
|
|
__( 'This is your default currency. <a href="%s" target="_blank">Change in Settings</a>', 'formipay' ),
|
|
admin_url('/admin.php?page=formipay-settings')
|
|
);
|
|
$product_currency_group['setting_product_price_regular_'.$currency_symbol]['required'] = true;
|
|
$product_currency_group['setting_product_price_regular_'.$currency_symbol]['placeholder'] = __( 'Enter Regular Price...', 'formipay' );
|
|
$product_currency_group['setting_product_price_sale_'.$currency_symbol]['placeholder'] = __( 'Enter Sale Price...', 'formipay' );
|
|
}else{
|
|
$product_currency_group['setting_product_pricing_'.$currency_symbol]['description'] = sprintf(
|
|
__( 'System will calculate the price in %s based on exchange rate against %s when you leave these empty.', 'formipay' ),
|
|
$currency_symbol, $default_currency_symbol
|
|
);
|
|
}
|
|
}else{
|
|
$product_currency_group['setting_product_pricing_'.$currency_symbol]['label'] = __( 'Product Prices', 'formipay' );
|
|
$product_currency_group['setting_product_price_regular_'.$currency_symbol]['placeholder'] = __( 'Enter Regular Price...', 'formipay' );
|
|
$product_currency_group['setting_product_price_sale_'.$currency_symbol]['placeholder'] = __( 'Enter Sale Price...', 'formipay' );
|
|
}
|
|
}
|
|
|
|
$product_currency_group = apply_filters( 'formipay/product-settings/tab:general/group:product-currency', $product_currency_group );
|
|
|
|
// Shipping Dimensions Group (for physical products only)
|
|
$shipping_dimensions_group = array(
|
|
'setting_product_shipping_dimensions' => array(
|
|
'type' => 'group_title',
|
|
'label' => __( 'Shipping Dimensions', 'formipay' ),
|
|
'description' => __( 'Weight and dimensions for carrier shipping calculation.', 'formipay' ),
|
|
'dependency' => array(
|
|
'key' => 'product_type',
|
|
'value' => 'physical'
|
|
),
|
|
'group' => 'started'
|
|
),
|
|
'product_weight' => array(
|
|
'type' => 'number',
|
|
'label' => __( 'Weight (kg)', 'formipay' ),
|
|
'step' => 0.01,
|
|
'min' => 0,
|
|
'placeholder' => '0.00',
|
|
'dependency' => array(
|
|
'key' => 'product_type',
|
|
'value' => 'physical'
|
|
)
|
|
),
|
|
'product_length' => array(
|
|
'type' => 'number',
|
|
'label' => __( 'Length (cm)', 'formipay' ),
|
|
'step' => 0.1,
|
|
'min' => 0,
|
|
'placeholder' => '0.0',
|
|
'dependency' => array(
|
|
'key' => 'product_type',
|
|
'value' => 'physical'
|
|
)
|
|
),
|
|
'product_width' => array(
|
|
'type' => 'number',
|
|
'label' => __( 'Width (cm)', 'formipay' ),
|
|
'step' => 0.1,
|
|
'min' => 0,
|
|
'placeholder' => '0.0',
|
|
'dependency' => array(
|
|
'key' => 'product_type',
|
|
'value' => 'physical'
|
|
)
|
|
),
|
|
'product_height' => array(
|
|
'type' => 'number',
|
|
'label' => __( 'Height (cm)', 'formipay' ),
|
|
'step' => 0.1,
|
|
'min' => 0,
|
|
'placeholder' => '0.0',
|
|
'dependency' => array(
|
|
'key' => 'product_type',
|
|
'value' => 'physical'
|
|
),
|
|
'group' => 'ended'
|
|
),
|
|
);
|
|
|
|
$shipping_dimensions_group = apply_filters( 'formipay/product-settings/tab:general/group:shipping-dimensions', $shipping_dimensions_group );
|
|
|
|
$general_all_fields = array_merge($product_details_group, $product_currency_group, $shipping_dimensions_group);
|
|
|
|
$general_all_fields = apply_filters( 'formipay/product-settings/tab:general', $general_all_fields );
|
|
|
|
$fields['formipay_product_settings']['general'] = array(
|
|
'name' => __('General', 'formipay'),
|
|
'fields' => $general_all_fields
|
|
);
|
|
|
|
return $fields;
|
|
|
|
}
|
|
|
|
public function variations_config($fields) {
|
|
// Product Variations - Unified React field with attributes and variations table
|
|
$product_variations_group = array(
|
|
'setting_product_variations' => array(
|
|
'type' => 'group_title',
|
|
'label' => __( 'Product Variations', 'formipay' ),
|
|
'description' => __( 'Configure attributes and their combinations to generate product variations with multi-currency pricing.', 'formipay' ),
|
|
'group' => 'started'
|
|
),
|
|
'product_variations' => array(
|
|
'type' => 'variation',
|
|
'label' => __( 'Variations', 'formipay' ),
|
|
'description' => __( 'Add attributes (e.g., Color, Size) and their values. Variations will be generated automatically from all combinations.', 'formipay' ),
|
|
'name' => 'product_variations',
|
|
),
|
|
);
|
|
|
|
$product_variations_group = apply_filters( 'formipay/product-settings/tab:variations/group:product-variations', $product_variations_group );
|
|
|
|
$last_product_variations_group = array_key_last($product_variations_group);
|
|
$product_variations_group[$last_product_variations_group]['group'] = 'ended';
|
|
|
|
$variation_all_fields = apply_filters( 'formipay/product-settings/tab:variations', $product_variations_group );
|
|
|
|
$fields['formipay_product_settings']['variation'] = array(
|
|
'name' => __('Variations', 'formipay'),
|
|
'fields' => $variation_all_fields
|
|
);
|
|
|
|
return $fields;
|
|
}
|
|
|
|
public function stock_config($fields) {
|
|
|
|
// Product Quantity Group
|
|
$product_quantity_group = array(
|
|
'setting_product_quantity' => array(
|
|
'type' => 'group_title',
|
|
'label' => __( 'Quantity Settings', 'formipay' ),
|
|
'description' => __( 'You can activate this if you will manage the stock.', 'formipay' ),
|
|
'group' => 'started'
|
|
),
|
|
'product_quantity_toggle' => array(
|
|
'type' => 'checkbox',
|
|
'label' => __( 'Activate Quantity', 'formipay' ),
|
|
),
|
|
'product_quantity_range' => array(
|
|
'type' => 'number',
|
|
'label' => __( 'Quantity Range Step', 'formipay' ),
|
|
'value' => 1,
|
|
'dependency' => array(
|
|
'key' => 'product_quantity_toggle',
|
|
'value' => 'not_empty'
|
|
)
|
|
),
|
|
'product_minimum_purchase' => array(
|
|
'type' => 'number',
|
|
'label' => __( 'Minimum Purchase', 'formipay' ),
|
|
'value' => 1,
|
|
'dependency' => array(
|
|
'key' => 'product_quantity_toggle',
|
|
'value' => 'not_empty'
|
|
)
|
|
),
|
|
'product_stock' => array(
|
|
'type' => 'number',
|
|
'label' => __( 'Stock', 'formipay' ),
|
|
'description' => __('Set -1 for unlimited stock', 'formipay'),
|
|
'value' => -1,
|
|
'dependency' => array(
|
|
'key' => 'product_quantity_toggle',
|
|
'value' => 'not_empty'
|
|
)
|
|
)
|
|
);
|
|
|
|
$product_quantity_group = apply_filters( 'formipay/product-settings/tab:stock/group:product-quantity', $product_quantity_group );
|
|
|
|
$last_product_quantity_group = array_key_last($product_quantity_group);
|
|
$product_quantity_group[$last_product_quantity_group]['group'] = 'ended';
|
|
|
|
$stock_all_fields = apply_filters( 'formipay/product-settings/tab:stock', $product_quantity_group );
|
|
|
|
$fields['formipay_product_settings']['stock'] = array(
|
|
'name' => __('Stock & Quantity', 'formipay'),
|
|
'fields' => $stock_all_fields
|
|
);
|
|
|
|
return $fields;
|
|
|
|
}
|
|
|
|
public function formipay_tabledata_products() {
|
|
|
|
check_ajax_referer( 'formipay-admin', '_wpnonce' );
|
|
|
|
if ( ! current_user_can( 'manage_options' ) ) {
|
|
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
|
}
|
|
|
|
global $wpdb;
|
|
|
|
// Initialize default args
|
|
$base_args = [
|
|
'post_type' => 'formipay-product',
|
|
'post_status' => ['publish', 'draft', 'pending'],
|
|
'fields' => 'ids' // Optimize initial query
|
|
];
|
|
|
|
// Handle status filtering
|
|
if (isset($_REQUEST['post_status']) && 'all' !== $_REQUEST['post_status']) {
|
|
$base_args['post_status'] = [sanitize_key($_REQUEST['post_status'])];
|
|
}
|
|
|
|
// Currency filtering
|
|
if (!empty($_REQUEST['currency'])) {
|
|
// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
|
|
$base_args['meta_query'] = [
|
|
[
|
|
'key' => 'product_currency',
|
|
'value' => sanitize_text_field(wp_unslash($_REQUEST['currency'])),
|
|
'compare' => 'LIKE'
|
|
]
|
|
];
|
|
}
|
|
|
|
// Category filtering
|
|
if (!empty($_REQUEST['category'])) {
|
|
// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query
|
|
$base_args['tax_query'] = [
|
|
[
|
|
'taxonomy' => 'formipay-product-category',
|
|
'field' => 'term_id',
|
|
'terms' => absint($_REQUEST['category'])
|
|
]
|
|
];
|
|
}
|
|
|
|
// Search functionality
|
|
if (!empty($_REQUEST['search'])) {
|
|
$base_args['s'] = isset($_REQUEST['search']) ? sanitize_text_field(wp_unslash($_REQUEST['search'])) : '';
|
|
}
|
|
|
|
// Sorting
|
|
if (!empty($_REQUEST['orderby'])) {
|
|
$orderby = sanitize_key($_REQUEST['orderby']);
|
|
$order = isset($_REQUEST['sort']) ? sanitize_key($_REQUEST['sort']) : 'ASC';
|
|
|
|
if ('price' === $orderby) {
|
|
// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
|
|
$base_args['meta_key'] = 'product_price';
|
|
$base_args['orderby'] = 'meta_value_num';
|
|
} else {
|
|
$base_args['orderby'] = $orderby;
|
|
}
|
|
$base_args['order'] = $order;
|
|
}
|
|
|
|
// Pagination
|
|
if (isset($_REQUEST['limit'])) {
|
|
$base_args['posts_per_page'] = absint($_REQUEST['limit']);
|
|
}
|
|
if (isset($_REQUEST['offset'])) {
|
|
$base_args['offset'] = intval($_REQUEST['offset']);
|
|
}
|
|
|
|
// Main query
|
|
$query = new \WP_Query($base_args);
|
|
$product_ids = $query->posts;
|
|
$total_products = $query->found_posts;
|
|
|
|
// Process results
|
|
$global_currencies = get_global_currency_array();
|
|
$products = [];
|
|
foreach ($product_ids as $product_id) {
|
|
$product = get_post($product_id);
|
|
|
|
$currency = explode(':::', get_post_meta($product_id, 'product_currency', true));
|
|
$categories = wp_get_post_terms($product_id, 'formipay-product-category', ['fields' => 'names']);
|
|
|
|
// Build multi-currency prices array
|
|
$prices = [];
|
|
foreach ($global_currencies as $curr) {
|
|
$curr_raw = $curr['currency'];
|
|
$curr_parts = explode(':::', $curr_raw);
|
|
$curr_code = $curr_parts[0] ?? '';
|
|
$symbol = formipay_get_currency_data_by_value($curr_raw, 'symbol');
|
|
|
|
$regular_price = get_post_meta($product_id, 'setting_product_price_regular_' . $symbol, true);
|
|
$sale_price = get_post_meta($product_id, 'setting_product_price_sale_' . $symbol, true);
|
|
|
|
// Only add if we have at least a regular price
|
|
if (!empty($regular_price)) {
|
|
// Format price using this currency's own formatting rules
|
|
$decimal_digits = intval($curr['decimal_digits'] ?? 2);
|
|
$decimal_symbol = $curr['decimal_symbol'] ?? '.';
|
|
$thousand_separator = $curr['thousand_separator'] ?? ',';
|
|
|
|
$formatted_regular = $symbol . ' ' . number_format(floatval($regular_price), $decimal_digits, $decimal_symbol, $thousand_separator);
|
|
$formatted_sale = !empty($sale_price) ? $symbol . ' ' . number_format(floatval($sale_price), $decimal_digits, $decimal_symbol, $thousand_separator) : '';
|
|
|
|
$prices[] = [
|
|
'currency' => $curr_code,
|
|
'symbol' => $symbol,
|
|
'flag' => formipay_get_flag_by_currency($curr_raw),
|
|
'regular_price' => $formatted_regular,
|
|
'sale_price' => $formatted_sale,
|
|
'has_sale' => !empty($sale_price),
|
|
];
|
|
}
|
|
}
|
|
|
|
// Fallback to single price if no multi-currency prices set
|
|
if (empty($prices)) {
|
|
$fallback_price = get_post_meta($product_id, 'price', true);
|
|
$prices[] = [
|
|
'currency' => $currency[0] ?? 'USD',
|
|
'symbol' => $currency[2] ?? '$',
|
|
'flag' => formipay_get_flag_by_currency($currency[0] ?? ''),
|
|
'regular_price' => formipay_price_format($fallback_price, $product_id),
|
|
'sale_price' => '',
|
|
'has_sale' => false,
|
|
];
|
|
}
|
|
|
|
$products[] = [
|
|
'ID' => $product_id,
|
|
'title' => $product->post_title,
|
|
'category' => implode(', ', $categories),
|
|
'type' => formipay_get_post_meta($product_id, 'product_type'),
|
|
'stock' => formipay_get_post_meta($product_id, 'stock') ?: '∞',
|
|
'prices' => $prices,
|
|
'status' => $product->post_status,
|
|
];
|
|
}
|
|
|
|
// Get status counts using WordPress API
|
|
$counts = wp_count_posts('formipay-product');
|
|
$status_counts = [];
|
|
foreach ($counts as $status => $count) {
|
|
$status_counts[$status] = $count;
|
|
}
|
|
$status_counts['all'] = array_sum($status_counts);
|
|
|
|
wp_send_json([
|
|
'results' => $products,
|
|
'total' => $total_products,
|
|
'posts_report' => array_map('intval', (array)$status_counts)
|
|
]);
|
|
|
|
}
|
|
|
|
public function formipay_create_product_post() {
|
|
|
|
check_ajax_referer( 'formipay-admin', '_wpnonce' );
|
|
|
|
if ( ! current_user_can( 'manage_options' ) ) {
|
|
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
|
}
|
|
|
|
$title = isset($_REQUEST['title']) ? sanitize_text_field( wp_unslash($_REQUEST['title']) ) : '';
|
|
|
|
if( !empty($title) && '' !== $title ){
|
|
$post_id = wp_insert_post( [
|
|
'post_title' => $title,
|
|
'post_type' => 'formipay-product',
|
|
], true );
|
|
|
|
if(is_wp_error($post_id)){
|
|
wp_send_json_error( [
|
|
'message' => $post_id->get_error_message()
|
|
] );
|
|
}
|
|
|
|
update_post_meta($post_id, 'product_currency', 'USD:::United States dollar:::$'); // Note:: Ganti dengan default currency dari global settings
|
|
|
|
wp_send_json_success( [
|
|
'edit_post_url' => admin_url('post.php?post='.$post_id.'&action=edit')
|
|
] );
|
|
}
|
|
|
|
wp_send_json_error( [
|
|
'message' => esc_html__( 'Product\'s title is empty.', 'formipay' )
|
|
] );
|
|
|
|
}
|
|
|
|
public function formipay_product_get_currencies() {
|
|
|
|
check_ajax_referer( 'formipay-admin', '_wpnonce' );
|
|
|
|
if ( ! current_user_can( 'manage_options' ) ) {
|
|
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
|
}
|
|
|
|
$search = isset($_REQUEST['search']) ? sanitize_text_field( wp_unslash($_REQUEST['search']) ) : '';
|
|
|
|
$countries = formipay_currency_array();
|
|
$results = [];
|
|
foreach($countries as $country){
|
|
$country_name = strtolower($country['name']);
|
|
$country_search = strtolower($search);
|
|
if(strpos($country_name, $country_search) !== false || $country_search == strtolower($country['code'])){
|
|
$results[] = [
|
|
'value' => $country['code'],
|
|
// phpcs:ignore PluginCheck.CodeAnalysis.ImageFunctions.NonEnqueuedImage -- This image is a plugin asset and not a WordPress attachment.
|
|
'label' => '<img src="'.formipay_get_flag_by_currency($country['code']).'" height="18" style="margin-bottom: -3px;"> '.$country['name']
|
|
];
|
|
}
|
|
}
|
|
|
|
wp_send_json( $results );
|
|
|
|
}
|
|
|
|
public function formipay_delete_product() {
|
|
|
|
check_ajax_referer( 'formipay-admin', '_wpnonce' );
|
|
|
|
if ( ! current_user_can( 'manage_options' ) ) {
|
|
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
|
}
|
|
|
|
$form_id = isset($_REQUEST['id']) ? intval($_REQUEST['id']) : '';
|
|
|
|
$delete = wp_delete_post($form_id, true);
|
|
|
|
if(is_wp_error( $delete )){
|
|
wp_send_json_error( [
|
|
'title' => esc_html__( 'Failed', 'formipay' ),
|
|
'message' => esc_html__( 'Failed to delete product. Please try again.', 'formipay' ),
|
|
'icon' => 'error'
|
|
] );
|
|
}
|
|
|
|
wp_send_json_success( [
|
|
'title' => esc_html__( 'Deleted', 'formipay' ),
|
|
'message' => esc_html__( 'Product is deleted permanently.', 'formipay' ),
|
|
'icon' => 'success'
|
|
] );
|
|
|
|
}
|
|
|
|
public function formipay_bulk_delete_product() {
|
|
|
|
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 product selected. Please try again.', 'formipay' ),
|
|
'icon' => 'error'
|
|
] );
|
|
}
|
|
|
|
$ids = isset($_REQUEST['ids']) ? $_REQUEST['ids'] : [];
|
|
|
|
$success = 0;
|
|
$failed = 0;
|
|
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 product(s).', 'formipay' ), $success);
|
|
}
|
|
if($failed > 0){
|
|
$report .= sprintf( __( ' Failed %d product(s).', 'formipay' ), $failed);
|
|
}
|
|
|
|
wp_send_json_success( [
|
|
'title' => esc_html__( 'Done!', 'formipay' ),
|
|
'message' => $report,
|
|
'icon' => 'info'
|
|
] );
|
|
|
|
}
|
|
|
|
public function formipay_duplicate_product() {
|
|
|
|
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']) : '';
|
|
$post = get_post($post_id);
|
|
if (!$post) {
|
|
wp_send_json_error( [
|
|
'title' => esc_html__('Failed', 'formipay'),
|
|
'message' => esc_html__( 'Product is not defined.', 'formipay' ),
|
|
'icon' => 'error'
|
|
] );
|
|
}
|
|
|
|
if (!in_array($post->post_type, ['formipay-product'])) {
|
|
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)',
|
|
'post_content' => $post->post_content,
|
|
'post_status' => 'draft', // Set sebagai draft
|
|
'post_type' => $post->post_type,
|
|
'post_author' => $post->post_author,
|
|
];
|
|
|
|
$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'
|
|
] );
|
|
}
|
|
|
|
$meta_data = get_post_meta($post_id);
|
|
foreach ($meta_data as $key => $values) {
|
|
foreach ($values as $value) {
|
|
update_post_meta($new_post_id, $key, maybe_unserialize($value));
|
|
}
|
|
}
|
|
|
|
$taxonomies = get_object_taxonomies($post->post_type);
|
|
foreach ($taxonomies as $taxonomy) {
|
|
$terms = wp_get_object_terms($post_id, $taxonomy, ['fields' => 'slugs']);
|
|
wp_set_object_terms($new_post_id, $terms, $taxonomy);
|
|
}
|
|
|
|
wp_send_json_success( [
|
|
'title' => esc_html__('Duplicated!', 'formipay'),
|
|
'message' => esc_html__( 'Product is successfully duplicated.', 'formipay' ),
|
|
'icon' => 'success'
|
|
] );
|
|
}
|
|
|
|
public function get_product_variables() {
|
|
$post_id = intval($_POST['post_id'] ?? 0);
|
|
$data = get_post_meta($post_id, 'product_variables', true);
|
|
$json = is_string($data) ? json_decode($data, true) : [];
|
|
if(is_array($json)){
|
|
wp_send_json_success( $json );
|
|
}
|
|
wp_send_json_error();
|
|
}
|
|
|
|
public function get_product_attributes() {
|
|
$post_id = intval($_POST['post_id'] ?? 0);
|
|
|
|
// Check permissions
|
|
if (!current_user_can('edit_post', $post_id)) {
|
|
wp_send_json_error(['message' => 'Unauthorized']);
|
|
}
|
|
|
|
// Get attributes from legacy meta key
|
|
$data = get_post_meta($post_id, 'product_variation_attributes', true);
|
|
$json = is_string($data) ? json_decode($data, true) : $data;
|
|
|
|
if (is_array($json)) {
|
|
wp_send_json_success($json);
|
|
}
|
|
|
|
wp_send_json_success([]);
|
|
}
|
|
|
|
public function save_product_depracated($post_id, $post) {
|
|
// Verify nonce and permissions here if you have a nonce field (recommended)
|
|
|
|
// Avoid autosave and revision saves
|
|
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
|
|
if (wp_is_post_revision($post_id)) return;
|
|
|
|
// Check user permissions
|
|
if (!current_user_can('edit_post', $post_id)) return;
|
|
|
|
if (isset($_POST['product_variables'])) {
|
|
// Sanitize input (JSON string)
|
|
$product_variables_json = wp_unslash($_POST['product_variables']); // Remove slashes added by WP
|
|
$product_variables = json_decode($product_variables_json, true);
|
|
|
|
if (json_last_error() === JSON_ERROR_NONE && is_array($product_variables)) {
|
|
// Save the meta as JSON string or serialized array
|
|
update_post_meta($post_id, 'product_variables', $product_variables_json);
|
|
} else {
|
|
// Invalid JSON, optionally delete meta or handle error
|
|
delete_post_meta($post_id, 'product_variables');
|
|
}
|
|
}
|
|
}
|
|
|
|
function save_product( $post_id ) {
|
|
|
|
// 1. Verifikasi Nonce untuk keamanan
|
|
if ( ! isset( $_POST['_wpnonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ) ), 'update-post_' . $post_id ) ) {
|
|
return;
|
|
}
|
|
|
|
// 2. Abaikan jika ini adalah autosave
|
|
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
|
|
return;
|
|
}
|
|
|
|
// 3. Periksa izin pengguna
|
|
if ( ! current_user_can( 'edit_post', $post_id ) ) {
|
|
return;
|
|
}
|
|
|
|
// 4. Periksa apakah data 'product_variables' dikirim
|
|
if ( ! isset( $_POST['product_variables'] ) ) {
|
|
// Jika tidak ada data, mungkin kita ingin menghapus meta yang lama
|
|
delete_post_meta( $post_id, 'product_variables' );
|
|
return;
|
|
}
|
|
|
|
// 5. Ambil data, lakukan sanitasi dasar, dan simpan
|
|
$variations_data_json = $_POST['product_variables'];
|
|
|
|
// Sanitasi: wp_slash() penting untuk memastikan JSON string disimpan dengan benar,
|
|
// terutama jika mengandung karakter kutip.
|
|
$sanitized_variations_data = wp_unslash( $variations_data_json );
|
|
|
|
// Simpan data ke database. WordPress akan menangani serialisasi jika perlu.
|
|
update_post_meta( $post_id, 'product_variables', $sanitized_variations_data );
|
|
|
|
}
|
|
|
|
}
|