prefix . 'wheel_spins';
wheel_of_fortune_debug_log("add_spins: Attempting to add $spins spins for user $user_id to wheel $wheel_id.");
// Preveri, ali zapis že obstaja
$existing_id = $wpdb->get_var($wpdb->prepare(
"SELECT id FROM $table_spins WHERE user_id = %d AND wheel_id = %d",
$user_id, $wheel_id
));
if ($existing_id) {
// Zapis obstaja, posodobi spine
$result = $wpdb->query($wpdb->prepare(
"UPDATE $table_spins SET spins_available = spins_available + %d WHERE id = %d",
$spins, $existing_id
));
wheel_of_fortune_debug_log("add_spins: Updated existing record. Result: $result");
} else {
// Zapis ne obstaja, ustvari novega
$result = $wpdb->insert(
$table_spins,
[
'user_id' => $user_id,
'wheel_id' => $wheel_id,
'spins_available' => $spins,
'last_spin_date' => null
],
['%d', '%d', '%d', '%s']
);
wheel_of_fortune_debug_log("add_spins: Inserted new record. Result: $result");
}
return $result !== false;
}
/**
* Main plugin class
*/
class WheelOfFortune {
private static $instance = null;
public static function get_instance() {
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
private function __construct() {
// Register hooks
add_action('init', array($this, 'init'));
add_action('plugins_loaded', array($this, 'load_textdomain'));
register_activation_hook(WHEEL_OF_FORTUNE_PLUGIN_FILE, array($this, 'activate'));
register_deactivation_hook(WHEEL_OF_FORTUNE_PLUGIN_FILE, array($this, 'deactivate'));
add_action('admin_menu', array($this, 'admin_menu'));
add_action('rest_api_init', array($this, 'register_rest_routes'));
add_shortcode('wheel_of_fortune', array($this, 'shortcode'));
if ($this->is_woocommerce_active()) {
add_action('woocommerce_order_status_processing', array($this, 'assign_spins_on_purchase'));
add_action('woocommerce_order_status_completed', array($this, 'assign_spins_on_purchase'));
}
add_action('wp_enqueue_scripts', array($this, 'enqueue_frontend_assets'));
add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_assets'));
add_action('wp_ajax_wheel_get_prize_details', array($this, 'ajax_get_prize_details'));
add_action('wp_ajax_wheel_save_prize', array($this, 'ajax_save_prize'));
add_action('wp_ajax_wheel_delete_prize', array($this, 'ajax_delete_prize'));
add_action('wp_ajax_wheel_search_users', array($this, 'ajax_search_users'));
add_action('wp_ajax_wheel_add_spins', array($this, 'ajax_add_spins'));
add_action('wp_ajax_wheel_reset_all_spins', array($this, 'ajax_reset_all_spins'));
add_action('wp_ajax_wheel_get_product', array($this, 'ajax_get_product'));
add_action('wp_ajax_wheel_test_email', array($this, 'ajax_test_email'));
add_action('wp_ajax_wheel_get_prizes', array($this, 'ajax_get_prizes'));
add_action('wp_ajax_wof_delete_wheel_product', array($this, 'ajax_delete_wheel_product'));
add_action('wp_ajax_wof_update_wheel_product_spins', array($this, 'ajax_update_wheel_product_spins'));
// Vključi testno skripto za kupone
if (is_admin()) {
require_once WHEEL_OF_FORTUNE_PLUGIN_DIR . 'admin/coupon-test.php';
}
}
/**
* Assigns spins to a user upon a completed WooCommerce purchase.
* This method is hooked to 'woocommerce_order_status_processing' and 'woocommerce_order_status_completed'.
*
* @param int $order_id The ID of the WooCommerce order.
*/
public function assign_spins_on_purchase($order_id) {
wheel_of_fortune_debug_log("=== SPIN ASSIGNMENT START ===");
wheel_of_fortune_debug_log("Hook triggered for order ID: $order_id");
if (!$order_id) {
wheel_of_fortune_debug_log("No order ID provided. Exiting.");
return;
}
$order = wc_get_order($order_id);
if (!$order) {
wheel_of_fortune_debug_log("Could not get order object for ID: $order_id. Exiting.");
return;
}
$user_id = $order->get_user_id();
if (!$user_id) {
wheel_of_fortune_debug_log("Order #$order_id has no associated user ID. Exiting.");
return;
}
wheel_of_fortune_debug_log("Processing for User ID: $user_id");
global $wpdb;
$wheel_products_table = $wpdb->prefix . 'wheel_of_fortune_products';
$total_spins_to_add_by_wheel = [];
foreach ($order->get_items() as $item) {
$product_id = $item->get_product_id();
$quantity = $item->get_quantity();
wheel_of_fortune_debug_log("Checking product ID: $product_id (Quantity: $quantity)");
$wheel_product = $wpdb->get_row($wpdb->prepare(
"SELECT wheel_id, spins_per_purchase FROM $wheel_products_table WHERE product_id = %d",
$product_id
), ARRAY_A);
if ($wheel_product) {
$wheel_id = (int)$wheel_product['wheel_id'];
$spins_per_item = (int)$wheel_product['spins_per_purchase'];
$spins_for_this_item = $spins_per_item * $quantity;
wheel_of_fortune_debug_log("Product ID $product_id is a wheel product for Wheel ID: $wheel_id. Grants $spins_per_item spin(s) per purchase. Total for this item: $spins_for_this_item");
if (!isset($total_spins_to_add_by_wheel[$wheel_id])) {
$total_spins_to_add_by_wheel[$wheel_id] = 0;
}
$total_spins_to_add_by_wheel[$wheel_id] += $spins_for_this_item;
} else {
wheel_of_fortune_debug_log("Product ID $product_id is not a wheel product.");
}
}
if (!empty($total_spins_to_add_by_wheel)) {
// Prepreci veckratno dodeljevanje spinov
if (get_post_meta($order_id, '_wheel_spins_assigned', true)) {
wheel_of_fortune_debug_log("Spins for order #$order_id have already been assigned. Exiting.");
return;
}
wheel_of_fortune_debug_log("Total spins to add: " . print_r($total_spins_to_add_by_wheel, true));
$notes = [];
foreach ($total_spins_to_add_by_wheel as $wheel_id => $spins) {
if ($spins > 0) {
wheel_of_fortune_debug_log("Adding $spins spin(s) to user $user_id for wheel $wheel_id.");
if(wheel_of_fortune_add_spins($user_id, $spins, $wheel_id)){
$notes[] = sprintf(__('%d spin(s) for wheel #%d', 'wheel-of-fortune'), $spins, $wheel_id);
}
}
}
// Dodaj opombo k narocilu
if(!empty($notes)){
$order->add_order_note(sprintf(__('User awarded Wheel of Fortune spins: %s.', 'wheel-of-fortune'), implode(', ', $notes)));
update_post_meta($order_id, '_wheel_spins_assigned', true);
}
} else {
wheel_of_fortune_debug_log("No wheel products found in order #$order_id.");
}
wheel_of_fortune_debug_log("=== SPIN ASSIGNMENT END ===");
}
public function init() {
// Initialization code can go here
}
public function activate() {
error_log("Wheel of Fortune: Aktivacija plugina...");
$this->create_database_tables();
$this->run_migration();
$this->set_default_options();
$this->add_default_prizes();
// Debug: Preveri, ali se tabela za kolesa ustvari
global $wpdb;
$wheels_table = $wpdb->prefix . 'wof_wheels';
$wheel_products_table = $wpdb->prefix . 'wheel_of_fortune_products';
$wheels_exists = $wpdb->get_var("SHOW TABLES LIKE '$wheels_table'") == $wheels_table;
$products_exists = $wpdb->get_var("SHOW TABLES LIKE '$wheel_products_table'") == $wheel_products_table;
error_log("=== ACTIVATION DEBUG ===");
error_log("Wheels table exists: " . ($wheels_exists ? 'YES' : 'NO'));
error_log("Products table exists: " . ($products_exists ? 'YES' : 'NO'));
if (!$wheels_exists) {
error_log('Wheel of Fortune: Wheels table was not created properly during activation.');
} else {
error_log('Wheel of Fortune: Wheels table created successfully.');
}
flush_rewrite_rules();
error_log("Wheel of Fortune: Aktivacija končana.");
}
public function deactivate() {
flush_rewrite_rules();
}
public function load_textdomain() {
load_plugin_textdomain('wheel-of-fortune', false, dirname(plugin_basename(__FILE__)) . '/languages');
}
private function create_database_tables() {
global $wpdb;
$charset_collate = $wpdb->get_charset_collate();
// Ustvari tabelo za kolesa
$wheels_table = $wpdb->prefix . 'wof_wheels';
$wheel_products_table = $wpdb->prefix . 'wheel_of_fortune_products';
// Debug informacije za tabelo
error_log("=== TABLE DEBUG ===");
error_log("Wheels table: " . $wheels_table);
error_log("Products table: " . $wheel_products_table);
// Preveri, ali tabela obstaja
$wheels_table_exists = $wpdb->get_var("SHOW TABLES LIKE '$wheels_table'") == $wheels_table;
error_log("Wheels table exists: " . ($wheels_table_exists ? 'YES' : 'NO'));
$products_table_exists = $wpdb->get_var("SHOW TABLES LIKE '$wheel_products_table'") == $wheel_products_table;
error_log("Products table exists: " . ($products_table_exists ? 'YES' : 'NO'));
if ($wheels_table_exists) {
$wheels_table_structure = $wpdb->get_results("DESCRIBE $wheels_table");
error_log("Wheels table structure: " . print_r($wheels_table_structure, true));
}
if ($products_table_exists) {
$products_table_structure = $wpdb->get_results("DESCRIBE $wheel_products_table");
error_log("Products table structure: " . print_r($products_table_structure, true));
}
$sql_wheels = "CREATE TABLE $wheels_table (
id mediumint(9) NOT NULL AUTO_INCREMENT,
name varchar(255) NOT NULL,
slug varchar(100) NOT NULL,
created_at datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
PRIMARY KEY (id),
UNIQUE KEY slug (slug)
) $charset_collate;";
$sql_products = "CREATE TABLE $wheel_products_table (
id mediumint(9) NOT NULL AUTO_INCREMENT,
wheel_id mediumint(9) NOT NULL,
product_id bigint(20) NOT NULL,
spins_per_purchase int(11) NOT NULL DEFAULT 1,
created_at datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
UNIQUE KEY wheel_product (wheel_id, product_id)
) $charset_collate;";
// --- 2. Posodobljena tabela za nagrade ---
$table_prizes = $wpdb->prefix . 'wheel_prizes';
$sql_prizes = "CREATE TABLE $table_prizes (
id mediumint(9) NOT NULL AUTO_INCREMENT,
wheel_id mediumint(9) NOT NULL DEFAULT 1,
name varchar(255) NOT NULL,
description text DEFAULT '',
probability float NOT NULL,
is_active tinyint(1) NOT NULL DEFAULT 1,
image_url varchar(255) DEFAULT '',
email_subject varchar(255) DEFAULT '',
email_template text DEFAULT '',
redemption_code varchar(100) DEFAULT '',
is_discount tinyint(1) NOT NULL DEFAULT 0,
discount_value float DEFAULT 0,
PRIMARY KEY (id),
KEY wheel_id (wheel_id)
) $charset_collate;";
// --- 3. Posodobljena tabela za spine (NOVO - spini po kolesih) ---
$table_spins = $wpdb->prefix . 'wheel_spins';
$sql_spins = "CREATE TABLE $table_spins (
id mediumint(9) NOT NULL AUTO_INCREMENT,
user_id bigint(20) NOT NULL,
wheel_id mediumint(9) NOT NULL DEFAULT 1,
spins_available int(11) NOT NULL DEFAULT 0,
last_spin_date datetime DEFAULT NULL,
PRIMARY KEY (id),
UNIQUE KEY user_wheel (user_id, wheel_id),
KEY user_id (user_id),
KEY wheel_id (wheel_id)
) $charset_collate;";
// --- 4. Posodobljena tabela za log (NOVO - log po kolesih) ---
$table_log = $wpdb->prefix . 'wheel_log';
$sql_log = "CREATE TABLE $table_log (
id mediumint(9) NOT NULL AUTO_INCREMENT,
user_id bigint(20) NOT NULL,
wheel_id mediumint(9) NOT NULL DEFAULT 1,
prize_id mediumint(9) NOT NULL,
spin_date datetime NOT NULL,
redeemed tinyint(1) NOT NULL DEFAULT 0,
redemption_code varchar(100) DEFAULT '',
PRIMARY KEY (id),
KEY user_id (user_id),
KEY wheel_id (wheel_id),
KEY prize_id (prize_id)
) $charset_collate;";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql_wheels); // Dodajanje nove tabele
dbDelta($sql_products);
dbDelta($sql_prizes);
dbDelta($sql_spins);
dbDelta($sql_log);
// Debug: preveri, ali so se tabele ustvarile
$wheels_after = $wpdb->get_var("SHOW TABLES LIKE '$wheels_table'") == $wheels_table;
$products_after = $wpdb->get_var("SHOW TABLES LIKE '$wheel_products_table'") == $wheel_products_table;
error_log("After dbDelta - Wheels table exists: " . ($wheels_after ? 'YES' : 'NO'));
error_log("After dbDelta - Products table exists: " . ($products_after ? 'YES' : 'NO'));
if (!$wheels_after) {
error_log("Wheel of Fortune: Tabela $wheels_table se ni ustvarila!");
} else {
error_log("Wheel of Fortune: Tabela $wheels_table uspešno ustvarjena.");
}
if (!$products_after) {
error_log("Wheel of Fortune: Tabela $wheel_products_table se ni ustvarila!");
} else {
error_log("Wheel of Fortune: Tabela $wheel_products_table uspešno ustvarjena.");
}
}
private function run_migration() {
global $wpdb;
$wheels_table = $wpdb->prefix . 'wof_wheels';
$prizes_table = $wpdb->prefix . 'wheel_prizes';
$spins_table = $wpdb->prefix . 'wheel_spins';
$log_table = $wpdb->prefix . 'wheel_log';
// Debug informacije
error_log("=== MIGRATION DEBUG ===");
error_log("Wheels table: " . $wheels_table);
error_log("Prizes table: " . $prizes_table);
error_log("Spins table: " . $spins_table);
error_log("Log table: " . $log_table);
// 1. Preveri, če "Default" kolo že obstaja
$default_wheel_exists = $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM $wheels_table WHERE id = %d", 1));
error_log("Default wheel exists: " . $default_wheel_exists);
// 2. Če ne obstaja, ga ustvari
if (!$default_wheel_exists) {
error_log("Creating default wheel...");
$result = $wpdb->insert(
$wheels_table,
[
'id' => 1,
'name' => __('Default Wheel', 'wheel-of-fortune'),
'slug' => 'default',
'created_at' => current_time('mysql')
],
['%d', '%s', '%s', '%s']
);
error_log("Insert result: " . $result);
error_log("Last SQL query: " . $wpdb->last_query);
error_log("Last SQL error: " . $wpdb->last_error);
}
// 3. Posodobi obstoječe nagrade, da pripadajo privzetemu kolesu
$prizes_updated = $wpdb->query("UPDATE $prizes_table SET wheel_id = 1 WHERE wheel_id = 0 OR wheel_id IS NULL");
error_log("Prizes updated: " . $prizes_updated);
// 4. Migriraj obstoječe spine v novo strukturo
$existing_spins = $wpdb->get_results("SELECT user_id, meta_value as spins FROM {$wpdb->usermeta} WHERE meta_key = '_wheel_spins' AND meta_value > 0");
error_log("Existing spins found: " . count($existing_spins));
foreach ($existing_spins as $spin_data) {
// Preveri, če zapis že obstaja
$existing_record = $wpdb->get_var($wpdb->prepare(
"SELECT id FROM $spins_table WHERE user_id = %d AND wheel_id = 1",
$spin_data->user_id
));
if (!$existing_record) {
$result = $wpdb->insert(
$spins_table,
[
'user_id' => $spin_data->user_id,
'wheel_id' => 1,
'spins_available' => intval($spin_data->spins),
'last_spin_date' => current_time('mysql')
],
['%d', '%d', '%d', '%s']
);
error_log("Migrated spins for user {$spin_data->user_id}: " . $result);
}
}
// 5. Migriraj obstoječi log (če obstaja)
$log_updated = $wpdb->query("UPDATE $log_table SET wheel_id = 1 WHERE wheel_id = 0 OR wheel_id IS NULL");
error_log("Log updated: " . $log_updated);
// 6. Dodaj privzete nagrade, če jih ni
$existing_prizes = $wpdb->get_var("SELECT COUNT(*) FROM $prizes_table WHERE wheel_id = 1");
if ($existing_prizes == 0) {
$this->add_default_prizes();
}
}
private function set_default_options() {
$default_options = array(
'wheel_cooldown_minutes' => 0,
'wheel_max_spins' => 0,
'wheel_send_emails' => true, // E-pošta se vedno pošlje
'wheel_spin_products' => array(),
'wheel_smtp_enabled' => false,
'wheel_smtp_host' => '',
'wheel_smtp_port' => '587',
'wheel_smtp_username' => '',
'wheel_smtp_password' => '',
'wheel_smtp_encryption' => 'tls',
'wheel_email_from_name' => get_bloginfo('name'),
'wheel_email_from_email' => get_bloginfo('admin_email'),
);
foreach ($default_options as $option => $value) {
if (get_option($option) === false) {
add_option($option, $value);
}
}
$this->add_default_prizes();
}
private function add_default_prizes() {
global $wpdb;
$table_name = $wpdb->prefix . 'wheel_prizes';
$count = $wpdb->get_var("SELECT COUNT(*) FROM $table_name");
if ($count == 0) {
// Default prizes with wheel_id
$default_prizes = array(
['wheel_id' => 1, 'name' => '200k FTMO', 'description' => '200k FTMO voucher', 'probability' => 0.05, 'is_active' => 1],
['wheel_id' => 1, 'name' => '20% OFF', 'description' => '20% discount on your next purchase', 'probability' => 0.15, 'is_active' => 1],
['wheel_id' => 1, 'name' => '50k Funded7', 'description' => '50k Funded7 voucher', 'probability' => 0.10, 'is_active' => 1],
['wheel_id' => 1, 'name' => '15% OFF', 'description' => '15% discount on your next purchase', 'probability' => 0.20, 'is_active' => 1],
['wheel_id' => 1, 'name' => '100k TugeTrade', 'description' => '100k TugeTrade voucher', 'probability' => 0.10, 'is_active' => 1],
['wheel_id' => 1, 'name' => '5k Alpicap', 'description' => '5k Alpicap voucher', 'probability' => 0.15, 'is_active' => 1],
['wheel_id' => 1, 'name' => '30% OFF', 'description' => '30% discount on your next purchase', 'probability' => 0.10, 'is_active' => 1],
['wheel_id' => 1, 'name' => '200k FundedNext', 'description' => '200k FundedNext voucher', 'probability' => 0.05, 'is_active' => 1],
['wheel_id' => 1, 'name' => '75% OFF', 'description' => '75% discount on your next purchase', 'probability' => 0.05, 'is_active' => 1],
['wheel_id' => 1, 'name' => '200k FundingPips', 'description' => '200k FundingPips voucher', 'probability' => 0.05, 'is_active' => 1]
);
foreach ($default_prizes as $prize) {
$wpdb->insert($table_name, $prize);
}
}
}
public function admin_menu() {
add_menu_page(
__('Wheels of Fortune', 'wheel-of-fortune'),
__('Wheels', 'wheel-of-fortune'),
'manage_options',
'wof-wheels', // slug
array($this, 'wheels_page'), // callback
'dashicons-marker',
30
);
// Stran za urejanje posameznega kolesa (skrita iz glavnega menija, dostopna preko linkov)
add_submenu_page(
'wof-wheels', // parent slug
__('Edit Wheel', 'wheel-of-fortune'),
__('Edit Wheel', 'wheel-of-fortune'),
'manage_options',
'wof-edit-wheel',
array($this, 'edit_wheel_page')
);
// Statistika in uporabniki
add_submenu_page('wof-wheels', __('Statistics', 'wheel-of-fortune'), __('Statistics', 'wheel-of-fortune'), 'manage_options', 'wof-stats', array($this, 'stats_page'));
add_submenu_page('wof-wheels', __('Users & Spins', 'wheel-of-fortune'), __('Users & Spins', 'wheel-of-fortune'), 'manage_options', 'wof-users', array($this, 'users_page'));
}
public function wheels_page() {
require_once WHEEL_OF_FORTUNE_PLUGIN_DIR . 'admin/wheels-page.php';
}
public function edit_wheel_page() {
require_once WHEEL_OF_FORTUNE_PLUGIN_DIR . 'admin/edit-wheel-page.php';
}
public function prizes_page() {
// Ta stran ni več v uporabi, saj so nagrade urejene pod vsakim kolesom
// Pustimo jo zaenkrat prazno ali preusmerimo
echo "
" . __("This page is deprecated. Please manage prizes under a specific wheel.", "wheel-of-fortune") . "
";
}
public function stats_page() {
include WHEEL_OF_FORTUNE_PLUGIN_DIR . 'admin/stats-page.php';
}
public function users_page() {
include WHEEL_OF_FORTUNE_PLUGIN_DIR . 'admin/users-page.php';
}
public function register_rest_routes() {
register_rest_route('wheel-of-fortune/v1', '/spin', array('methods' => 'POST', 'callback' => array($this, 'process_wheel_spin'), 'permission_callback' => 'is_user_logged_in'));
register_rest_route('wheel-of-fortune/v1', '/test', array('methods' => 'GET', 'callback' => function() { return new WP_REST_Response(['success' => true, 'message' => 'REST API endpoint is working correctly.'], 200); }, 'permission_callback' => '__return_true'));
}
public function process_wheel_spin(WP_REST_Request $request) {
$user_id = get_current_user_id();
if ($user_id === 0) {
return new WP_Error('not_logged_in', __('You must be logged in to spin the wheel.', 'wheel-of-fortune'), ['status' => 401]);
}
$wheel_id = $request->get_param('wheel_id');
if (empty($wheel_id)) {
return new WP_Error('no_wheel_id', __('Wheel ID is missing.', 'wheel-of-fortune'), ['status' => 400]);
}
global $wpdb;
$spins_table = $wpdb->prefix . 'wheel_spins';
$user_spins = $wpdb->get_row($wpdb->prepare("SELECT spins_available FROM $spins_table WHERE user_id = %d AND wheel_id = %d", $user_id, $wheel_id));
$spins = $user_spins ? intval($user_spins->spins_available) : 0;
if ($spins <= 0) {
return new WP_Error('no_spins', __('You have no spins left.', 'wheel-of-fortune'), ['status' => 403]);
}
$prizes = $this->get_wheel_prizes($wheel_id);
if (empty($prizes)) {
return new WP_Error('no_prizes', __('No prizes available.', 'wheel-of-fortune'), ['status' => 500]);
}
// Uporabi delujočo logiko za izbiro nagrade
$prize = $this->select_random_prize($prizes);
$new_spins = $spins - 1;
$wpdb->update($spins_table, ['spins_available' => $new_spins, 'last_spin_date' => current_time('mysql')], ['user_id' => $user_id, 'wheel_id' => $wheel_id]);
$log_table = $wpdb->prefix . 'wheel_log';
$wpdb->insert($log_table, ['user_id' => $user_id, 'wheel_id' => $wheel_id, 'prize_id' => $prize['id'], 'spin_date' => current_time('mysql'), 'redeemed' => 0]);
$log_id = $wpdb->insert_id;
// Uporabi delujočo logiko za izračun kota
$degree = $this->calculate_prize_degree($prize['id'], $prizes);
$redemption_code = !empty($prize['redemption_code']) ? $prize['redemption_code'] : '';
$user = get_userdata($user_id);
if ($prize['is_discount'] && $prize['discount_value'] > 0 && class_exists('WooCommerce')) {
$coupon_code = 'WOF-' . uniqid() . '-' . $user->ID;
$coupon_id = $this->create_coupon_with_best_method($coupon_code, $user, $prize['discount_value']);
if ($coupon_id) {
$redemption_code = $coupon_code;
$wpdb->update($log_table, ['redemption_code' => $redemption_code], ['id' => $log_id]);
$prize['redemption_code'] = $redemption_code;
}
}
if (get_option('wheel_send_emails', true)) {
$this->send_prize_email($user_id, $prize);
}
$response_data = [ 'prize' => $prize, 'degree' => $degree, 'remaining_spins' => $new_spins, 'discount_code' => $redemption_code ];
return new WP_REST_Response(['success' => true, 'data' => $response_data], 200);
}
public function get_wheel_prizes($wheel_id = 1) {
global $wpdb;
$table_name = $wpdb->prefix . 'wheel_prizes';
return $wpdb->get_results($wpdb->prepare("SELECT * FROM $table_name WHERE wheel_id = %d AND is_active = 1 ORDER BY id ASC", $wheel_id), ARRAY_A);
}
private function select_random_prize($prizes) {
// Filter out prizes with 0 probability
$winnable_prizes = array_filter($prizes, function($prize) {
return isset($prize['probability']) && $prize['probability'] > 0;
});
// If no winnable prizes, return null or handle as an error
if (empty($winnable_prizes)) {
return end($prizes); // Or null, depending on desired behavior for no-win scenario
}
// Recalculate total probability for winnable prizes
$total_probability = array_sum(wp_list_pluck($winnable_prizes, 'probability'));
// Normalize probabilities if they don't sum to 1
if ($total_probability > 0) {
foreach ($winnable_prizes as &$prize) {
$prize['probability'] = $prize['probability'] / $total_probability;
}
unset($prize);
}
$rand = mt_rand(1, 10000) / 10000; // Increased precision
$cumulative = 0;
foreach ($winnable_prizes as $prize) {
$cumulative += $prize['probability'];
if ($rand <= $cumulative) {
return $prize;
}
}
return end($winnable_prizes); // Fallback to the last winnable prize
}
private function calculate_prize_degree($prize_id, $prizes) {
$prize_index = -1;
foreach ($prizes as $index => $prize) {
if ($prize['id'] == $prize_id) {
$prize_index = $index;
break;
}
}
if ($prize_index === -1) return 0;
$num_prizes = count($prizes);
$cx = 350;
$cy = 350;
$outer_radius = 330;
$inner_radius = 70;
$angle = 360 / $num_prizes;
$segment_size = $angle;
$prize_angle = $prize_index * $segment_size + ($segment_size / 2);
$target_stop_angle = 270 - $prize_angle;
$variation_range = $segment_size * 0.20;
$random_variation = mt_rand(-$variation_range, $variation_range);
$final_angle = $target_stop_angle + $random_variation;
$final_angle = fmod($final_angle, 360);
return ($final_angle < 0) ? $final_angle + 360 : $final_angle;
}
public function shortcode($atts) {
$atts = shortcode_atts(array(
'id' => '1', // Default to wheel ID 1 or slug 'default'
), $atts, 'wheel_of_fortune');
global $wpdb;
$wheels_table = $wpdb->prefix . 'wof_wheels';
$wheel_id_or_slug = $atts['id'];
if (is_numeric($wheel_id_or_slug)) {
$wheel = $wpdb->get_row($wpdb->prepare("SELECT * FROM $wheels_table WHERE id = %d", $wheel_id_or_slug), ARRAY_A);
} else {
$wheel = $wpdb->get_row($wpdb->prepare("SELECT * FROM $wheels_table WHERE slug = %s", $wheel_id_or_slug), ARRAY_A);
}
if (!$wheel) {
$wheel = $wpdb->get_row($wpdb->prepare("SELECT * FROM $wheels_table WHERE id = 1"), ARRAY_A);
if (!$wheel) {
return '';
}
}
$wheel_id = $wheel['id'];
if (!is_user_logged_in()) {
return '
' . sprintf(__('You need to log in to participate in this game.', 'wheel-of-fortune'), wp_login_url(get_permalink())) . '
';
}
$prizes = $this->get_wheel_prizes($wheel_id);
if (empty($prizes)) {
return '';
}
$this->enqueue_frontend_assets();
$user_id = get_current_user_id();
$spins_table = $wpdb->prefix . 'wheel_spins';
$spins_left = $wpdb->get_var($wpdb->prepare("SELECT spins_available FROM $spins_table WHERE user_id = %d AND wheel_id = %d", $user_id, $wheel_id));
$spins_left = ($spins_left === null) ? 0 : (int)$spins_left;
// Definiramo polje za prevode, da bo dostopno v PHP in JS
$l10n = [
'spin_button' => __('SPIN', 'wheel-of-fortune'),
'spinning' => __('Spinning...', 'wheel-of-fortune'),
'no_spins_left' => __('No More Spins', 'wheel-of-fortune'),
'congratulations' => __('Congratulations!', 'wheel-of-fortune'),
'you_won' => __('You won:', 'wheel-of-fortune'),
'close' => __('Close', 'wheel-of-fortune'),
'error' => __('Error', 'wheel-of-fortune'),
'discount_code_sent' => __('Your discount code has been sent to your email.', 'wheel-of-fortune'),
];
wp_localize_script('wheel-of-fortune-js', 'wof_data', array(
'ajax_url' => admin_url('admin-ajax.php'),
'rest_url' => get_rest_url(null, 'wheel-of-fortune/v1/spin'),
'nonce' => wp_create_nonce('wp_rest'),
'wheel_id' => $wheel_id,
'spins_left' => $spins_left,
'prizes' => $prizes,
'l10n' => $l10n // Uporabimo definirano polje
));
ob_start();
// Pass variables to the template
include(WHEEL_OF_FORTUNE_PLUGIN_DIR . 'public/shortcode-template.php');
return ob_get_clean();
}
public function enqueue_frontend_assets() {
wp_enqueue_style('wheel-of-fortune-css', WHEEL_OF_FORTUNE_PLUGIN_URL . 'assets/css/wheel.css', [], WHEEL_OF_FORTUNE_VERSION);
wp_enqueue_script('wheel-of-fortune-js', WHEEL_OF_FORTUNE_PLUGIN_URL . 'assets/js/wheel.js', ['jquery'], WHEEL_OF_FORTUNE_VERSION, true);
}
public function enqueue_admin_assets($hook) {
// Preveri, ali je trenutna stran ena od naših admin strani
if (strpos($hook, 'wof-') !== false || strpos($hook, 'wheel-') !== false) {
wp_enqueue_style('wheel-of-fortune-admin-css', WHEEL_OF_FORTUNE_PLUGIN_URL . 'assets/css/admin.css', [], WHEEL_OF_FORTUNE_VERSION);
wp_enqueue_script('wheel-of-fortune-admin-js', WHEEL_OF_FORTUNE_PLUGIN_URL . 'admin/js/admin.js', ['jquery'], WHEEL_OF_FORTUNE_VERSION, true);
wp_localize_script('wheel-of-fortune-admin-js', 'wheel_admin_nonce', array('_ajax_nonce' => wp_create_nonce('wheel_admin_nonce')));
wp_localize_script('wheel-of-fortune-admin-js', 'wheel_admin_i18n', [
'select_user' => __('Select a user', 'wheel-of-fortune'),
'select_user_and_spins' => __('Please select a user and enter the number of spins.', 'wheel-of-fortune'),
'confirm_reset_all_spins' => __('Are you sure you want to reset the spins for all users? This cannot be undone!', 'wheel-of-fortune'),
'enter_product_id_and_spins' => __('Please enter the product ID and number of spins.', 'wheel-of-fortune'),
'remove' => __('Remove', 'wheel-of-fortune'),
'no_products' => __('No products have been configured.', 'wheel-of-fortune'),
'product_not_found' => __('Product not found.', 'wheel-of-fortune'),
'error_finding_product' => __('Error finding product.', 'wheel-of-fortune'),
'active' => __('Active', 'wheel-of-fortune'),
'inactive' => __('Inactive', 'wheel-of-fortune'),
'confirm_delete_prize' => __('Are you sure you want to delete this prize?', 'wheel-of-fortune'),
'sending' => __('Sending...', 'wheel-of-fortune'),
'sending_test_email' => __('Sending test email...', 'wheel-of-fortune'),
'send_test_email' => __('Send Test Email', 'wheel-of-fortune'),
'error_sending_email' => __('Error sending email.', 'wheel-of-fortune'),
'enter_recipient_email' => __('Please enter a recipient email address.', 'wheel-of-fortune'),
]);
}
}
private function is_woocommerce_active() {
return in_array('woocommerce/woocommerce.php', apply_filters('active_plugins', get_option('active_plugins')));
}
/**
* Generates the SVG for the wheel with visible, curved, and auto-adjusting text.
* This version uses for superior text rendering on segments.
*
* @param array $prizes The array of prizes.
* @return string The generated SVG string.
*/
public function generate_wheel_svg($prizes) {
$num_prizes = count($prizes);
if ($num_prizes === 0) {
return '