diff --git a/code_export.txt b/code_export.txt
deleted file mode 100644
index 4f92533..0000000
--- a/code_export.txt
+++ /dev/null
@@ -1,6706 +0,0 @@
-"./admin/coupon-test.php" :
-"""
- false,
- 'message' => '',
- 'tests' => array(),
- 'working_method' => null
- );
-
- // Preveri, ali je WooCommerce aktiven
- if (!class_exists('WooCommerce')) {
- $results['message'] = 'WooCommerce ni aktiven. Prosim aktivirajte WooCommerce vtičnik.';
- return $results;
- }
-
- // Pridobi trenutnega uporabnika za testiranje
- $user = wp_get_current_user();
- if (!$user || !$user->exists()) {
- $results['message'] = 'Uporabnik ni prijavljen. Prijavite se kot administrator.';
- return $results;
- }
-
- // Nastavi testno kodo
- $test_code = 'TEST-' . strtoupper(substr(bin2hex(random_bytes(4)), 0, 8));
-
- // Test 1: Standardna WooCommerce API metoda
- $results['tests']['standard_api'] = self::test_standard_api($test_code . '-1', $user);
-
- // Test 2: Programsko ustvarjanje kupona
- $results['tests']['programmatic'] = self::test_programmatic($test_code . '-2', $user);
-
- // Test 3: Uporaba WC_Coupon z dodatnimi preverjanji
- $results['tests']['wc_coupon_extended'] = self::test_wc_coupon_extended($test_code . '-3', $user);
-
- // Test 4: Neposredno vstavljanje v podatkovno bazo
- $results['tests']['direct_db'] = self::test_direct_db($test_code . '-4', $user);
-
- // Počisti testne kupone
- self::cleanup_test_coupons($test_code);
-
- // Določi, katera metoda deluje
- foreach ($results['tests'] as $method => $test_result) {
- if ($test_result['success']) {
- $results['working_method'] = $method;
- $results['success'] = true;
- break;
- }
- }
-
- if ($results['success']) {
- $results['message'] = 'Našli smo delujočo metodo za ustvarjanje kuponov: ' . $results['working_method'];
- } else {
- $results['message'] = 'Nobena testirana metoda ne deluje. Preverite dnevnik napak za več informacij.';
- }
-
- return $results;
- }
-
- /**
- * Test 1: Standardna WooCommerce API metoda
- */
- private static function test_standard_api($code, $user) {
- $result = array(
- 'success' => false,
- 'message' => '',
- 'coupon_id' => 0
- );
-
- try {
- $coupon = new WC_Coupon();
- $coupon->set_code($code);
- $coupon->set_description('Test coupon');
- $coupon->set_discount_type('percent');
- $coupon->set_amount(10);
- $coupon->set_individual_use(true);
- $coupon->set_usage_limit(1);
- $coupon->set_usage_limit_per_user(1);
- $coupon->set_email_restrictions(array($user->user_email));
- $coupon_id = $coupon->save();
-
- if ($coupon_id) {
- $result['success'] = true;
- $result['message'] = 'Kupon uspešno ustvarjen z ID: ' . $coupon_id;
- $result['coupon_id'] = $coupon_id;
- } else {
- $result['message'] = 'Napaka: Kupon ni bil ustvarjen (save() je vrnil 0)';
- }
- } catch (Exception $e) {
- $result['message'] = 'Napaka: ' . $e->getMessage();
- }
-
- return $result;
- }
-
- /**
- * Test 2: Programsko ustvarjanje kupona
- */
- private static function test_programmatic($code, $user) {
- $result = array(
- 'success' => false,
- 'message' => '',
- 'coupon_id' => 0
- );
-
- try {
- // Ustvari nov post tipa shop_coupon
- $coupon_data = array(
- 'post_title' => $code,
- 'post_content' => '',
- 'post_status' => 'publish',
- 'post_author' => $user->ID,
- 'post_type' => 'shop_coupon'
- );
-
- $coupon_id = wp_insert_post($coupon_data);
-
- if (!is_wp_error($coupon_id)) {
- // Dodaj meta podatke za kupon
- update_post_meta($coupon_id, 'discount_type', 'percent');
- update_post_meta($coupon_id, 'coupon_amount', '10');
- update_post_meta($coupon_id, 'individual_use', 'yes');
- update_post_meta($coupon_id, 'usage_limit', '1');
- update_post_meta($coupon_id, 'usage_limit_per_user', '1');
- update_post_meta($coupon_id, 'customer_email', array($user->user_email));
-
- $result['success'] = true;
- $result['message'] = 'Kupon uspešno ustvarjen z ID: ' . $coupon_id;
- $result['coupon_id'] = $coupon_id;
- } else {
- $result['message'] = 'Napaka: ' . $coupon_id->get_error_message();
- }
- } catch (Exception $e) {
- $result['message'] = 'Napaka: ' . $e->getMessage();
- }
-
- return $result;
- }
-
- /**
- * Test 3: Uporaba WC_Coupon z dodatnimi preverjanji
- */
- private static function test_wc_coupon_extended($code, $user) {
- $result = array(
- 'success' => false,
- 'message' => '',
- 'coupon_id' => 0
- );
-
- try {
- // Preveri, ali koda že obstaja
- $existing_id = wc_get_coupon_id_by_code($code);
- if ($existing_id) {
- $result['message'] = 'Napaka: Kupon s to kodo že obstaja (ID: ' . $existing_id . ')';
- return $result;
- }
-
- // Ustvari nov kupon z dodatnimi preverjanji
- $coupon = new WC_Coupon();
- $coupon->set_code($code);
- $coupon->set_description('Test coupon with extended checks');
- $coupon->set_discount_type('percent');
- $coupon->set_amount(10);
- $coupon->set_individual_use(true);
- $coupon->set_usage_limit(1);
- $coupon->set_usage_limit_per_user(1);
- $coupon->set_email_restrictions(array($user->user_email));
-
- // Dodatna nastavitev
- $coupon->set_date_expires(strtotime('+7 days'));
-
- $coupon_id = $coupon->save();
-
- // Preveri, ali je kupon res ustvarjen
- if ($coupon_id) {
- $verification_id = wc_get_coupon_id_by_code($code);
- if ($verification_id && $verification_id == $coupon_id) {
- $result['success'] = true;
- $result['message'] = 'Kupon uspešno ustvarjen in preverjen z ID: ' . $coupon_id;
- $result['coupon_id'] = $coupon_id;
- } else {
- $result['message'] = 'Napaka: Kupon je bil ustvarjen, vendar preverjanje ni uspelo';
- }
- } else {
- $result['message'] = 'Napaka: Kupon ni bil ustvarjen (save() je vrnil 0)';
- }
- } catch (Exception $e) {
- $result['message'] = 'Napaka: ' . $e->getMessage();
- }
-
- return $result;
- }
-
- /**
- * Test 4: Neposredno vstavljanje v podatkovno bazo
- */
- private static function test_direct_db($code, $user) {
- $result = array(
- 'success' => false,
- 'message' => '',
- 'coupon_id' => 0
- );
-
- try {
- global $wpdb;
-
- // Ustvari nov post tipa shop_coupon
- $wpdb->insert(
- $wpdb->posts,
- array(
- 'post_title' => $code,
- 'post_name' => sanitize_title($code),
- 'post_content' => '',
- 'post_status' => 'publish',
- 'post_author' => $user->ID,
- 'post_type' => 'shop_coupon',
- 'post_date' => current_time('mysql'),
- 'post_date_gmt' => current_time('mysql', 1)
- )
- );
-
- $coupon_id = $wpdb->insert_id;
-
- if ($coupon_id) {
- // Dodaj meta podatke za kupon
- $meta_data = array(
- 'discount_type' => 'percent',
- 'coupon_amount' => '10',
- 'individual_use' => 'yes',
- 'usage_limit' => '1',
- 'usage_limit_per_user' => '1',
- 'customer_email' => serialize(array($user->user_email))
- );
-
- foreach ($meta_data as $meta_key => $meta_value) {
- $wpdb->insert(
- $wpdb->postmeta,
- array(
- 'post_id' => $coupon_id,
- 'meta_key' => $meta_key,
- 'meta_value' => $meta_value
- )
- );
- }
-
- $result['success'] = true;
- $result['message'] = 'Kupon uspešno ustvarjen neposredno v bazi z ID: ' . $coupon_id;
- $result['coupon_id'] = $coupon_id;
- } else {
- $result['message'] = 'Napaka: Kupon ni bil ustvarjen v bazi';
- }
- } catch (Exception $e) {
- $result['message'] = 'Napaka: ' . $e->getMessage();
- }
-
- return $result;
- }
-
- /**
- * Počisti testne kupone
- */
- private static function cleanup_test_coupons($prefix) {
- global $wpdb;
-
- // Poišči vse testne kupone
- $test_coupons = $wpdb->get_results(
- $wpdb->prepare(
- "SELECT ID FROM {$wpdb->posts} WHERE post_title LIKE %s AND post_type = 'shop_coupon'",
- $prefix . '%'
- )
- );
-
- // Izbriši najdene kupone
- foreach ($test_coupons as $coupon) {
- wp_delete_post($coupon->ID, true);
- }
- }
-}
-
-/**
- * Funkcija za obdelavo AJAX zahteve za testiranje kuponov
- */
-function wheel_test_coupons_ajax() {
- // Preveri varnostno kodo
- check_ajax_referer('wheel_admin_nonce', 'nonce');
-
- // Preveri pravice
- if (!current_user_can('manage_options')) {
- wp_send_json_error(array('message' => 'Nimate pravic za izvedbo tega dejanja.'));
- return;
- }
-
- // Zaženi teste
- $results = WheelCouponTester::run_tests();
-
- // Vrni rezultate
- if ($results['success']) {
- wp_send_json_success($results);
- } else {
- wp_send_json_error($results);
- }
-}
-add_action('wp_ajax_wheel_test_coupons', 'wheel_test_coupons_ajax');
-
-/**
- * Shrani najboljšo metodo za ustvarjanje kuponov
- */
-function wheel_save_best_coupon_method() {
- // Preveri varnostno kodo
- check_ajax_referer('wheel_admin_nonce', 'nonce');
-
- // Preveri pravice
- if (!current_user_can('manage_options')) {
- wp_send_json_error(array('message' => 'Nimate pravic za izvedbo tega dejanja.'));
- return;
- }
-
- // Preveri, ali je metoda podana
- if (!isset($_POST['method']) || empty($_POST['method'])) {
- wp_send_json_error(array('message' => 'Metoda ni podana.'));
- return;
- }
-
- $method = sanitize_text_field($_POST['method']);
- $valid_methods = array('standard_api', 'programmatic', 'wc_coupon_extended', 'direct_db');
-
- if (!in_array($method, $valid_methods)) {
- wp_send_json_error(array('message' => 'Neveljavna metoda.'));
- return;
- }
-
- // Shrani najboljšo metodo
- update_option('wheel_best_coupon_method', $method);
-
- wp_send_json_success(array(
- 'message' => sprintf(__('Metoda %s je bila uspešno shranjena kot najboljša metoda za ustvarjanje kuponov.', 'wheel-of-fortune'), $method)
- ));
-}
-add_action('wp_ajax_wheel_save_best_coupon_method', 'wheel_save_best_coupon_method'); """
-
-
-"./admin/edit-wheel-page.php" :
-"""
-prefix . 'wheel_prizes';
-
- $wheel_id = isset($_POST['wheel_id']) ? intval($_POST['wheel_id']) : 0;
- $name = isset($_POST['prize_name']) ? sanitize_text_field($_POST['prize_name']) : '';
- $description = isset($_POST['prize_description']) ? sanitize_textarea_field($_POST['prize_description']) : '';
- $probability = isset($_POST['prize_probability']) ? floatval($_POST['prize_probability']) : 0;
- $is_active = isset($_POST['prize_is_active']) ? 1 : 0;
- $redemption_code = isset($_POST['prize_redemption_code']) ? sanitize_text_field($_POST['prize_redemption_code']) : '';
- $is_discount = isset($_POST['prize_is_discount']) ? 1 : 0;
- $discount_value = isset($_POST['prize_discount_value']) ? floatval($_POST['prize_discount_value']) : 0;
- $email_subject = isset($_POST['prize_email_subject']) ? sanitize_text_field($_POST['prize_email_subject']) : '';
- $email_template = isset($_POST['prize_email_template']) ? wp_kses_post($_POST['prize_email_template']) : '';
- $is_try_again = isset($_POST['prize_is_try_again']) ? 1 : 0;
-
- if (!empty($name) && $wheel_id > 0) {
- $result = $wpdb->insert(
- $prizes_table,
- [
- 'wheel_id' => $wheel_id,
- 'name' => $name,
- 'description' => $description,
- 'probability' => $probability,
- 'is_active' => $is_active,
- 'redemption_code' => $redemption_code,
- 'is_discount' => $is_discount,
- 'discount_value' => $discount_value,
- 'email_subject' => $email_subject,
- 'email_template' => $email_template,
- 'is_try_again' => $is_try_again
- ],
- ['%d', '%s', '%s', '%f', '%d', '%s', '%d', '%f', '%s', '%s', '%d']
- );
-
- if ($result !== false) {
- echo '
' . __('Prize added successfully!', 'wheel-of-fortune') . '
';
- } else {
- echo '' . __('Error adding prize. Please try again.', 'wheel-of-fortune') . '
';
- }
- } else {
- echo '' . __('Please fill in all required fields.', 'wheel-of-fortune') . '
';
- }
- } elseif ($_POST['action'] === 'edit_prize' && check_admin_referer('wheel_prizes_nonce')) {
- global $wpdb;
- $prizes_table = $wpdb->prefix . 'wheel_prizes';
-
- $prize_id = isset($_POST['prize_id']) ? intval($_POST['prize_id']) : 0;
- $wheel_id = isset($_POST['wheel_id']) ? intval($_POST['wheel_id']) : 0;
- $name = isset($_POST['prize_name']) ? sanitize_text_field($_POST['prize_name']) : '';
- $description = isset($_POST['prize_description']) ? sanitize_textarea_field($_POST['prize_description']) : '';
- $probability = isset($_POST['prize_probability']) ? floatval($_POST['prize_probability']) : 0;
- $is_active = isset($_POST['prize_is_active']) ? 1 : 0;
- $redemption_code = isset($_POST['prize_redemption_code']) ? sanitize_text_field($_POST['prize_redemption_code']) : '';
- $is_discount = isset($_POST['prize_is_discount']) ? 1 : 0;
- $discount_value = isset($_POST['prize_discount_value']) ? floatval($_POST['prize_discount_value']) : 0;
- $email_subject = isset($_POST['prize_email_subject']) ? sanitize_text_field($_POST['prize_email_subject']) : '';
- $email_template = isset($_POST['prize_email_template']) ? wp_kses_post($_POST['prize_email_template']) : '';
- $is_try_again = isset($_POST['prize_is_try_again']) ? 1 : 0;
-
- if (!empty($name) && $prize_id > 0 && $wheel_id > 0) {
- $result = $wpdb->update(
- $prizes_table,
- [
- 'wheel_id' => $wheel_id,
- 'name' => $name,
- 'description' => $description,
- 'probability' => $probability,
- 'is_active' => $is_active,
- 'redemption_code' => $redemption_code,
- 'is_discount' => $is_discount,
- 'discount_value' => $discount_value,
- 'email_subject' => $email_subject,
- 'email_template' => $email_template,
- 'is_try_again' => $is_try_again
- ],
- ['id' => $prize_id],
- ['%d', '%s', '%s', '%f', '%d', '%s', '%d', '%f', '%s', '%s', '%d'],
- ['%d']
- );
-
- if ($result !== false) {
- echo '' . __('Prize updated successfully!', 'wheel-of-fortune') . '
';
- } else {
- echo '' . __('Error updating prize. Please try again.', 'wheel-of-fortune') . '
';
- }
- } else {
- echo '' . __('Please fill in all required fields.', 'wheel-of-fortune') . '
';
- }
- }
-}
-
-if (
- $_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) &&
- in_array($_POST['action'], ['add_wheel_product', 'delete_wheel_product'])
-) {
- global $wpdb;
- $wheels_table = $wpdb->prefix . 'wof_wheels';
- $wheel_products_table = $wpdb->prefix . 'wheel_of_fortune_products';
- if ($_POST['action'] === 'add_wheel_product' && check_admin_referer('wheel_products_nonce')) {
- $wheel_id = isset($_POST['wheel_id']) ? intval($_POST['wheel_id']) : 0;
- $product_id = isset($_POST['product_id']) ? intval($_POST['product_id']) : 0;
- $spins_per_purchase = isset($_POST['spins_per_purchase']) ? intval($_POST['spins_per_purchase']) : 1;
-
- // Debug informacije
- error_log("=== WHEEL PRODUCT DEBUG ===");
- error_log("POST data: " . print_r($_POST, true));
- error_log("Wheel ID: " . $wheel_id);
- error_log("Product ID: " . $product_id);
- error_log("Spins per purchase: " . $spins_per_purchase);
- error_log("Table name: " . $wheel_products_table);
-
- // Preveri, ali tabela obstaja
- $table_exists = $wpdb->get_var("SHOW TABLES LIKE '$wheel_products_table'") == $wheel_products_table;
- error_log("Table exists: " . ($table_exists ? 'YES' : 'NO'));
-
- if (!$table_exists) {
- error_log("ERROR: Tabela $wheel_products_table ne obstaja!");
- echo '' . __('Napaka: Tabela za produkte ne obstaja. Prosimo, deaktivirajte in ponovno aktivirajte plugin.', 'wheel-of-fortune') . '
';
- return;
- }
-
- if ($wheel_id > 0 && $product_id > 0 && $spins_per_purchase > 0) {
- // Preveri, ali kolo obstaja
- $wheel_exists = $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM $wheels_table WHERE id = %d", $wheel_id));
- error_log("Wheel exists: " . $wheel_exists);
-
- if (!$wheel_exists) {
- error_log("ERROR: Kolo z ID $wheel_id ne obstaja!");
- echo '' . __('Napaka: Izbrano kolo ne obstaja.', 'wheel-of-fortune') . '
';
- return;
- }
-
- // Preveri, ali produkt obstaja
- if (class_exists('WooCommerce')) {
- $product = wc_get_product($product_id);
- if (!$product) {
- error_log("ERROR: Produkt z ID $product_id ne obstaja!");
- echo '' . __('Napaka: Izbrani produkt ne obstaja.', 'wheel-of-fortune') . '
';
- return;
- }
- }
-
- $data = [
- 'wheel_id' => $wheel_id,
- 'product_id' => $product_id,
- 'spins_per_purchase' => $spins_per_purchase
- ];
-
- error_log("Data to insert: " . print_r($data, true));
-
- // Preveri, ali je produkt že povezan s tem kolesom
- $existing_product = $wpdb->get_var($wpdb->prepare(
- "SELECT id FROM $wheel_products_table WHERE wheel_id = %d AND product_id = %d",
- $wheel_id, $product_id
- ));
-
- if ($existing_product) {
- error_log("Product already exists for this wheel, updating...");
- } else {
- error_log("Adding new product to wheel...");
- }
-
- $result = $wpdb->replace(
- $wheel_products_table,
- $data,
- ['%d', '%d', '%d']
- );
-
- error_log("SQL result: " . $result);
- error_log("Last SQL query: " . $wpdb->last_query);
- error_log("Last SQL error: " . $wpdb->last_error);
-
- if ($result !== false) {
- echo '' . __('Produkt je bil uspešno dodan ali posodobljen.', 'wheel-of-fortune') . '
';
- } else {
- echo '' . __('Napaka pri dodajanju produkta. Preveri vnos.', 'wheel-of-fortune') . '
';
- }
- } else {
- error_log("Validation failed - Wheel ID: $wheel_id, Product ID: $product_id, Spins: $spins_per_purchase");
- echo '' . __('Napaka pri dodajanju produkta. Preveri vnos.', 'wheel-of-fortune') . '
';
- }
- } elseif ($_POST['action'] === 'delete_wheel_product' && check_admin_referer('wheel_products_nonce')) {
- $id = isset($_POST['id']) ? intval($_POST['id']) : 0;
- if ($id > 0) {
- $wpdb->delete($wheel_products_table, ['id' => $id], ['%d']);
- echo '' . __('Produkt je bil izbrisan.', 'wheel-of-fortune') . '
';
- }
- }
-}
-
-global $wpdb;
-$wheels_table = $wpdb->prefix . 'wof_wheels';
-$prizes_table = $wpdb->prefix . 'wheel_prizes';
-
-// Get the current wheel ID from URL
-$wheel_id = isset($_GET['wheel_id']) ? intval($_GET['wheel_id']) : 0;
-
-// Fetch wheel data
-$wheel = $wpdb->get_row($wpdb->prepare("SELECT * FROM $wheels_table WHERE id = %d", $wheel_id), ARRAY_A);
-
-if (!$wheel) {
- echo '' . __('Wheel not found.', 'wheel-of-fortune') . '
';
- return;
-}
-
-// Fetch prizes for this specific wheel
-$prizes = $wpdb->get_results($wpdb->prepare("SELECT * FROM $prizes_table WHERE wheel_id = %d ORDER BY id ASC", $wheel_id), ARRAY_A);
-$total_probability = array_sum(wp_list_pluck($prizes, 'probability'));
-
-// Fetch povezane produkte za to kolo
-$wheel_products_table = $wpdb->prefix . 'wheel_of_fortune_products';
-$products = $wpdb->get_results($wpdb->prepare("SELECT * FROM $wheel_products_table WHERE wheel_id = %d", $wheel_id), ARRAY_A);
-
-// Pridobi vse WooCommerce produkte za dropdown
-if (class_exists('WooCommerce')) {
- $all_products = wc_get_products(array('limit' => -1, 'status' => 'publish'));
-} else {
- $all_products = array();
-}
-
-?>
-
-
-
-
←
-
-
-
-
-
-
-
-
-
- 1): ?>
-
' . esc_html($total_probability) . ''); ?>
- 0 && $total_probability < 1): ?>
-
' . esc_html($total_probability) . ''); ?>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- get_name()) : esc_html($prod['product_id']); ?>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- """
-
-
-"./admin/js/admin.js" :
-"""
-jQuery(document).ready(function($) {
- 'use strict';
-
- // Only run on our plugin's admin pages
- if (!$('.wheel-admin-page').length) {
- return;
- }
-
- // Tab navigation
- $('.nav-tab').on('click', function(e) {
- e.preventDefault();
- $('.nav-tab').removeClass('nav-tab-active');
- $(this).addClass('nav-tab-active');
- $('.wheel-tab-content').hide();
- $('#' + $(this).data('target')).show();
- });
-
- // --- Modal Logic ---
- var modal = $('#edit-prize-modal');
- var span = modal.find('.close');
-
- // Close modal
- span.on('click', function() {
- modal.hide();
- });
- $(window).on('click', function(event) {
- if ($(event.target).is(modal)) {
- modal.hide();
- }
- });
-
- // --- Add New Prize ---
- $('.add-new-prize').on('click', function(e) {
- e.preventDefault();
-
- // Clear form for new prize
- $('#edit-prize-form')[0].reset();
- $('#edit-prize-id').val(''); // Clear prize ID for new prize
-
- // Get wheel_id from the modal's data attribute
- var wheelId = $('#edit-prize-modal').data('wheel-id');
- $('#edit-wheel-id').val(wheelId);
-
- console.log('Opening modal for new prize with wheel_id:', wheelId);
-
- modal.show();
- });
-
- // --- Edit Prize ---
- $('.edit-prize').on('click', function(e) {
- e.preventDefault();
- var prizeId = $(this).data('id');
-
- // AJAX call to get prize details
- $.post(ajaxurl, {
- action: 'wheel_get_prize_details',
- _ajax_nonce: wheel_admin_nonce._ajax_nonce,
- prize_id: prizeId
- }, function(response) {
- if (response.success) {
- var prize = response.data;
- // Populate form
- $('#edit-prize-id').val(prize.id);
- $('#edit-wheel-id').val(prize.wheel_id); // wheel_id je že v formi
- $('#edit-prize-name').val(prize.name);
- $('#edit-prize-description').val(prize.description);
- $('#edit-prize-probability').val(prize.probability);
- $('#edit-prize-is-active').prop('checked', parseInt(prize.is_active, 10));
- $('#edit-prize-redemption-code').val(prize.redemption_code);
- $('#edit-prize-is-discount').prop('checked', parseInt(prize.is_discount, 10));
- $('#edit-prize-discount-value').val(prize.discount_value);
- $('#edit-prize-email-subject').val(prize.email_subject);
- $('#edit-prize-email-template').val(prize.email_template);
- $('#edit-prize-is-try-again').prop('checked', parseInt(prize.is_try_again, 10));
-
- modal.show();
- } else {
- alert(response.data.message || 'An error occurred.');
- }
- }).fail(function() {
- alert('An error occurred while loading prize details.');
- });
- });
-
- // --- Save Prize (via AJAX) ---
- $('#edit-prize-form').on('submit', function(e) {
- e.preventDefault();
-
- // Pripravimo podatke iz forme
- const formData = {
- action: 'wheel_save_prize',
- _ajax_nonce: wheel_admin_nonce._ajax_nonce,
- wheel_id: $('#edit-wheel-id').val(), // **KLJUČNO: pošljemo wheel_id**
- prize_id: $('#edit-prize-id').val(),
- name: $('#edit-prize-name').val(),
- description: $('#edit-prize-description').val(),
- probability: $('#edit-prize-probability').val(),
- is_active: $('#edit-prize-is-active').is(':checked') ? 1 : 0,
- redemption_code: $('#edit-prize-redemption-code').val(),
- is_discount: $('#edit-prize-is-discount').is(':checked') ? 1 : 0,
- discount_value: $('#edit-prize-discount-value').val(),
- email_subject: $('#edit-prize-email-subject').val(),
- email_template: $('#edit-prize-email-template').val(),
- is_try_again: $('#edit-prize-is-try-again').is(':checked') ? 1 : 0,
- };
-
- // Debug: preveri wheel_id
- console.log('Wheel ID from form:', formData.wheel_id);
- console.log('Form data:', formData);
-
- // Validate form fields
- if (!formData.name) {
- alert('Prize name is required.');
- return;
- }
- if (isNaN(parseFloat(formData.probability)) || formData.probability < 0 || formData.probability > 1) {
- alert('Probability must be a number between 0 and 1.');
- return;
- }
- if (!formData.wheel_id || formData.wheel_id == 0) {
- alert('Wheel ID is missing. Please refresh the page and try again.');
- return;
- }
-
- // AJAX call to save the prize
- $.post(ajaxurl, formData, function(response) {
- console.log('Server response:', response);
- if (response.success) {
- alert(response.data.message);
- modal.hide();
- location.reload(); // Refresh page to see changes
- } else {
- alert(response.data.message || 'An error occurred while saving.');
- }
- }).fail(function(xhr, status, error) {
- console.error('AJAX error:', {xhr: xhr, status: status, error: error});
- alert('A critical error occurred. Please try again.');
- });
- });
-
- // --- Delete Prize ---
- $('.delete-prize').on('click', function(e) {
- e.preventDefault();
-
- if (confirm('Are you sure you want to delete this prize?')) {
- var prizeId = $(this).data('id');
-
- $.post(ajaxurl, {
- action: 'wheel_delete_prize',
- _ajax_nonce: wheel_admin_nonce._ajax_nonce,
- prize_id: prizeId
- }, function(response) {
- if (response.success) {
- alert(response.data.message);
- location.reload();
- } else {
- alert(response.data.message || 'An error occurred.');
- }
- });
- }
- });
-
- // --- SETTINGS PAGE - TEST EMAIL ---
- if ($('#test-email-button').length) {
- $('#test-email-button').on('click', function(e) {
- e.preventDefault();
-
- const button = $(this);
- const resultDiv = $('#test-email-result');
- const recipientEmail = $('#test-email-recipient').val();
- const spinner = button.siblings('.spinner');
-
- if (!recipientEmail) {
- alert(wheel_admin_i18n.enter_recipient_email || 'Please enter a recipient email address.');
- return;
- }
-
- button.prop('disabled', true);
- spinner.addClass('is-active');
- resultDiv.slideUp().removeClass('notice notice-success notice-error is-dismissible').empty();
-
- // Collect all settings from the form to test unsaved values
- const data = {
- action: 'wheel_test_email',
- _ajax_nonce: wheel_admin_nonce._ajax_nonce,
- recipient_email: recipientEmail,
- smtp_enabled: $('#wheel_smtp_enabled').is(':checked') ? '1' : '0',
- smtp_host: $('#wheel_smtp_host').val(),
- smtp_port: $('#wheel_smtp_port').val(),
- smtp_encryption: $('#wheel_smtp_encryption').val(),
- smtp_username: $('#wheel_smtp_username').val(),
- smtp_password: $('#wheel_smtp_password').val(),
- from_name: $('#wheel_email_from_name').val(),
- from_email: $('#wheel_email_from_email').val(),
- };
-
- $.ajax({
- url: ajaxurl,
- method: 'POST',
- data: data,
- success: function(response) {
- if (response.success) {
- resultDiv.addClass('notice notice-success is-dismissible').html('' + response.data.message + '
').slideDown();
- } else {
- const errorMessage = response.data.message || (wheel_admin_i18n.error_sending_email || 'An unknown error occurred.');
- resultDiv.addClass('notice notice-error is-dismissible').html('' + errorMessage + '
').slideDown();
- }
- },
- error: function(xhr) {
- let errorMessage = wheel_admin_i18n.error_sending_email || 'A communication error occurred with the server.';
- if(xhr.responseJSON && xhr.responseJSON.data && xhr.responseJSON.data.message) {
- errorMessage = xhr.responseJSON.data.message;
- }
- resultDiv.addClass('notice notice-error is-dismissible').html('' + errorMessage + '
').slideDown();
- },
- complete: function() {
- button.prop('disabled', false);
- spinner.removeClass('is-active');
- }
- });
- });
- }
-
- // Dodajanje/brisanje produkta za spine
- $('#add-product-button').on('click', function() {
- const button = $(this);
- const productId = $('#new-product-id').val();
- const spins = $('#new-product-spins').val();
- const wheelId = button.data('wheel-id');
-
- if (!productId || !spins) {
- alert('Prosim vnesite ID produkta in število spinov.');
- return;
- }
-
- $.ajax({
- url: ajaxurl,
- method: 'POST',
- data: {
- action: 'ajax_update_wheel_product_spins',
- _ajax_nonce: wheel_admin_nonce._ajax_nonce,
- wheel_id: wheelId,
- product_id: productId,
- spins: spins
- },
- success: function(response) {
- if(response.success) {
- location.reload();
- } else {
- alert('Napaka: ' + response.data.message);
- }
- },
- error: function() {
- alert('Prišlo je do kritične napake.');
- }
- });
- });
-
- $('.delete-product-button').on('click', function() {
- if(!confirm('Ste prepričani?')) return;
-
- const button = $(this);
- const productId = button.data('product-id');
- const wheelId = button.data('wheel-id');
-
- $.ajax({
- url: ajaxurl,
- method: 'POST',
- data: {
- action: 'ajax_delete_wheel_product',
- _ajax_nonce: wheel_admin_nonce._ajax_nonce,
- wheel_id: wheelId,
- product_id: productId
- },
- success: function(response) {
- if(response.success) {
- location.reload();
- } else {
- alert('Napaka: ' + response.data.message);
- }
- },
- error: function() {
- alert('Prišlo je do kritične napake.');
- }
- });
- });
-});"""
-
-
-"./admin/js/wheel.js" :
-"""
-/**
- * Wheel of Fortune - JavaScript for wheel functionality
- * Robust, smooth animation using requestAnimationFrame and easing functions.
- */
-jQuery(document).ready(function($) {
- // Check if wheelSettings are available
- if (typeof wheelSettings === 'undefined') {
- console.error('Wheel of Fortune: Settings (wheelSettings) are not defined. Please check the plugin setup.');
- return;
- }
-
- // Elements
- const wheel = $('.wheel');
- const button = $('.wheel-button');
- const resultDiv = $('.wheel-result');
- const spinsCounter = $('.wheel-spins-counter span');
-
- // Animation state
- let isSpinning = false;
- let animationFrameId = null;
- let accumulatedRotation = 0; // Total rotation is maintained between spins
-
- // Animation settings
- const spinDuration = 8000; // 8 seconds for a more dramatic effect
- const spinRotations = 5; // Number of full rotations before stopping
-
- /**
- * Easing function (cubic-bezier out) for natural deceleration
- * @param {number} t - Current time (0 to 1)
- * @returns {number} - Animation progress (0 to 1)
- */
- function easeOutCubic(t) {
- return 1 - Math.pow(1 - t, 3);
- }
-
- /**
- * Main animation loop
- * @param {number} startTime - Animation start time
- * @param {number} startRotation - Starting rotation angle
- * @param {number} rotationAmount - Total rotation to perform for this spin
- */
- function animateWheel(startTime, startRotation, rotationAmount) {
- const currentTime = Date.now();
- const elapsedTime = currentTime - startTime;
-
- if (elapsedTime >= spinDuration) {
- wheel.css('transform', `rotate(${startRotation + rotationAmount}deg)`);
- accumulatedRotation = startRotation + rotationAmount; // Update the final position
- finishSpin();
- return;
- }
-
- // Calculate progress within the animation duration
- const timeProgress = elapsedTime / spinDuration;
- // Apply the easing function to determine the rotation progress
- const rotationProgress = easeOutCubic(timeProgress);
-
- // Calculate the current rotation
- const newRotation = startRotation + (rotationAmount * rotationProgress);
- wheel.css('transform', `rotate(${newRotation}deg)`);
-
- // Continue to the next frame
- animationFrameId = requestAnimationFrame(() => animateWheel(startTime, startRotation, rotationAmount));
- }
-
- /**
- * Function to execute after the spin animation is complete
- */
- function finishSpin() {
- // Display the result with a slight delay for better effect
- setTimeout(() => {
- const prize = window.spinResult.prize;
- resultDiv.html(`Congratulations! You've won: ${prize.name}
`);
- resultDiv.addClass('win').fadeIn(300);
-
- isSpinning = false;
-
- // Re-enable the button if there are remaining spins
- if (window.spinResult.remaining_spins > 0) {
- button.prop('disabled', false);
- } else {
- button.prop('disabled', true);
- }
- }, 500); // 500ms pause before showing the result
- }
-
- // Spin button click handler
- button.on('click', function() {
- if (isSpinning) return;
-
- isSpinning = true;
- button.prop('disabled', true);
- resultDiv.hide().removeClass('win error');
-
- $.ajax({
- url: wheelSettings.ajaxUrl,
- method: 'POST',
- data: {
- action: 'wheel_spin',
- nonce: wheelSettings.nonce
- },
- beforeSend: function(xhr) {
- xhr.setRequestHeader('X-WP-Nonce', wheelSettings.nonce);
- },
- success: function(response) {
- if (response.success) {
- window.spinResult = response;
-
- // The target angle (0-360) for the wheel to stop at, sent by the server.
- const targetAngle = response.degree;
-
- // Add several full rotations for a nice visual effect.
- const fullSpins = spinRotations * 360;
-
- // Get the current angle of the wheel, normalized to 0-360 degrees.
- const currentAngle = accumulatedRotation % 360;
-
- // Calculate the rotation needed to get from the current angle to the target angle.
- // We must always rotate forward (clockwise, positive rotation).
- let rotationToTarget = targetAngle - currentAngle;
- if (rotationToTarget < 0) {
- rotationToTarget += 360;
- }
-
- // The total amount of rotation for this spin.
- const rotationAmount = fullSpins + rotationToTarget;
-
- const startRotation = accumulatedRotation;
-
- // Start the animation. The function will rotate the wheel by 'rotationAmount' degrees.
- animateWheel(Date.now(), startRotation, rotationAmount);
-
- // Update the remaining spins counter on the screen.
- spinsCounter.text(response.remaining_spins);
- } else {
- // Display error from server
- resultDiv.html(`${response.data.message || 'An error occurred.'}
`);
- resultDiv.addClass('error').fadeIn(300);
- isSpinning = false;
- button.prop('disabled', false);
- }
- },
- error: function(xhr) {
- const errorMsg = xhr.responseJSON ? xhr.responseJSON.message : 'A communication error occurred.';
- resultDiv.html(`${errorMsg}
`);
- resultDiv.addClass('error').fadeIn(300);
- isSpinning = false;
- button.prop('disabled', false);
- }
- });
- });
-
- // Initialization
- if (wheelSettings.remainingSpins <= 0) {
- button.prop('disabled', true);
- }
-});"""
-
-
-"./admin/partials/prize-form-fields.php" :
-"""
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- """
-
-
-"./admin/settings-page.php" :
-"""
- $product_id) {
- if (!empty($product_id) && isset($product_spins[$key])) {
- $spin_products[$product_id] = intval($product_spins[$key]);
- }
- }
- }
- update_option('wheel_spin_products', $spin_products);
-
- // Dnevni spin - shrani izbrano kolo
- $daily_spin_wheel_id = isset($_POST['wof_daily_spin_wheel_id']) ? intval($_POST['wof_daily_spin_wheel_id']) : '';
- update_option('wof_daily_spin_wheel_id', $daily_spin_wheel_id);
-
- // Prikaži sporočilo o uspehu
- add_settings_error('wheel_settings', 'settings_updated', __('Nastavitve so bile uspešno shranjene.', 'wheel-of-fortune'), 'updated');
-}
-
-// Ročno dodajanje spinov uporabniku se zdaj izvaja preko AJAX
-
-// Pridobi trenutne nastavitve
-$cooldown_minutes = get_option('wheel_cooldown_minutes', 0);
-$max_spins = get_option('wheel_max_spins', 0);
-$send_emails = get_option('wheel_send_emails', false);
-$spin_products = get_option('wheel_spin_products', array());
-
-// Pridobi vsa kolesa za dropdown
-$wheels_table = $wpdb->prefix . 'wof_wheels';
-$wheels = $wpdb->get_results("SELECT * FROM $wheels_table ORDER BY id ASC", ARRAY_A);
-$daily_spin_wheel_id = get_option('wof_daily_spin_wheel_id', '');
-
-// Prikaži sporočila o napakah/uspehu
-settings_errors('wheel_settings');
-?>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- get_wheel_prizes();
- echo $wheel->generate_wheel_svg($prizes);
- ?>
-
-
-
-
-
-
-
-
-
-
-
-
-
- """
-
-
-"./admin/stats-page.php" :
-"""
-prefix . 'users';
-$spins_table = $wpdb->prefix . 'wheel_spins';
-$log_table = $wpdb->prefix . 'wheel_log';
-$prizes_table = $wpdb->prefix . 'wheel_prizes';
-$wheels_table = $wpdb->prefix . 'wof_wheels';
-
-// Pridobi vsa kolesa
-$wheels = $wpdb->get_results("SELECT * FROM $wheels_table ORDER BY id ASC", ARRAY_A);
-
-// Izberi kolo (privzeto prvo)
-$selected_wheel_id = isset($_GET['wheel_id']) ? intval($_GET['wheel_id']) : 1;
-$selected_wheel = $wpdb->get_row($wpdb->prepare("SELECT * FROM $wheels_table WHERE id = %d", $selected_wheel_id), ARRAY_A);
-
-if (!$selected_wheel) {
- $selected_wheel_id = 1;
- $selected_wheel = $wpdb->get_row("SELECT * FROM $wheels_table WHERE id = 1", ARRAY_A);
-}
-
-// Iskanje uporabnikov
-$search = isset($_GET['s']) ? sanitize_text_field($_GET['s']) : '';
-$search_condition = '';
-if (!empty($search)) {
- $search_condition = $wpdb->prepare(
- "AND (u.user_login LIKE %s OR u.user_email LIKE %s OR u.display_name LIKE %s)",
- "%{$search}%",
- "%{$search}%",
- "%{$search}%"
- );
-}
-
-// Pridobi uporabnike z spin-i za izbrano kolo
-$users_with_spins = $wpdb->get_results(
- $wpdb->prepare(
- "SELECT u.ID, u.user_email, u.display_name,
- COALESCE(s.spins_available, 0) as spins_available,
- COUNT(l.id) as total_spins,
- MAX(l.spin_date) as last_spin_date
- FROM {$users_table} u
- LEFT JOIN {$spins_table} s ON u.ID = s.user_id AND s.wheel_id = %d
- LEFT JOIN {$log_table} l ON u.ID = l.user_id AND l.wheel_id = %d
- WHERE 1=1 {$search_condition}
- GROUP BY u.ID
- HAVING total_spins > 0 OR spins_available > 0
- ORDER BY total_spins DESC",
- $selected_wheel_id, $selected_wheel_id
- ),
- ARRAY_A
-);
-
-// Označi nagrado kot unovčeno
-if (isset($_POST['mark_redeemed']) && isset($_POST['prize_id'])) {
- check_admin_referer('mark_prize_redeemed_nonce', 'mark_prize_redeemed_nonce');
-
- $prize_log_id = intval($_POST['prize_id']);
-
- $wpdb->update(
- $log_table,
- array('redeemed' => 1),
- array('id' => $prize_log_id)
- );
-
- echo '' .
- __('Nagrada je bila označena kot unovčena.', 'wheel-of-fortune') .
- '
';
-}
-
-// Ponastavi spine na 0 za vse uporabnike na izbranem kolesu
-if (isset($_POST['reset_all_spins_wheel']) && isset($_POST['wheel_id'])) {
- check_admin_referer('reset_spins_wheel_nonce', 'reset_spins_wheel_nonce');
-
- $wheel_id = intval($_POST['wheel_id']);
-
- // Preveri, če kolo obstaja
- $wheel_exists = $wpdb->get_var($wpdb->prepare("SELECT id FROM $wheels_table WHERE id = %d", $wheel_id));
-
- if ($wheel_exists) {
- // Ponastavi spine na 0 za vse uporabnike na tem kolesu
- $result = $wpdb->update(
- $spins_table,
- array('spins_available' => 0),
- array('wheel_id' => $wheel_id),
- array('%d'),
- array('%d')
- );
-
- if ($result !== false) {
- echo '' .
- sprintf(__('Vsi spini za kolo ID %d so bili uspešno ponastavljeni na 0.', 'wheel-of-fortune'), $wheel_id) .
- '
';
- } else {
- echo '' .
- __('Prišlo je do napake pri ponastavitvi spinov.', 'wheel-of-fortune') .
- '
';
- }
- } else {
- echo '' .
- __('Izbrano kolo ne obstaja.', 'wheel-of-fortune') .
- '
';
- }
-}
-
-// Izberi uporabnika za podrobnosti
-$selected_user_id = isset($_GET['user_id']) ? intval($_GET['user_id']) : 0;
-
-// Pridobi podrobnosti o nagradah uporabnika za izbrano kolo, če je izbran
-$user_prizes = array();
-if ($selected_user_id > 0) {
- $user_prizes = $wpdb->get_results(
- $wpdb->prepare(
- "SELECT l.id, p.name as prize_name, p.description as prize_description,
- l.spin_date, l.redeemed
- FROM {$log_table} l
- JOIN {$prizes_table} p ON l.prize_id = p.id
- WHERE l.user_id = %d AND l.wheel_id = %d
- ORDER BY l.spin_date DESC",
- $selected_user_id, $selected_wheel_id
- ),
- ARRAY_A
- );
-}
-
-?>
-
-
-
-
-
-
-
- :
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 0) : ?>
-
-
-
display_name)); ?>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ' . esc_html__('Unovčeno', 'wheel-of-fortune') :
- ' ' . esc_html__('Neunovčeno', 'wheel-of-fortune');
- ?>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- """
-
-
-"./admin/users-page.php" :
-"""
-prefix . 'wof_wheels';
-$wheels = $wpdb->get_results("SELECT * FROM $wheels_table ORDER BY id ASC", ARRAY_A);
-
-// Izberi kolo (privzeto prvo)
-$selected_wheel_id = isset($_GET['wheel_id']) ? intval($_GET['wheel_id']) : 1;
-$selected_wheel = $wpdb->get_row($wpdb->prepare("SELECT * FROM $wheels_table WHERE id = %d", $selected_wheel_id), ARRAY_A);
-
-if (!$selected_wheel) {
- $selected_wheel_id = 1;
- $selected_wheel = $wpdb->get_row("SELECT * FROM $wheels_table WHERE id = 1", ARRAY_A);
-}
-
-// Obdelaj akcije
-if (isset($_POST['add_spins_submit'])) {
- check_admin_referer('wheel_add_spins_nonce', 'wheel_add_spins_nonce');
-
- $user_id = intval($_POST['user_id']);
- $spins = intval($_POST['spins']);
- $wheel_id = intval($_POST['wheel_id']);
-
- if ($user_id > 0 && $spins > 0 && $wheel_id > 0) {
- $spins_table = $wpdb->prefix . 'wheel_spins';
-
- // Preveri, če uporabnik že ima zapis za to kolo
- $existing = $wpdb->get_var($wpdb->prepare(
- "SELECT id FROM $spins_table WHERE user_id = %d AND wheel_id = %d",
- $user_id, $wheel_id
- ));
-
- if ($existing) {
- $wpdb->query($wpdb->prepare(
- "UPDATE $spins_table SET spins_available = spins_available + %d WHERE user_id = %d AND wheel_id = %d",
- $spins, $user_id, $wheel_id
- ));
- } else {
- $wpdb->insert($spins_table, [
- 'user_id' => $user_id,
- 'wheel_id' => $wheel_id,
- 'spins_available' => $spins,
- 'last_spin_date' => null
- ], ['%d', '%d', '%d', '%s']);
- }
-
- echo '' .
- sprintf(__('Uporabniku ID %d je bilo uspešno dodanih %d spinov za kolo %s.', 'wheel-of-fortune'), $user_id, $spins, $selected_wheel['name']) .
- '
';
- }
-}
-
-if (isset($_POST['reset_spins_submit'])) {
- check_admin_referer('wheel_reset_spins_nonce', 'wheel_reset_spins_nonce');
-
- $user_id = intval($_POST['user_id']);
- $wheel_id = intval($_POST['wheel_id']);
-
- if ($user_id > 0 && $wheel_id > 0) {
- $spins_table = $wpdb->prefix . 'wheel_spins';
-
- $wpdb->update(
- $spins_table,
- array('spins_available' => 0),
- array('user_id' => $user_id, 'wheel_id' => $wheel_id)
- );
-
- echo '' .
- sprintf(__('Spini uporabnika ID %d za kolo %s so bili uspešno ponastavljeni na 0.', 'wheel-of-fortune'), $user_id, $selected_wheel['name']) .
- '
';
- }
-}
-
-// Pridobi podatke o uporabnikih
-$users_table = $wpdb->prefix . 'users';
-$spins_table = $wpdb->prefix . 'wheel_spins';
-$log_table = $wpdb->prefix . 'wheel_log';
-$prizes_table = $wpdb->prefix . 'wheel_prizes';
-
-// Iskanje uporabnikov
-$search = isset($_GET['s']) ? sanitize_text_field($_GET['s']) : '';
-$search_condition = '';
-if (!empty($search)) {
- $search_condition = $wpdb->prepare(
- "AND (u.user_login LIKE %s OR u.user_email LIKE %s OR u.display_name LIKE %s)",
- "%{$search}%",
- "%{$search}%",
- "%{$search}%"
- );
-}
-
-// Pridobi uporabnike z spin-i za izbrano kolo
-$users = $wpdb->get_results(
- $wpdb->prepare(
- "SELECT u.ID, u.user_login, u.user_email, u.display_name,
- COALESCE(s.spins_available, 0) as spins_available,
- COUNT(l.id) as total_spins
- FROM {$users_table} u
- LEFT JOIN {$spins_table} s ON u.ID = s.user_id AND s.wheel_id = %d
- LEFT JOIN {$log_table} l ON u.ID = l.user_id AND l.wheel_id = %d
- WHERE 1=1 {$search_condition}
- GROUP BY u.ID
- HAVING total_spins > 0 OR spins_available > 0
- ORDER BY total_spins DESC",
- $selected_wheel_id, $selected_wheel_id
- ),
- ARRAY_A
-);
-
-// Izbrani uporabnik za urejanje
-$selected_user_id = isset($_GET['edit_user']) ? intval($_GET['edit_user']) : 0;
-$selected_user = null;
-$user_prizes = array();
-
-if ($selected_user_id > 0) {
- $selected_user = get_userdata($selected_user_id);
- if ($selected_user) {
- // Pridobi spine za izbrano kolo
- $spins = $wpdb->get_var($wpdb->prepare(
- "SELECT spins_available FROM $spins_table WHERE user_id = %d AND wheel_id = %d",
- $selected_user_id, $selected_wheel_id
- ));
- $spins = $spins ?: 0;
-
- // Pridobi nagrade uporabnika za izbrano kolo
- $user_prizes = $wpdb->get_results(
- $wpdb->prepare(
- "SELECT l.id, p.name as prize_name, p.description as prize_description,
- l.spin_date, l.redeemed
- FROM {$log_table} l
- JOIN {$prizes_table} p ON l.prize_id = p.id
- WHERE l.user_id = %d AND l.wheel_id = %d
- ORDER BY l.spin_date DESC",
- $selected_user_id, $selected_wheel_id
- ),
- ARRAY_A
- );
- }
-}
-
-?>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
display_name)); ?>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ' . esc_html__('Unovčeno', 'wheel-of-fortune') :
- ' ' . esc_html__('Neunovčeno', 'wheel-of-fortune');
- ?>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 0) : ?>
-
-
-
-
-
-
-
-
- """
-
-
-"./admin/wheels-page.php" :
-"""
-prefix . 'wof_wheels';
-
-// Handle adding a new wheel
-if (isset($_POST['add_wheel_submit']) && check_admin_referer('wof_add_wheel_nonce')) {
- $wheel_name = sanitize_text_field($_POST['wheel_name']);
- $wheel_slug = sanitize_title($_POST['wheel_name']); // Generate slug from name
-
- if (!empty($wheel_name)) {
- $wpdb->insert(
- $wheels_table,
- ['name' => $wheel_name, 'slug' => $wheel_slug, 'created_at' => current_time('mysql')],
- ['%s', '%s', '%s']
- );
- echo '' . __('New wheel created successfully!', 'wheel-of-fortune') . '
';
- } else {
- echo '' . __('Please provide a name for the wheel.', 'wheel-of-fortune') . '
';
- }
-}
-
-// Handle deleting a wheel
-if (isset($_GET['action']) && $_GET['action'] === 'delete' && isset($_GET['wheel_id']) && check_admin_referer('wof_delete_wheel_' . $_GET['wheel_id'])) {
- $wheel_id_to_delete = intval($_GET['wheel_id']);
- if ($wheel_id_to_delete !== 1) { // Prevent deleting the default wheel
- // TODO: Consider what to do with prizes associated with this wheel. For now, we'll just delete the wheel.
- $wpdb->delete($wheels_table, ['id' => $wheel_id_to_delete], ['%d']);
- echo '' . __('Wheel deleted successfully.', 'wheel-of-fortune') . '
';
- } else {
- echo '' . __('The default wheel cannot be deleted.', 'wheel-of-fortune') . '
';
- }
-}
-
-
-$wheels = $wpdb->get_results("SELECT * FROM $wheels_table ORDER BY id ASC", ARRAY_A);
-?>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- [wheel_of_fortune id=""]
-
-
-
-
- |
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
"""
-
-
-"./assets/css/admin.css" :
-"""
-/**
- * Kolo Sreče - CSS za administratorski vmesnik
- */
-
-/* Splošni stil administratorske strani */
-.wheel-admin-page {
- max-width: 1200px;
- margin: 20px 0;
-}
-
-.wheel-admin-page h1 {
- margin-bottom: 20px;
-}
-
-.wheel-admin-page .nav-tab-wrapper {
- margin-bottom: 20px;
-}
-
-/* Kartice */
-.wheel-card {
- background: #fff;
- border: 1px solid #ccd0d4;
- box-shadow: 0 1px 1px rgba(0,0,0,.04);
- margin-bottom: 20px;
- padding: 20px;
-}
-
-.wheel-card h2 {
- margin-top: 0;
- padding-bottom: 12px;
- border-bottom: 1px solid #eee;
-}
-
-/* Tabela z nagradami */
-.wheel-prizes-table {
- width: 100%;
- border-collapse: collapse;
- margin-top: 20px;
-}
-
-.wheel-prizes-table th,
-.wheel-prizes-table td {
- padding: 12px;
- text-align: left;
- border-bottom: 1px solid #eee;
-}
-
-.wheel-prizes-table th {
- background-color: #f9f9f9;
-}
-
-.wheel-prizes-table tr:hover {
- background-color: #f9f9f9;
-}
-
-/* Barve nagrad */
-.wheel-color-preview {
- display: inline-block;
- width: 20px;
- height: 20px;
- border-radius: 50%;
- margin-right: 10px;
- vertical-align: middle;
-}
-
-.wheel-color-blue {
- background-color: #5DADE2;
-}
-
-.wheel-color-red {
- background-color: #E74C3C;
-}
-
-.wheel-color-gray {
- background-color: #D5D8DC;
-}
-
-/* Obrazci */
-.wheel-form-table {
- width: 100%;
- margin-top: 20px;
-}
-
-.wheel-form-table th {
- width: 200px;
- padding: 15px 10px 15px 0;
- text-align: left;
- vertical-align: top;
-}
-
-.wheel-form-table td {
- padding: 15px 10px;
- vertical-align: top;
-}
-
-.wheel-form-table input[type="text"],
-.wheel-form-table input[type="number"],
-.wheel-form-table select,
-.wheel-form-table textarea {
- width: 100%;
- max-width: 400px;
-}
-
-.wheel-form-table .description {
- color: #666;
- font-style: italic;
- margin-top: 5px;
- display: block;
-}
-
-/* Gumbi */
-.wheel-button-primary {
- background: #0073aa;
- border-color: #0073aa;
- color: #fff;
- padding: 5px 15px;
- border-radius: 3px;
- cursor: pointer;
-}
-
-.wheel-button-secondary {
- background: #f7f7f7;
- border-color: #ccc;
- color: #555;
- padding: 5px 15px;
- border-radius: 3px;
- cursor: pointer;
-}
-
-.wheel-button-delete {
- background: #d63638;
- border-color: #d63638;
- color: #fff;
- padding: 5px 15px;
- border-radius: 3px;
- cursor: pointer;
-}
-
-/* Statistika */
-.wheel-stats-container {
- display: flex;
- flex-wrap: wrap;
- margin: 0 -10px;
-}
-
-.wheel-stats-box {
- background: #fff;
- border: 1px solid #ccd0d4;
- box-shadow: 0 1px 1px rgba(0,0,0,.04);
- padding: 20px;
- margin: 10px;
- flex: 1 0 calc(33.333% - 20px);
- min-width: 250px;
- text-align: center;
-}
-
-.wheel-stats-box h3 {
- margin-top: 0;
- color: #23282d;
-}
-
-.wheel-stats-number {
- font-size: 32px;
- font-weight: bold;
- color: #0073aa;
- margin: 10px 0;
-}
-
-/* Predogled kolesa */
-.wheel-preview-container {
- max-width: 300px;
- margin: 20px auto;
-}
-
-/* Odzivnost */
-@media screen and (max-width: 782px) {
- .wheel-form-table th {
- width: 100%;
- display: block;
- padding-bottom: 0;
- }
-
- .wheel-form-table td {
- width: 100%;
- display: block;
- }
-
- .wheel-stats-box {
- flex: 1 0 calc(50% - 20px);
- }
-}
-
-@media screen and (max-width: 600px) {
- .wheel-stats-box {
- flex: 1 0 calc(100% - 20px);
- }
-} """
-
-
-"./assets/css/wheel.css" :
-"""
-/**
- * Wheel of Fortune - CSS for wheel styling
- * Modern game-show aesthetic with 3D effects and lighting
- */
-
-/* Main container */
-.wheel-container {
- position: relative;
- width: 100%;
- max-width: 600px;
- margin: 0 auto;
- background: none !important;
- border: none !important;
- box-shadow: none !important;
- border-radius: 0 !important;
- padding: 0 !important;
-}
-
-/* Dark theme */
-.wheel-container.theme-dark {
- background: none !important;
- border: none !important;
- box-shadow: none !important;
- border-radius: 0 !important;
- padding: 0 !important;
- color: inherit;
-}
-
-/* Wheel sizes */
-.wheel-container.size-small {
- max-width: 300px;
- transform: scale(0.9);
-}
-
-.wheel-container.size-medium {
- max-width: 650px;
-}
-
-.wheel-container.size-large {
- max-width: 800px;
-}
-
-/* Wheel wrapper with lighting effects */
-.wheel-wrapper {
- position: relative;
- margin: 0 auto;
- width: 100%;
- max-width: 700px;
- filter: drop-shadow(0 0 15px rgba(0, 200, 255, 0.3));
- padding-top: 80px;
- transition: transform 0.05s ease-out;
-}
-
-/* Outer ring lighting effect - POENOSTAVLJENO */
-.wheel-wrapper::before {
- content: '';
- position: absolute;
- top: 0;
- left: -5%;
- width: 110%;
- height: 110%;
- border-radius: 50%;
- /* Manj kompleksen gradient */
- background: radial-gradient(
- circle at center,
- rgba(0, 150, 200, 0.1) 0%,
- rgba(0, 0, 0, 0) 70%
- );
- z-index: -1;
- pointer-events: none;
-}
-
-/* Wheel */
-.wheel {
- width: 100%;
- height: 100%;
- transform-origin: center;
- transition: none; /* POMEMBNO: ne uporabljamo CSS tranzicije, saj jo upravlja JS */
- display: block;
- will-change: transform;
- /* Enostavnejši shadow, ki ga podpirajo vse naprave */
- filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.25));
- border: 4px solid #222;
- box-shadow: 0 0 10px 2px rgba(0, 223, 233, 0.5), 0 2px 8px rgba(0,0,0,0.3);
- border-radius: 50%;
- background: #111;
-}
-
-/* Wheel frame - BREZ SVG FILTRA */
-.wheel-frame {
- fill: #0a4d6e;
- stroke: #0a7bb5;
- stroke-width: 8;
-}
-
-/* LED lighting on wheel frame - BREZ SVG FILTRA */
-.wheel-light-track {
- fill: none;
- stroke: #00c8ff;
- stroke-width: 6;
- stroke-dasharray: 3, 8;
- animation: lightTrackAnimation 5s linear infinite;
-}
-
-@keyframes lightTrackAnimation {
- 0% {
- stroke-dashoffset: 0;
- }
- 100% {
- stroke-dashoffset: 100;
- }
-}
-
-/* Fast light track animation for spinning */
-@keyframes fastLightTrackAnimation {
- 0% {
- stroke-dashoffset: 0;
- }
- 100% {
- stroke-dashoffset: 200;
- }
-}
-
-/* Wheel segment - BREZ SVG FILTRA */
-.wheel-segment {
- stroke: #fff;
- stroke-width: 1px;
- transition: all 0.2s;
-}
-
-/* Simple solid fills for segment color classes */
-.wheel-segment-red { fill: #ff3131; }
-.wheel-segment-green { fill: #7ed957; }
-.wheel-segment-purple { fill: #8c52ff; }
-.wheel-segment-orange { fill: #ff914d; }
-.wheel-segment-blue { fill: #1da3e7; }
-
-/* Divider between segments */
-.wheel-divider {
- stroke: rgba(255, 255, 255, 0.5);
- stroke-width: 2px;
-}
-
-/* Pegs on the wheel */
-.wheel-peg {
- fill: #e0e0e0;
- stroke: #666;
- stroke-width: 1px;
- /* Enostavnejši shadow namesto glow filtra */
- filter: drop-shadow(0 1px 2px rgba(0,0,0,0.5));
-}
-
-@keyframes pegPulse {
- from {
- fill: #e0e0e0;
- filter: url(#pegGlow);
- }
- to {
- fill: #ffffff;
- filter: url(#pegGlow) drop-shadow(0 0 3px rgba(255, 255, 255, 0.8));
- }
-}
-
-/* Faster peg pulse for spinning */
-@keyframes fastPegPulse {
- 0% {
- fill: #e0e0e0;
- filter: url(#pegGlow);
- }
- 50% {
- fill: #ffffff;
- filter: url(#pegGlow) drop-shadow(0 0 5px rgba(255, 255, 255, 0.9));
- }
- 100% {
- fill: #e0e0e0;
- filter: url(#pegGlow);
- }
-}
-
-/* Text on wheel - BREZ SVG FILTRA */
-.wheel-text {
- font-family: 'Arial Rounded MT Bold', 'Arial', sans-serif;
- font-size: 24px;
- font-weight: 900;
- fill: #ffffff;
- stroke: #000000;
- stroke-width: 0.5px;
- paint-order: stroke fill;
- letter-spacing: 1px;
- pointer-events: none;
- text-anchor: middle;
- /* Enostavnejša senca, ki deluje povsod */
- text-shadow: 1px 1px 3px rgba(0,0,0,0.7);
- text-overflow: ellipsis;
- max-width: 70px;
-}
-
-/* Center hub - BREZ SVG FILTRA */
-.wheel-hub-outer {
- fill: #0a4d6e;
- stroke: #0a7bb5;
- stroke-width: 4;
-}
-
-.wheel-hub-inner {
- fill: #999;
-}
-
-.wheel-hub-button {
- fill: #330066;
-}
-
-/* Hub text - BREZ SVG FILTRA */
-.wheel-hub-text {
- font-family: 'Arial Rounded MT Bold', 'Arial', sans-serif;
- font-size: 20px;
- font-weight: bold;
- fill: #ff00aa;
- text-anchor: middle;
- /* Enostavnejša senca namesto glow filtra */
- text-shadow: 0 0 10px #ff00aa;
-}
-
-/* Pointer - BREZ SVG FILTRA */
-.wheel-pointer {
- position: absolute;
- top: 60px;
- left: 50%;
- transform: translateX(-50%);
- width: 60px;
- height: 70px;
- z-index: 10;
- pointer-events: none;
- filter: drop-shadow(0 4px 6px rgba(0, 0, 0, 0.4));
- transition: transform 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
- margin-bottom: 20px;
-}
-
-/* Pointer active state - BREZ SVG FILTRA */
-.wheel-pointer.active {
- filter: drop-shadow(0 0 10px rgba(255, 255, 255, 0.8));
- animation: pointerPulse 1s infinite alternate;
-}
-
-/* Pointer bounce effect when hitting a peg */
-.wheel-pointer.bounce {
- animation: pointerBounce 0.3s ease-in-out;
-}
-
-@keyframes pointerPulse {
- from {
- opacity: 0.8;
- }
- to {
- opacity: 1;
- }
-}
-
-@keyframes pointerBounce {
- 0% {
- transform: translateX(-50%) rotate(0deg);
- }
- 25% {
- transform: translateX(-50%) rotate(-5deg);
- }
- 75% {
- transform: translateX(-50%) rotate(5deg);
- }
- 100% {
- transform: translateX(-50%) rotate(0deg);
- }
-}
-
-.wheel-pointer svg {
- width: 100%;
- height: 100%;
-}
-
-/* Pointer parts */
-.pointer-mount {
- fill: #c0c0c0;
- stroke: #a0a0a0;
- stroke-width: 1;
-}
-
-.pointer-arm {
- fill: #a0a0a0;
- stroke: #808080;
- stroke-width: 1;
-}
-
-.pointer-tip {
- fill: #ff0066;
- stroke: #cc0055;
- stroke-width: 1;
-}
-
-/* Wheel button with improved styling */
-.wheel-button {
- display: flex;
- align-items: center;
- justify-content: center;
- margin: 20px auto 0 auto;
- padding: 0 40px !important;
- background: linear-gradient(135deg, #ff00c4, #00dfe9);
- color: #fff;
- border: none;
- border-radius: 24px;
- font-size: 28px;
- font-weight: bold;
- cursor: pointer;
- box-shadow: 0 3px 10px #00dfe9;
- transition: all 0.3s ease;
- position: relative;
- overflow: hidden;
- height: 56px;
- min-width: 140px;
- letter-spacing: 2px;
- line-height: 1 !important;
- text-shadow: 0 2px 8px #000, 0 0 10px #0cf101;
- -webkit-appearance: none;
- appearance: none;
-}
-
-/* Button hover effect */
-.wheel-button:hover {
- transform: translateY(-2px) scale(1.04);
- box-shadow: 0 7px 30px #ff00c4, 0 0 30px #00dfe9;
- background: linear-gradient(135deg, #00dfe9, #ff00c4);
-}
-
-/* Button active effect */
-.wheel-button:active {
- transform: translateY(1px) scale(0.98);
- box-shadow: 0 3px 10px #00dfe9;
-}
-
-/* Button disabled state */
-.wheel-button:disabled {
- background: linear-gradient(135deg, #aa6699, #774466);
- cursor: not-allowed;
- transform: none;
- box-shadow: none;
- opacity: 0.7;
-}
-
-/* Button ripple effect */
-.wheel-button::after {
- content: '';
- position: absolute;
- top: 50%;
- left: 50%;
- width: 5px;
- height: 5px;
- background: rgba(255, 255, 255, 0.5);
- opacity: 0;
- border-radius: 100%;
- transform: scale(1, 1) translate(-50%, -50%);
- transform-origin: 50% 50%;
-}
-
-.wheel-button:focus:not(:active)::after {
- animation: ripple 1s ease-out;
-}
-
-@keyframes ripple {
- 0% {
- transform: scale(0, 0);
- opacity: 0.5;
- }
- 20% {
- transform: scale(25, 25);
- opacity: 0.3;
- }
- 100% {
- opacity: 0;
- transform: scale(40, 40);
- }
-}
-
-/* Spins counter */
-.wheel-spins-counter {
- text-align: center;
- margin: 18px 0 0 0;
- font-size: 22px;
- font-weight: bold;
- color: #fff;
- text-shadow: 0 2px 8px #000, 0 0 10px #0cf101, 0 0 20px #00dfe9;
- letter-spacing: 1px;
- background: rgba(0,0,0,0.35);
- border-radius: 10px;
- padding: 8px 0;
-}
-
-/* Result display */
-.wheel-result {
- display: none;
- text-align: center;
- margin: 20px 0;
- padding: 15px;
- background: rgba(255, 255, 255, 0.1);
- border-radius: 10px;
- box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
- color: white;
- animation: resultGlow 2s infinite alternate;
-}
-
-@keyframes resultGlow {
- from {
- box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
- }
- to {
- box-shadow: 0 5px 25px rgba(255, 0, 170, 0.5);
- }
-}
-
-.wheel-result.win {
- background: rgba(255, 0, 170, 0.2);
-}
-
-.wheel-result h3 {
- font-size: 24px;
- margin: 0 0 10px 0;
- color: #ffffff;
- text-shadow: 0 0 10px rgba(255, 0, 170, 0.8);
- letter-spacing: 1px;
-}
-
-.wheel-result p {
- margin: 5px 0;
-}
-
-.wheel-result strong {
- color: #ffcc00;
- font-size: 1.2em;
- text-shadow: 0 0 5px rgba(255, 204, 0, 0.8);
-}
-
-/* Login required message */
-.wheel-login-required,
-.wheel-no-spins {
- text-align: center;
- margin: 20px 0;
- padding: 20px;
- background: rgba(255, 255, 255, 0.1);
- border-radius: 10px;
- box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
- color: white;
-}
-
-.wheel-login-required a {
- color: #00c8ff;
- text-decoration: none;
- font-weight: bold;
- transition: all 0.3s ease;
- text-shadow: 0 0 5px rgba(0, 200, 255, 0.5);
-}
-
-.wheel-login-required a:hover {
- color: #33d6ff;
- text-shadow: 0 0 10px rgba(0, 200, 255, 0.8);
-}
-
-/* Error message */
-.wheel-error {
- text-align: center;
- margin: 20px 0;
- padding: 15px;
- background: rgba(255, 0, 0, 0.2);
- border-radius: 10px;
- box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
- color: white;
- font-weight: bold;
-}
-
-/* Posodobljene medijske poizvedbe za manjše zaslone */
-@media (max-width: 768px) {
- .wheel-text {
- font-size: 10px;
- max-width: 60px;
- }
-
- .wheel-container.size-large {
- max-width: 500px;
- transform: scale(0.95);
- }
-
- .wheel-hub-text {
- font-size: 18px;
- }
-
- .wheel-pointer {
- width: 50px;
- height: 70px;
- }
-
- .wheel-wrapper {
- padding-top: 35px;
- }
-}
-
-@media (max-width: 576px) {
- .wheel-container {
- padding: 20px 0;
- transform: scale(0.9);
- }
-
- .wheel-text {
- font-size: 8px;
- max-width: 50px;
- }
-
- .wheel-container.size-medium,
- .wheel-container.size-small {
- max-width: 320px;
- transform: scale(0.85);
- }
-
- .wheel-hub-text {
- font-size: 16px;
- }
-
- .wheel-button {
- padding: 8px 25px;
- font-size: 16px;
- margin: 15px auto;
- }
-
- .wheel-pointer {
- width: 40px;
- height: 60px;
- }
-
- .wheel-wrapper {
- padding-top: 30px;
- }
-}
-
-@media (max-width: 480px) {
- .wheel-container {
- transform: scale(0.8);
- padding: 15px 0;
- }
-
- .wheel-text {
- font-size: 7px;
- max-width: 40px;
- }
-
- .wheel-container.size-medium,
- .wheel-container.size-small,
- .wheel-container.size-large {
- max-width: 280px;
- transform: scale(0.75);
- }
-
- .wheel-hub-text {
- font-size: 14px;
- }
-
- .wheel-button {
- padding: 7px 20px;
- font-size: 14px;
- margin: 10px auto;
- }
-
- .wheel-pointer {
- width: 35px;
- height: 50px;
- }
-
- .wheel-wrapper {
- padding-top: 25px;
- }
-
- .wheel-result h3 {
- font-size: 18px;
- }
-
- .wheel-result p {
- font-size: 14px;
- }
-}
-
-/* Dodana nova medijska poizvedba za zelo majhne zaslone */
-@media (max-width: 360px) {
- .wheel-container {
- transform: scale(0.7);
- padding: 10px 0;
- }
-
- .wheel-container.size-medium,
- .wheel-container.size-small,
- .wheel-container.size-large {
- max-width: 240px;
- transform: scale(0.65);
- }
-
- .wheel-text {
- font-size: 6px;
- max-width: 30px;
- }
-
- .wheel-hub-text {
- font-size: 12px;
- }
-
- .wheel-pointer {
- width: 30px;
- height: 45px;
- }
-
- .wheel-wrapper {
- padding-top: 20px;
- }
-}
-
-/* Dodana možnost za ročno prilagajanje velikosti */
-.wheel-container.scale-90 {
- transform: scale(0.9);
-}
-
-.wheel-container.scale-80 {
- transform: scale(0.8);
-}
-
-.wheel-container.scale-70 {
- transform: scale(0.7);
-}
-
-.wheel-container.scale-60 {
- transform: scale(0.6);
-}
-
-.wheel-container.scale-50 {
- transform: scale(0.5);
-}
-"""
-
-
-"./assets/js/wheel.js" :
-"""
-/**
- * Wheel of Fortune - JavaScript for wheel functionality
- * Robust, smooth animation using requestAnimationFrame and easing functions.
- */
-jQuery(document).ready(function($) {
- // Preveri, ali so podatki na voljo
- if (typeof wof_data === 'undefined') {
- console.error('WOF Data is missing.');
- return;
- }
-
- // Elementi
- var wheelContainer = $('.wheel-container');
- var wheelElement = wheelContainer.find('.wheel');
- var spinButton = wheelContainer.find('.wheel-button');
- var resultDiv = wheelContainer.find('.wheel-result');
- var spinsCounter = wheelContainer.find('.wheel-spins-counter span');
-
- // Stanje
- var isSpinning = false;
- var accumulatedRotation = 0;
- var wheelSpins = wof_data.spins_left;
- var l10n = wof_data.l10n;
-
- // Nastavitve animacije
- var spinDuration = 8000;
- var baseRotations = 5;
-
- // Funkcija za animacijo
- function easeOutCubic(t) {
- return 1 - Math.pow(1 - t, 3);
- }
-
- function animateWheel(startTime, startRotation, totalRotation) {
- var currentTime = Date.now();
- var elapsedTime = currentTime - startTime;
-
- if (elapsedTime >= spinDuration) {
- wheelElement.css('transform', 'rotate(' + (startRotation + totalRotation) + 'deg)');
- accumulatedRotation = (startRotation + totalRotation);
- finishSpin();
- return;
- }
-
- var timeProgress = elapsedTime / spinDuration;
- var rotationProgress = easeOutCubic(timeProgress);
- var currentRotation = startRotation + (totalRotation * rotationProgress);
- wheelElement.css('transform', 'rotate(' + currentRotation + 'deg)');
-
- requestAnimationFrame(function() {
- animateWheel(startTime, startRotation, totalRotation);
- });
- }
-
- // Obdelava po koncu vrtenja
- function finishSpin() {
- var prize = window.wof_spin_result.prize;
- showPrizePopup(prize);
- isSpinning = false;
-
- if (wheelSpins > 0) {
- spinButton.prop('disabled', false).text(l10n.spin_button);
- } else {
- spinButton.prop('disabled', true).text(l10n.no_spins_left);
- }
- }
-
- // Prikaz nagrade
- function showPrizePopup(prize) {
- var isTryAgain = window.wof_spin_result.is_try_again === 1 || prize.is_try_again === 1;
- var html = '';
- if (isTryAgain) {
- html = '' + prize.name + '
';
- } else {
- html = '' + l10n.congratulations + ' ' + l10n.you_won + ' ' + prize.name + '
';
- }
- if (window.wof_spin_result.discount_code) {
- html += '' + l10n.discount_code_sent + '
';
- }
- resultDiv.html(html).addClass('win').fadeIn(300);
- }
-
- // Posodobitev števca spinov
- function updateSpinsCounter() {
- if (spinsCounter.length) {
- spinsCounter.text(wheelSpins);
- }
- }
-
- // Klik na gumb za vrtenje
- spinButton.on('click', function() {
- if (isSpinning || wheelSpins <= 0) return;
-
- isSpinning = true;
- spinButton.prop('disabled', true).text(l10n.spinning);
- resultDiv.hide().removeClass('win error');
-
- $.ajax({
- url: wof_data.rest_url,
- method: 'POST',
- beforeSend: function(xhr) {
- xhr.setRequestHeader('X-WP-Nonce', wof_data.nonce);
- },
- data: {
- wheel_id: wof_data.wheel_id,
- },
- success: function(response) {
- if (response.success) {
- window.wof_spin_result = response.data;
- wheelSpins = response.data.remaining_spins;
- updateSpinsCounter();
-
- var targetAngle = response.data.degree;
- var fullSpinsRotation = baseRotations * 360;
- var currentAngle = accumulatedRotation % 360;
-
- var rotationToTarget = targetAngle - currentAngle;
- if (rotationToTarget < 0) {
- rotationToTarget += 360;
- }
-
- var totalRotationAmount = fullSpinsRotation + rotationToTarget;
-
- animateWheel(Date.now(), accumulatedRotation, totalRotationAmount);
-
- } else {
- handleError(response.data.message || l10n.error);
- }
- },
- error: function(xhr) {
- var errorMsg = xhr.responseJSON ? (xhr.responseJSON.message || l10n.error) : l10n.error;
- handleError(errorMsg);
- }
- });
- });
-
- function handleError(message) {
- resultDiv.html('' + message + '
').addClass('error').fadeIn(300);
- isSpinning = false;
- if(wheelSpins > 0){
- spinButton.prop('disabled', false).text(l10n.spin_button);
- }
- }
-
- // Inicializacija
- function init() {
- updateSpinsCounter();
- if (wheelSpins <= 0) {
- spinButton.prop('disabled', true).text(l10n.no_spins_left);
- }
- }
-
- init();
-});"""
-
-
-"./languages/wheel-of-fortune.pot" :
-"""
-# Copyright (C) 2023 Vaše ime
-# This file is distributed under the GPL v2 or later.
-msgid ""
-msgstr ""
-"Project-Id-Version: Kolo Sreče 1.0.0\n"
-"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/wheel-of-fortune\n"
-"POT-Creation-Date: 2023-07-01T12:00:00+00:00\n"
-"PO-Revision-Date: 2023-07-01T12:00:00+00:00\n"
-"Last-Translator: FULL NAME \n"
-"Language-Team: LANGUAGE \n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"X-Generator: WP-CLI 2.7.1\n"
-"X-Domain: wheel-of-fortune\n"
-
-#. Plugin Name of the plugin
-msgid "Kolo Sreče"
-msgstr ""
-
-#. Plugin URI of the plugin
-msgid "https://example.com/kolo-srece"
-msgstr ""
-
-#. Description of the plugin
-msgid "WordPress vtičnik za interaktivno kolo sreče z nagradami"
-msgstr ""
-
-#. Author of the plugin
-msgid "Vaše ime"
-msgstr ""
-
-#. Author URI of the plugin
-msgid "https://example.com"
-msgstr ""
-
-#: wheel-of-fortune.php:199
-msgid "Nimate več razpoložljivih vrtljajev"
-msgstr ""
-
-#: wheel-of-fortune.php:214
-msgid "Počakajte še %d minut pred naslednjim vrtenjem"
-msgstr ""
-
-#: wheel-of-fortune.php:304
-msgid "Čestitamo! Zadeli ste nagrado na kolesu sreče - %s"
-msgstr ""
-
-#: wheel-of-fortune.php:307
-msgid ""
-"Pozdravljeni %s,\n"
-"\n"
-"Čestitamo! Pravkar ste zadeli nagrado na našem kolesu sreče:\n"
-"\n"
-"%s - %s\n"
-"\n"
-"Za unovčenje nagrade se obrnite na našo podporo ali sledite navodilom na naši spletni strani.\n"
-"\n"
-"Lep pozdrav,\n"
-"Ekipa %s"
-msgstr ""
-
-#: wheel-of-fortune.php:372
-msgid "Za sodelovanje v nagradni igri se morate prijaviti ."
-msgstr ""
-
-#: wheel-of-fortune.php:383
-msgid "Trenutno nimate razpoložljivih vrtljajev. Kupite izdelke za pridobitev novih vrtljajev."
-msgstr ""
-
-#: templates/wheel.php:37
-msgid "Preostali vrtljaji:"
-msgstr ""
-
-#: templates/wheel.php:41
-msgid "Zavrti kolo"
-msgstr ""
-
-#: admin/settings-page.php:37
-msgid "Nastavitve so bile uspešno shranjene."
-msgstr ""
-
-#: admin/settings-page.php:53
-msgid "Kolo Sreče - Nastavitve"
-msgstr ""
-
-#: admin/settings-page.php:56
-msgid "Splošne nastavitve"
-msgstr ""
-
-#: admin/settings-page.php:57
-msgid "Izdelki"
-msgstr ""
-
-#: admin/settings-page.php:58
-msgid "Predogled"
-msgstr ""
-
-#: admin/settings-page.php:71
-msgid "Časovna omejitev (minute)"
-msgstr ""
-
-#: admin/settings-page.php:75
-msgid "Število minut, ki mora preteči med dvema vrtljajema. Vrednost 0 pomeni brez omejitve."
-msgstr ""
-
-#: admin/settings-page.php:80
-msgid "Maksimalno število spinov"
-msgstr ""
-
-#: admin/settings-page.php:84
-msgid "Maksimalno število spinov, ki jih lahko ima uporabnik. Vrednost 0 pomeni brez omejitve."
-msgstr ""
-
-#: admin/settings-page.php:89
-msgid "Email obvestila"
-msgstr ""
-
-#: admin/settings-page.php:93
-msgid "Pošlji email obvestilo ob zadetku nagrade"
-msgstr ""
-
-#: admin/settings-page.php:103
-msgid "Upravljanje s spini"
-msgstr ""
-
-#: admin/settings-page.php:108
-msgid "Dodeli spine uporabnikom"
-msgstr ""
-
-#: admin/settings-page.php:111
-msgid "Uporabite spodnji obrazec za dodelitev spinov izbranim uporabnikom."
-msgstr ""
-
-#: admin/settings-page.php:114
-msgid "Išči uporabnike..."
-msgstr ""
-
-#: admin/settings-page.php:116
-msgid "Izberi uporabnika"
-msgstr ""
-
-#: admin/settings-page.php:118
-msgid "Število spinov"
-msgstr ""
-
-#: admin/settings-page.php:119
-msgid "Dodaj spine"
-msgstr ""
-
-#: admin/settings-page.php:125
-msgid "Ponastavi vse spine"
-msgstr ""
-
-#: admin/settings-page.php:128
-msgid "Ponastavi vse spine"
-msgstr ""
-
-#: admin/settings-page.php:129
-msgid "Ta akcija bo ponastavila število spinov za vse uporabnike na 0. Tega ni mogoče razveljaviti!"
-msgstr ""
-
-#: admin/settings-page.php:139
-msgid "Izdelki, ki podeljujejo spine"
-msgstr ""
-
-#: admin/settings-page.php:141
-msgid "Nastavite izdelke, ki bodo ob nakupu podelili določeno število spinov."
-msgstr ""
-
-#: admin/settings-page.php:146
-msgid "ID izdelka"
-msgstr ""
-
-#: admin/settings-page.php:147
-msgid "Ime izdelka"
-msgstr ""
-
-#: admin/settings-page.php:148
-msgid "Število spinov"
-msgstr ""
-
-#: admin/settings-page.php:149
-msgid "Akcije"
-msgstr ""
-
-#: admin/settings-page.php:155
-msgid "Ni nastavljenih izdelkov."
-msgstr ""
-
-#: admin/settings-page.php:169
-msgid "Odstrani"
-msgstr ""
-
-#: admin/settings-page.php:178
-msgid "ID izdelka"
-msgstr ""
-
-#: admin/settings-page.php:182
-msgid "Število spinov"
-msgstr ""
-
-#: admin/settings-page.php:185
-msgid "Dodaj izdelek"
-msgstr ""
-
-#: admin/settings-page.php:197
-msgid "Predogled kolesa"
-msgstr ""
-
-#: admin/settings-page.php:209
-msgid "To je predogled kolesa, ki ga bodo videli uporabniki. Za spreminjanje nagrad pojdite na stran \"Nagrade\"."
-msgstr ""
-
-#: admin/settings-page.php:215
-msgid "Shrani nastavitve"
-msgstr ""
-
-#: admin/settings-page.php:233
-msgid "Izdelek ni najden"
-msgstr ""
-
-#: admin/settings-page.php:236
-msgid "Napaka pri iskanju izdelka"
-msgstr ""
-
-#: admin/settings-page.php:249
-msgid "Vnesite veljaven ID izdelka in število spinov"
-msgstr ""
-
-#: admin/settings-page.php:256
-msgid "Odstrani"
-msgstr ""
-
-#: admin/settings-page.php:276
-msgid "Ni nastavljenih izdelkov."
-msgstr ""
-
-#: admin/settings-page.php:283
-msgid "Ali ste prepričani, da želite ponastaviti vse spine za vse uporabnike? Tega ni mogoče razveljaviti!"
-msgstr ""
-
-#: admin/settings-page.php:292
-msgid "Vsi spini so bili uspešno ponastavljeni."
-msgstr ""
-
-#: admin/settings-page.php:294
-msgid "Napaka pri ponastavljanju spinov:"
-msgstr ""
-
-#: admin/settings-page.php:297
-msgid "Prišlo je do napake pri komunikaciji s strežnikom."
-msgstr ""
-
-#: admin/settings-page.php:320
-msgid "Izberi uporabnika"
-msgstr ""
-
-#: admin/settings-page.php:337
-msgid "Izberite uporabnika in vnesite število spinov"
-msgstr ""
-
-#: admin/settings-page.php:352
-msgid "Spini so bili uspešno dodani."
-msgstr ""
-
-#: admin/settings-page.php:354
-msgid "Napaka pri dodajanju spinov:"
-msgstr ""
-
-#: admin/settings-page.php:357
-msgid "Prišlo je do napake pri komunikaciji s strežnikom."
-msgstr ""
-
-#: admin/prizes-page.php:36
-msgid "Ime nagrade je obvezno."
-msgstr ""
-
-#: admin/prizes-page.php:38
-msgid "Verjetnost mora biti med 0 in 1."
-msgstr ""
-
-#: admin/prizes-page.php:54
-msgid "Nagrada je bila uspešno dodana."
-msgstr ""
-
-#: admin/prizes-page.php:80
-msgid "Ime nagrade je obvezno."
-msgstr ""
-
-#: admin/prizes-page.php:82
-msgid "Verjetnost mora biti med 0 in 1."
-msgstr ""
-
-#: admin/prizes-page.php:98
-msgid "Nagrada je bila uspešno posodobljena."
-msgstr ""
-
-#: admin/prizes-page.php:117
-msgid "Nagrada je bila uspešno izbrisana."
-msgstr ""
-
-#: admin/prizes-page.php:134
-msgid "Kolo Sreče - Nagrade"
-msgstr ""
-
-#: admin/prizes-page.php:139
-msgid "Seznam nagrad"
-msgstr ""
-
-#: admin/prizes-page.php:143
-msgid "Opozorilo: Skupna verjetnost vseh nagrad presega 1 (100%). Priporočamo, da prilagodite verjetnosti tako, da bo skupna vsota enaka 1."
-msgstr ""
-
-#: admin/prizes-page.php:144
-msgid "Trenutna skupna verjetnost:"
-msgstr ""
-
-#: admin/prizes-page.php:147
-msgid "Opozorilo: Skupna verjetnost vseh nagrad je manjša od 1 (100%). Priporočamo, da prilagodite verjetnosti tako, da bo skupna vsota enaka 1."
-msgstr ""
-
-#: admin/prizes-page.php:148
-msgid "Trenutna skupna verjetnost:"
-msgstr ""
-
-#: admin/prizes-page.php:156
-msgid "ID"
-msgstr ""
-
-#: admin/prizes-page.php:157
-msgid "Ime"
-msgstr ""
-
-#: admin/prizes-page.php:158
-msgid "Opis"
-msgstr ""
-
-#: admin/prizes-page.php:159
-msgid "Verjetnost"
-msgstr ""
-
-#: admin/prizes-page.php:160
-msgid "Barva"
-msgstr ""
-
-#: admin/prizes-page.php:161
-msgid "Status"
-msgstr ""
-
-#: admin/prizes-page.php:162
-msgid "Akcije"
-msgstr ""
-
-#: admin/prizes-page.php:168
-msgid "Ni nagrad. Dodajte prvo nagrado spodaj."
-msgstr ""
-
-#: admin/prizes-page.php:179
-msgid "Aktivna"
-msgstr ""
-
-#: admin/prizes-page.php:179
-msgid "Neaktivna"
-msgstr ""
-
-#: admin/prizes-page.php:182
-msgid "Uredi"
-msgstr ""
-
-#: admin/prizes-page.php:183
-msgid "Izbriši"
-msgstr ""
-
-#: admin/prizes-page.php:194
-msgid "Dodaj novo nagrado"
-msgstr ""
-
-#: admin/prizes-page.php:203
-msgid "Ime nagrade"
-msgstr ""
-
-#: admin/prizes-page.php:210
-msgid "Opis"
-msgstr ""
-
-#: admin/prizes-page.php:217
-msgid "Verjetnost"
-msgstr ""
-
-#: admin/prizes-page.php:221
-msgid "Vnesite vrednost med 0 in 1 (npr. 0.1 za 10% verjetnost)."
-msgstr ""
-
-#: admin/prizes-page.php:226
-msgid "Barva"
-msgstr ""
-
-#: admin/prizes-page.php:230
-msgid "Modra"
-msgstr ""
-
-#: admin/prizes-page.php:231
-msgid "Rdeča"
-msgstr ""
-
-#: admin/prizes-page.php:232
-msgid "Siva"
-msgstr ""
-
-#: admin/prizes-page.php:239
-msgid "Nagrada je aktivna"
-msgstr ""
-
-#: admin/prizes-page.php:247
-msgid "Dodaj nagrado"
-msgstr ""
-
-#: admin/prizes-page.php:258
-msgid "Uredi nagrado"
-msgstr ""
-
-#: admin/prizes-page.php:267
-msgid "Ime nagrade"
-msgstr ""
-
-#: admin/prizes-page.php:274
-msgid "Opis"
-msgstr ""
-
-#: admin/prizes-page.php:281
-msgid "Verjetnost"
-msgstr ""
-
-#: admin/prizes-page.php:285
-msgid "Vnesite vrednost med 0 in 1 (npr. 0.1 za 10% verjetnost)."
-msgstr ""
-
-#: admin/prizes-page.php:290
-msgid "Barva"
-msgstr ""
-
-#: admin/prizes-page.php:294
-msgid "Modra"
-msgstr ""
-
-#: admin/prizes-page.php:295
-msgid "Rdeča"
-msgstr ""
-
-#: admin/prizes-page.php:296
-msgid "Siva"
-msgstr ""
-
-#: admin/prizes-page.php:303
-msgid "Nagrada je aktivna"
-msgstr ""
-
-#: admin/prizes-page.php:311
-msgid "Shrani spremembe"
-msgstr ""
-
-#: admin/prizes-page.php:335
-msgid "Aktivna"
-msgstr ""
-
-#: admin/prizes-page.php:345
-msgid "Ali ste prepričani, da želite izbrisati to nagrado?"
-msgstr ""
-
-#: admin/stats-page.php:134
-msgid "Kolo Sreče - Statistika"
-msgstr ""
-
-#: admin/stats-page.php:138
-msgid "Skupno število vrtljajev"
-msgstr ""
-
-#: admin/stats-page.php:143
-msgid "Uporabniki z vrtljaji"
-msgstr ""
-
-#: admin/stats-page.php:148
-msgid "Preostali vrtljaji"
-msgstr ""
-
-#: admin/stats-page.php:155
-msgid "Nagrade po kategorijah"
-msgstr ""
-
-#: admin/stats-page.php:160
-msgid "Nagrada"
-msgstr ""
-
-#: admin/stats-page.php:161
-msgid "Barva"
-msgstr ""
-
-#: admin/stats-page.php:162
-msgid "Število zadetkov"
-msgstr ""
-
-#: admin/stats-page.php:168
-msgid "Ni podatkov."
-msgstr ""
-
-#: admin/stats-page.php:186
-msgid "Vrtljaji po dnevih (zadnjih 30 dni)"
-msgstr ""
-
-#: admin/stats-page.php:189
-msgid "Ni podatkov za prikaz."
-msgstr ""
-
-#: admin/stats-page.php:225
-msgid "Uporabniki z največ vrtljaji"
-msgstr ""
-
-#: admin/stats-page.php:230
-msgid "Uporabnik"
-msgstr ""
-
-#: admin/stats-page.php:231
-msgid "Email"
-msgstr ""
-
-#: admin/stats-page.php:232
-msgid "Število vrtljajev"
-msgstr ""
-
-#: admin/stats-page.php:238
-msgid "Ni podatkov."
-msgstr ""
-
-#: admin/stats-page.php:255
-msgid "Uporabniki z največ preostalimi vrtljaji"
-msgstr ""
-
-#: admin/stats-page.php:260
-msgid "Uporabnik"
-msgstr ""
-
-#: admin/stats-page.php:261
-msgid "Email"
-msgstr ""
-
-#: admin/stats-page.php:262
-msgid "Preostali vrtljaji"
-msgstr ""
-
-#: admin/stats-page.php:268
-msgid "Ni podatkov."
-msgstr ""
-
-#: admin/stats-page.php:285
-msgid "Zadnjih 10 vrtljajev"
-msgstr ""
-
-#: admin/stats-page.php:290
-msgid "ID"
-msgstr ""
-
-#: admin/stats-page.php:291
-msgid "Uporabnik"
-msgstr ""
-
-#: admin/stats-page.php:292
-msgid "Nagrada"
-msgstr ""
-
-#: admin/stats-page.php:293
-msgid "Datum"
-msgstr ""
-
-#: admin/stats-page.php:294
-msgid "Unovčeno"
-msgstr ""
-
-#: admin/stats-page.php:300
-msgid "Ni podatkov."
-msgstr ""
-
-#: admin/stats-page.php:310
-msgid "Da"
-msgstr ""
-
-#: admin/stats-page.php:312
-msgid "Ne"
-msgstr ""
-
-#: admin/stats-page.php:325
-msgid "Izvoz podatkov"
-msgstr ""
-
-#: admin/stats-page.php:327
-msgid "Izvozite podatke o vrtljajih in nagradah za nadaljnjo analizo."
-msgstr ""
-
-#: admin/stats-page.php:336
-msgid "Vsi vrtljaji"
-msgstr ""
-
-#: admin/stats-page.php:342
-msgid "Nagrade in zadetki"
-msgstr ""
-
-#: admin/stats-page.php:348
-msgid "Uporabniki in vrtljaji"
-msgstr ""
-
-#: admin/stats-page.php:353
-msgid "Od datuma:"
-msgstr ""
-
-#: admin/stats-page.php:358
-msgid "Do datuma:"
-msgstr ""
-
-#: admin/stats-page.php:363
-msgid "Format:"
-msgstr ""
-
-#: admin/stats-page.php:372
-msgid "Izvozi podatke"
-msgstr "" """
-
-
-"./public/shortcode-template.php" :
-"""
-
-
-
-
-
- generate_wheel_svg($prizes); ?>
-
-
-
- >
- 0) ? esc_html($l10n['spin_button']) : esc_html($l10n['no_spins_left']); ?>
-
-
-
-
-
-
-
-
"""
-
-
-"./templates/emails/default-prize-email.html" :
-"""
-
-
-
- Congratulations on your win!
-
-
-
-
-
- Congratulations, {user_name}!
-
-
-
-
- You've won a prize!
-
- You just won a fantastic prize on our Wheel of Fortune:
-
-
-
- Prize:
- {prize_name}
-
-
- Description:
- {prize_description}
-
-
- Redemption code:
- {redemption_code}
-
-
-
- To redeem your prize, follow the instructions on our website or contact our support team.
-
-
- Thank you for participating!
-
-
-
-
-
- This is an automated message. Please do not reply to this email.
- © {date} {site_name} . All rights reserved.
-
-
-
-
- """
-
-
-"./templates/wheel.php" :
-"""
-prefix . 'wheel_spins';
-$spins = $wpdb->get_var($wpdb->prepare("SELECT spins_available FROM $spins_table WHERE user_id = %d AND wheel_id = %d", $user_id, $wheel_id));
-$spins = $spins === null ? 0 : (int) $spins;
-
-// Get prizes for the specific wheel
-$wheel = wheel_of_fortune();
-$prizes = $wheel->get_wheel_prizes($wheel_id);
-
-// Set classes for size, theme and scale
-$container_classes = array(
- 'wheel-container',
- 'wheel-of-fortune-container',
- 'size-' . $atts['size'],
- 'theme-' . $atts['theme']
-);
-
-// Add scale class if provided
-if (!empty($atts['scale'])) {
- $container_classes[] = $atts['scale'];
-}
-
-// Generate unique ID for this wheel
-$wheel_id_html = 'wheel-of-fortune-' . uniqid();
-
-?>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- generate_wheel_svg($prizes);
- } else {
- echo '
' . esc_html__('Error loading the wheel. No prizes available.', 'wheel-of-fortune') . '
';
- }
- ?>
-
-
-
-
-
-
-
>
-
-
-
-
-
-
- """
-
-
-"./wheel-of-fortune.php" :
-"""
-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'));
-
- // --- CRON: filter in akcija vedno aktivna ---
- add_filter('cron_schedules', array($this, 'add_custom_cron_schedules'));
- add_action('wof_daily_spin_event', array($this, 'execute_daily_spin_cron'));
- // ------------------------------------------
-
- 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_ajax_update_wheel_product_spins', array($this, 'ajax_update_wheel_product_spins'));
- add_action('wp_ajax_wof_delete_wheel_product', array($this, 'ajax_delete_wheel_product'));
- add_action('wp_ajax_wheel_migrate_try_again', array($this, 'ajax_migrate_try_again'));
- add_action('wp_ajax_wheel_reset_spins_wheel', array($this, 'ajax_reset_spins_wheel'));
-
- // 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() {
- $this->create_database_tables();
- $this->run_migration();
- $this->set_default_options();
-
- // Dodaj cron opravilo za dnevne spine
- if (!wp_next_scheduled('wheel_daily_spins_cron')) {
- wp_schedule_event(time(), 'wheel_daily', 'wheel_daily_spins_cron');
- }
-
- // Izvedi migracijo za is_try_again stolpec
- $this->migrate_add_is_try_again_column();
- }
-
- public function deactivate() {
- wp_clear_scheduled_hook('wof_daily_spin_event');
- error_log("Wheel of Fortune: Cron job 'wof_daily_spin_event' cleared.");
- 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,
- is_try_again tinyint(1) NOT NULL 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.");
- }
-
- // Migracija: dodaj stolpec is_try_again v obstoječe tabele
- $this->migrate_add_is_try_again_column();
- }
-
- private function migrate_add_is_try_again_column() {
- global $wpdb;
- $table_prizes = $wpdb->prefix . 'wheel_prizes';
-
- // Preveri, če stolpec is_try_again že obstaja
- $column_exists = $wpdb->get_results("SHOW COLUMNS FROM $table_prizes LIKE 'is_try_again'");
-
- if (empty($column_exists)) {
- // Dodaj stolpec is_try_again
- $result = $wpdb->query("ALTER TABLE $table_prizes ADD COLUMN is_try_again tinyint(1) NOT NULL DEFAULT 0");
- if ($result !== false) {
- error_log("Wheel of Fortune: Stolpec is_try_again uspešno dodan v tabelo $table_prizes");
- } else {
- error_log("Wheel of Fortune: Napaka pri dodajanju stolpca is_try_again v tabelo $table_prizes");
- }
- } else {
- error_log("Wheel of Fortune: Stolpec is_try_again že obstaja v tabeli $table_prizes");
- }
- }
-
- 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')
- );
-
- // Dodam podstran za nastavitve
- add_submenu_page(
- 'wof-wheels',
- __('Settings', 'wheel-of-fortune'),
- __('Settings', 'wheel-of-fortune'),
- 'manage_options',
- 'wof-settings',
- array($this, 'settings_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'));
- }
-
- // Dodam funkcijo za prikaz strani z nastavitvami
- public function settings_page() {
- require_once WHEEL_OF_FORTUNE_PLUGIN_DIR . 'admin/settings-page.php';
- }
-
- 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;
- }
- }
-
- // Pošlji email samo, če ni "try again" nagrada
- if (get_option('wheel_send_emails', true) && (!isset($prize['is_try_again']) || $prize['is_try_again'] != 1)) {
- $this->send_prize_email($user_id, $prize);
- }
-
- $response_data = [
- 'prize' => $prize,
- 'degree' => $degree,
- 'remaining_spins' => $new_spins,
- 'discount_code' => $redemption_code,
- 'is_try_again' => isset($prize['is_try_again']) ? (int)$prize['is_try_again'] : 0
- ];
-
- 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 '' . esc_html__('No prizes available.', 'wheel-of-fortune') . '
';
- }
-
- // SVG dimensions and parameters
- $cx = 350;
- $cy = 350;
- $outer_radius = 330;
- $inner_radius = 70;
- $angle = 360 / $num_prizes;
-
- // Initialize SVG parts
- $defs = '';
- $segments_paths = '';
- $text_paths = '';
-
- // Generate segments and text paths
- // Updated segment color palette
- $segment_colors = ['#ff3131', '#7ed957', '#8c52ff', '#ff914d', '#1da3e7'];
- for ($i = 0; $i < $num_prizes; $i++) {
- $prize = $prizes[$i];
- $start_angle = $i * $angle;
- $end_angle = ($i + 1) * $angle;
-
- // --- 1. Draw the visible segment path ---
- $start_rad = deg2rad($start_angle);
- $end_rad = deg2rad($end_angle);
-
- $x1 = $cx + $outer_radius * cos($start_rad); $y1 = $cy + $outer_radius * sin($start_rad);
- $x2 = $cx + $outer_radius * cos($end_rad); $y2 = $cy + $outer_radius * sin($end_rad);
- $x3 = $cx + $inner_radius * cos($end_rad); $y3 = $cy + $inner_radius * sin($end_rad);
- $x4 = $cx + $inner_radius * cos($start_rad); $y4 = $cy + $inner_radius * sin($start_rad);
-
- $large_arc = ($end_angle - $start_angle > 180) ? 1 : 0;
- $path_data = "M{$x1},{$y1} A{$outer_radius},{$outer_radius} 0 {$large_arc},1 {$x2},{$y2} L{$x3},{$y3} A{$inner_radius},{$inner_radius} 0 {$large_arc},0 {$x4},{$y4} Z";
-
- // Barva segmenta - ciklično, a če je nagrad 10, zadnji segment ne sme biti enak prvemu
- $color_index = $i % count($segment_colors);
- if ($num_prizes === 10 && $i === $num_prizes - 1 && $segment_colors[$color_index] === $segment_colors[0]) {
- $color_index = ($color_index + 1) % count($segment_colors);
- }
- $segment_color = $segment_colors[$color_index];
-
- $segments_paths .= " ";
-
- // --- 2. Draw dividers and pegs ---
- $divider_x1 = $cx + $inner_radius * cos($start_rad); $divider_y1 = $cy + $inner_radius * sin($start_rad);
- $divider_x2 = $cx + $outer_radius * cos($start_rad); $divider_y2 = $cy + $outer_radius * sin($start_rad);
- $segments_paths .= " ";
- $segments_paths .= " ";
-
- // --- 3. Draw text vertically (rotated to segment center) ---
- $text_angle = $start_angle + ($angle / 2);
- $text_rad = deg2rad($text_angle);
- $text_radius = ($inner_radius + $outer_radius) / 2;
- $text_x = $cx + $text_radius * cos($text_rad);
- $text_y = $cy + $text_radius * sin($text_rad);
- $rotate = $text_angle;
- // Da je vedno navzven (ne na glavo)
- if ($rotate > 90 && $rotate < 270) {
- $rotate += 180;
- }
- $text_paths .= "{$prize['name']} ";
- }
-
- $defs .= ' ';
-
- // Assemble the final SVG
- $svg = '';
- $svg .= $defs; // Add definitions first
- $svg .= ' ';
- $svg .= ' ';
- $svg .= $segments_paths; // Add all segments, dividers, and pegs
- $svg .= ' ';
- $svg .= ' ';
- $svg .= $text_paths; // Add all text paths on top of segments
- $svg .= ' ';
- $svg .= "SPIN ";
- $svg .= ' ';
-
- return $svg;
- }
-
- public function ajax_get_prize_details() {
- check_ajax_referer('wheel_admin_nonce', '_ajax_nonce');
-
- if (!current_user_can('manage_options')) {
- wp_send_json_error(['message' => __('You do not have permission to perform this action.', 'wheel-of-fortune')]);
- }
-
- $prize_id = isset($_POST['prize_id']) ? intval($_POST['prize_id']) : 0;
- if (!$prize_id) {
- wp_send_json_error(['message' => __('Prize ID was not provided.', 'wheel-of-fortune')]);
- }
-
- global $wpdb;
- $prize = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->prefix}wheel_prizes WHERE id = %d", $prize_id), ARRAY_A);
-
- if (!$prize) {
- wp_send_json_error(['message' => __('Prize not found.', 'wheel-of-fortune')]);
- }
-
- wp_send_json_success($prize);
- }
-
- public function ajax_save_prize() {
- check_ajax_referer('wheel_admin_nonce', '_ajax_nonce');
-
- if (!current_user_can('manage_options')) {
- wp_send_json_error(['message' => __('You do not have permission to perform this action.', 'wheel-of-fortune')]);
- }
-
- // Dodamo wheel_id
- $wheel_id = isset($_POST['wheel_id']) ? intval($_POST['wheel_id']) : 0;
- $prize_id = isset($_POST['prize_id']) ? intval($_POST['prize_id']) : 0;
- $name = isset($_POST['name']) ? sanitize_text_field($_POST['name']) : '';
- $description = isset($_POST['description']) ? sanitize_textarea_field($_POST['description']) : '';
- $probability = isset($_POST['probability']) ? floatval($_POST['probability']) : 0;
- $is_active = isset($_POST['is_active']) ? intval($_POST['is_active']) : 0;
- $redemption_code = isset($_POST['redemption_code']) ? sanitize_text_field($_POST['redemption_code']) : '';
- $is_discount = isset($_POST['is_discount']) ? intval($_POST['is_discount']) : 0;
- $email_subject = isset($_POST['email_subject']) ? sanitize_text_field($_POST['email_subject']) : '';
- $email_template = isset($_POST['email_template']) ? wp_kses_post($_POST['email_template']) : '';
- $discount_value = isset($_POST['discount_value']) ? floatval($_POST['discount_value']) : 0;
- $is_try_again = isset($_POST['is_try_again']) ? intval($_POST['is_try_again']) : 0;
-
- if (empty($name)) {
- wp_send_json_error(['message' => __('Prize name is required.', 'wheel-of-fortune')]);
- }
-
- if ($wheel_id === 0) {
- wp_send_json_error(['message' => __('Wheel ID is missing.', 'wheel-of-fortune')]);
- }
-
- if ($probability < 0 || $probability > 1) {
- wp_send_json_error(['message' => __('Probability must be between 0 and 1.', 'wheel-of-fortune')]);
- }
-
- global $wpdb;
- $table_name = $wpdb->prefix . 'wheel_prizes';
-
- $data = [
- 'wheel_id' => $wheel_id,
- 'name' => $name,
- 'description' => $description,
- 'probability' => $probability,
- 'is_active' => $is_active,
- 'redemption_code' => $redemption_code,
- 'is_discount' => $is_discount,
- 'email_subject' => $email_subject,
- 'email_template' => $email_template,
- 'discount_value' => $discount_value,
- 'is_try_again' => $is_try_again,
- ];
-
- $format = ['%d', '%s', '%s', '%f', '%d', '%s', '%d', '%s', '%s', '%f', '%d'];
-
- if ($prize_id > 0) {
- $result = $wpdb->update($table_name, $data, ['id' => $prize_id], $format, ['%d']);
- } else {
- $result = $wpdb->insert($table_name, $data, $format);
- $prize_id = $wpdb->insert_id;
- }
-
- if ($result === false) {
- wp_send_json_error(['message' => $wpdb->last_error]);
- } else {
- wp_send_json_success(['message' => __('Prize saved successfully!', 'wheel-of-fortune'), 'prize_id' => $prize_id]);
- }
- }
-
- public function ajax_delete_prize() {
- check_ajax_referer('wheel_admin_nonce', '_ajax_nonce');
-
- if (!current_user_can('manage_options')) {
- wp_send_json_error(['message' => __('You do not have permission to perform this action.', 'wheel-of-fortune')]);
- }
-
- $prize_id = isset($_POST['prize_id']) ? intval($_POST['prize_id']) : 0;
-
- if (!$prize_id) {
- wp_send_json_error(['message' => __('Prize ID was not provided.', 'wheel-of-fortune')]);
- }
-
- global $wpdb;
- $table_name = $wpdb->prefix . 'wheel_prizes';
-
- $result = $wpdb->delete($table_name, ['id' => $prize_id]);
-
- if ($result !== false) {
- wp_send_json_success(['message' => __('Prize deleted successfully.', 'wheel-of-fortune')]);
- } else {
- wp_send_json_error(['message' => __('Failed to delete the prize.', 'wheel-of-fortune')]);
- }
- }
-
- public function ajax_search_users() {
- check_ajax_referer('wheel_admin_nonce', 'nonce');
-
- if (!current_user_can('manage_options')) {
- wp_send_json_error(['message' => __('You do not have permission to perform this action.', 'wheel-of-fortune')]);
- }
-
- $search = isset($_POST['search']) ? sanitize_text_field($_POST['search']) : '';
-
- if (empty($search)) {
- wp_send_json_error(['message' => __('Search term is required.', 'wheel-of-fortune')]);
- }
-
- $users = get_users([
- 'search' => '*' . $search . '*',
- 'search_columns' => ['user_login', 'user_email', 'display_name'],
- 'number' => 10
- ]);
-
- $results = [];
- foreach ($users as $user) {
- $results[] = [
- 'id' => $user->ID,
- 'name' => $user->display_name,
- 'email' => $user->user_email
- ];
- }
-
- wp_send_json_success($results);
- }
-
- public function ajax_add_spins() {
- check_ajax_referer('wheel_admin_nonce', 'nonce');
-
- if (!current_user_can('manage_options')) {
- wp_send_json_error(['message' => __('You do not have permission to perform this action.', 'wheel-of-fortune')]);
- }
-
- $user_id = isset($_POST['user_id']) ? intval($_POST['user_id']) : 0;
- $spins = isset($_POST['spins']) ? intval($_POST['spins']) : 0;
-
- if (!$user_id || $spins <= 0) {
- wp_send_json_error(['message' => __('Invalid user ID or number of spins.', 'wheel-of-fortune')]);
- }
-
- if (wheel_of_fortune_add_spins($user_id, $spins)) {
- wp_send_json_success(['message' => sprintf(__('Successfully added %d spins to user ID %d.', 'wheel-of-fortune'), $spins, $user_id)]);
- } else {
- wp_send_json_error(['message' => __('Failed to add spins to user.', 'wheel-of-fortune')]);
- }
- }
-
- public function ajax_reset_all_spins() {
- check_ajax_referer('wheel_admin_nonce', 'nonce');
-
- if (!current_user_can('manage_options')) {
- wp_send_json_error(['message' => __('You do not have permission to perform this action.', 'wheel-of-fortune')]);
- }
-
- global $wpdb;
- $table_name = $wpdb->prefix . 'wheel_spins';
-
- $result = $wpdb->update(
- $table_name,
- ['spins_available' => 0],
- [],
- ['%d'],
- []
- );
-
- if ($result !== false) {
- // Reset user meta fields too
- $users = get_users(['fields' => 'ID']);
- foreach ($users as $user_id) {
- update_user_meta($user_id, '_wheel_spins', 0);
- }
-
- wp_send_json_success(['message' => __('All spins have been reset to 0.', 'wheel-of-fortune')]);
- } else {
- wp_send_json_error(['message' => __('Failed to reset spins.', 'wheel-of-fortune')]);
- }
- }
-
- public function ajax_get_product() {
- check_ajax_referer('wheel_admin_nonce', 'nonce');
-
- if (!current_user_can('manage_options')) {
- wp_send_json_error(['message' => __('You do not have permission to perform this action.', 'wheel-of-fortune')]);
- }
-
- if (!$this->is_woocommerce_active()) {
- wp_send_json_error(['message' => __('WooCommerce is not active.', 'wheel-of-fortune')]);
- }
-
- $product_id = isset($_POST['product_id']) ? intval($_POST['product_id']) : 0;
-
- if (!$product_id) {
- wp_send_json_error(['message' => __('Product ID is required.', 'wheel-of-fortune')]);
- }
-
- $product = wc_get_product($product_id);
-
- if (!$product) {
- wp_send_json_error(['message' => __('Product not found.', 'wheel-of-fortune')]);
- }
-
- wp_send_json_success([
- 'id' => $product->get_id(),
- 'name' => $product->get_name()
- ]);
- }
-
- public function ajax_test_email() {
- check_ajax_referer('wheel_admin_nonce', 'nonce');
-
- if (!current_user_can('manage_options')) {
- wp_send_json_error(['message' => __('You do not have permission to perform this action.', 'wheel-of-fortune')]);
- return;
- }
-
- $recipient_email = isset($_POST['recipient_email']) ? sanitize_email($_POST['recipient_email']) : '';
-
- if (empty($recipient_email) || !is_email($recipient_email)) {
- wp_send_json_error(['message' => __('Please provide a valid recipient email address.', 'wheel-of-fortune')]);
- return;
- }
-
- // Get settings from the form, passed via AJAX
- $smtp_enabled = isset($_POST['smtp_enabled']) && $_POST['smtp_enabled'] === '1';
- $smtp_host = isset($_POST['smtp_host']) ? sanitize_text_field($_POST['smtp_host']) : '';
- $smtp_port = isset($_POST['smtp_port']) ? intval($_POST['smtp_port']) : 587;
- $smtp_encryption = isset($_POST['smtp_encryption']) ? sanitize_text_field($_POST['smtp_encryption']) : 'tls';
- $smtp_username = isset($_POST['smtp_username']) ? sanitize_text_field($_POST['smtp_username']) : '';
- $smtp_password = isset($_POST['smtp_password']) ? wp_unslash($_POST['smtp_password']) : '';
- $from_name = isset($_POST['from_name']) ? sanitize_text_field($_POST['from_name']) : get_bloginfo('name');
- $from_email = isset($_POST['from_email']) ? sanitize_email($_POST['from_email']) : get_bloginfo('admin_email');
-
- $user = wp_get_current_user();
-
- // Prepare email content
- $subject = __('Wheel of Fortune - Test Email', 'wheel-of-fortune');
- $message_body = sprintf(
- __('Hello %1$s, This is a test email from the Wheel of Fortune plugin. If you received this message, your email settings seem to be working.Current Settings Used for This Test: Use SMTP: %2$sHost: %3$sPort: %4$sEncryption: %5$sUsername: %6$sSender Name: %7$sSender Email: %8$s Best regards, The Wheel of Fortune Plugin', 'wheel-of-fortune'),
- $user->display_name,
- $smtp_enabled ? __('Yes', 'wheel-of-fortune') : __('No (using default wp_mail)', 'wheel-of-fortune'),
- esc_html($smtp_host),
- esc_html($smtp_port),
- esc_html(strtoupper($smtp_encryption)),
- esc_html($smtp_username),
- esc_html($from_name),
- esc_html($from_email)
- );
-
- if (!$smtp_enabled) {
- // Use standard wp_mail if SMTP is disabled
- $headers = ['Content-Type: text/html; charset=UTF-8'];
- if (!empty($from_email) && !empty($from_name)) {
- $headers[] = 'From: ' . $from_name . ' <' . $from_email . '>';
- }
-
- $result = wp_mail($recipient_email, $subject, $message_body, $headers);
-
- if ($result) {
- wp_send_json_success(['message' => sprintf(__('Test email successfully sent to %s using the standard WordPress mail function.', 'wheel-of-fortune'), esc_html($recipient_email))]);
- } else {
- global $phpmailer;
- $error_info = (isset($phpmailer) && is_object($phpmailer) && !empty($phpmailer->ErrorInfo)) ? $phpmailer->ErrorInfo : 'Please check your server\'s PHP mail logs.';
- wp_send_json_error(['message' => sprintf(__('Failed to send email using wp_mail(). Error: %s', 'wheel-of-fortune'), esc_html($error_info))]);
- }
- return;
- }
-
- // --- Use a dedicated PHPMailer instance for SMTP test ---
- require_once ABSPATH . WPINC . '/PHPMailer/PHPMailer.php';
- require_once ABSPATH . WPINC . '/PHPMailer/SMTP.php';
- require_once ABSPATH . WPINC . '/PHPMailer/Exception.php';
-
- $mail = new PHPMailer\PHPMailer\PHPMailer(true);
-
- try {
- // Server settings
- $mail->isSMTP();
- $mail->Host = $smtp_host;
- $mail->SMTPAuth = !empty($smtp_username);
- $mail->Username = $smtp_username;
- $mail->Password = $smtp_password;
- if ($smtp_encryption === 'ssl') {
- $mail->SMTPSecure = PHPMailer\PHPMailer\PHPMailer::ENCRYPTION_SMTPS;
- } elseif ($smtp_encryption === 'tls') {
- $mail->SMTPSecure = PHPMailer\PHPMailer\PHPMailer::ENCRYPTION_STARTTLS;
- }
- $mail->Port = $smtp_port;
-
- // Recipients
- $mail->setFrom($from_email, $from_name);
- $mail->addAddress($recipient_email);
-
- // Content
- $mail->isHTML(true);
- $mail->CharSet = 'UTF-8';
- $mail->Subject = $subject;
- $mail->Body = $message_body;
- $mail->AltBody = wp_strip_all_tags($message_body);
-
- // Send the email
- $mail->send();
-
- wp_send_json_success(['message' => sprintf(__('SMTP test email successfully sent to %s.', 'wheel-of-fortune'), esc_html($recipient_email))]);
-
- } catch (PHPMailer\PHPMailer\Exception $e) {
- // PHPMailer exception
- wp_send_json_error(['message' => sprintf(__('Failed to send email. Error: %s', 'wheel-of-fortune'), esc_html($mail->ErrorInfo))]);
- } catch (Exception $e) {
- // Other exceptions
- wp_send_json_error(['message' => sprintf(__('An unexpected error occurred: %s', 'wheel-of-fortune'), esc_html($e->getMessage()))]);
- }
- }
-
- public function ajax_get_prizes() {
- check_ajax_referer('wheel_public_nonce', 'nonce');
-
- $wheel_id = isset($_POST['wheel_id']) ? intval($_POST['wheel_id']) : 1;
- $prizes = $this->get_wheel_prizes($wheel_id);
-
- wp_send_json_success($prizes);
- }
-
- /**
- * Ustvari kupon z uporabo najboljše metode, določene s testiranjem
- *
- * @param string $code Koda kupona
- * @param WP_User $user Uporabnik, za katerega se ustvari kupon
- * @param float $discount_value Vrednost popusta (v odstotkih)
- * @return int|bool ID kupona ali false v primeru napake
- */
- private function create_coupon_with_best_method($code, $user, $discount_value) {
- // Pridobi najboljšo metodo iz nastavitev
- $best_method = get_option('wheel_best_coupon_method', 'standard_api');
-
- wheel_of_fortune_debug_log("Creating coupon using method: {$best_method}");
-
- switch ($best_method) {
- case 'programmatic':
- // Metoda 2: Programsko ustvarjanje kupona
- try {
- $coupon_data = array(
- 'post_title' => $code,
- 'post_content' => '',
- 'post_status' => 'publish',
- 'post_author' => $user->ID,
- 'post_type' => 'shop_coupon'
- );
-
- $coupon_id = wp_insert_post($coupon_data);
-
- if (!is_wp_error($coupon_id)) {
- // Dodaj meta podatke za kupon
- update_post_meta($coupon_id, 'discount_type', 'percent');
- update_post_meta($coupon_id, 'coupon_amount', $discount_value);
- update_post_meta($coupon_id, 'individual_use', 'yes');
- update_post_meta($coupon_id, 'usage_limit', '1');
- update_post_meta($coupon_id, 'usage_limit_per_user', '1');
- update_post_meta($coupon_id, 'customer_email', array($user->user_email));
- update_post_meta($coupon_id, 'description', __('Wheel of Fortune', 'wheel-of-fortune'));
- // Nastavi veljavnost 10 dni
- update_post_meta($coupon_id, 'date_expires', strtotime('+10 days'));
- return $coupon_id;
- }
- } catch (Exception $e) {
- wheel_of_fortune_debug_log("Error in programmatic method: " . $e->getMessage());
- }
- break;
-
- case 'wc_coupon_extended':
- // Metoda 3: Uporaba WC_Coupon z dodatnimi preverjanji
- try {
- // Preveri, ali koda že obstaja
- $existing_id = wc_get_coupon_id_by_code($code);
- if ($existing_id) {
- wheel_of_fortune_debug_log("Coupon code already exists: {$code}");
- return false;
- }
-
- // Ustvari nov kupon z dodatnimi preverjanji
- $coupon = new WC_Coupon();
- $coupon->set_code($code);
- $coupon->set_description(__('Wheel of Fortune', 'wheel-of-fortune'));
- $coupon->set_discount_type('percent');
- $coupon->set_amount($discount_value);
- $coupon->set_individual_use(true);
- $coupon->set_usage_limit(1);
- $coupon->set_usage_limit_per_user(1);
- $coupon->set_email_restrictions(array($user->user_email));
- // Nastavi veljavnost 10 dni
- $coupon->set_date_expires(strtotime('+10 days'));
- $coupon_id = $coupon->save();
- // Preveri, ali je kupon res ustvarjen
- if ($coupon_id) {
- $verification_id = wc_get_coupon_id_by_code($code);
- if ($verification_id && $verification_id == $coupon_id) {
- return $coupon_id;
- }
- }
- } catch (Exception $e) {
- wheel_of_fortune_debug_log("Error in wc_coupon_extended method: " . $e->getMessage());
- }
- break;
-
- case 'direct_db':
- // Metoda 4: Neposredno vstavljanje v podatkovno bazo
- try {
- global $wpdb;
- // Ustvari nov post tipa shop_coupon
- $wpdb->insert(
- $wpdb->posts,
- array(
- 'post_title' => $code,
- 'post_name' => sanitize_title($code),
- 'post_content' => '',
- 'post_status' => 'publish',
- 'post_author' => $user->ID,
- 'post_type' => 'shop_coupon',
- 'post_date' => current_time('mysql'),
- 'post_date_gmt' => current_time('mysql', 1)
- )
- );
- $coupon_id = $wpdb->insert_id;
- if ($coupon_id) {
- // Dodaj meta podatke za kupon
- $meta_data = array(
- 'discount_type' => 'percent',
- 'coupon_amount' => $discount_value,
- 'individual_use' => 'yes',
- 'usage_limit' => '1',
- 'usage_limit_per_user' => '1',
- 'customer_email' => serialize(array($user->user_email)),
- 'description' => __('Wheel of Fortune', 'wheel-of-fortune'),
- // Nastavi veljavnost 10 dni
- 'date_expires' => strtotime('+10 days')
- );
- foreach ($meta_data as $meta_key => $meta_value) {
- $wpdb->insert(
- $wpdb->postmeta,
- array(
- 'post_id' => $coupon_id,
- 'meta_key' => $meta_key,
- 'meta_value' => $meta_value
- )
- );
- }
- return $coupon_id;
- }
- } catch (Exception $e) {
- wheel_of_fortune_debug_log("Error in direct_db method: " . $e->getMessage());
- }
- break;
-
- case 'standard_api':
- default:
- // Metoda 1: Standardna WooCommerce API metoda (privzeta)
- try {
- $coupon = new WC_Coupon();
- $coupon->set_code($code);
- $coupon->set_description(__('Wheel of Fortune', 'wheel-of-fortune'));
- $coupon->set_discount_type('percent');
- $coupon->set_amount($discount_value);
- $coupon->set_individual_use(true);
- $coupon->set_usage_limit(1);
- $coupon->set_usage_limit_per_user(1);
- $coupon->set_email_restrictions(array($user->user_email));
- // Nastavi veljavnost 10 dni
- $coupon->set_date_expires(strtotime('+10 days'));
- $coupon_id = $coupon->save();
- if ($coupon_id) {
- return $coupon_id;
- }
- } catch (Exception $e) {
- wheel_of_fortune_debug_log("Error in standard_api method: " . $e->getMessage());
- }
- break;
- }
-
- // Če pridemo do sem, je prišlo do napake pri ustvarjanju kupona
- return false;
- }
-
- /**
- * Sends an email notification to the user upon winning a prize.
- *
- * @param int $user_id The ID of the user who won.
- * @param array $prize The prize details array.
- */
- public function send_prize_email($user_id, $prize) {
- // Ne pošlji emaila, če je nagrada "try again"
- if (isset($prize['is_try_again']) && $prize['is_try_again'] == 1) {
- wheel_of_fortune_debug_log("send_prize_email: Email ni poslan za 'try again' nagrado: {$prize['name']}");
- return;
- }
-
- $user = get_userdata($user_id);
- if (!$user) {
- wheel_of_fortune_debug_log("send_prize_email: Uporabnik z ID {$user_id} ni bil najden.");
- return;
- }
-
- // Določi vsebino emaila - uporabi specifično predlogo za nagrado, če obstaja, sicer splošno
- $subject = !empty($prize['email_subject'])
- ? $prize['email_subject']
- : sprintf(__('Congratulations! You won a prize on the Wheel of Fortune - %s', 'wheel-of-fortune'), get_bloginfo('name'));
-
- $body = !empty($prize['email_template'])
- ? $prize['email_template']
- : file_get_contents(WHEEL_OF_FORTUNE_PLUGIN_DIR . 'templates/emails/default-prize-email.html');
-
- // Pripravi nadomestne oznake (placeholders)
- $replacements = [
- '{user_name}' => $user->display_name,
- '{user_email}' => $user->user_email,
- '{prize_name}' => $prize['name'],
- '{prize_description}' => $prize['description'],
- '{redemption_code}' => !empty($prize['redemption_code']) ? $prize['redemption_code'] : __('N/A', 'wheel-of-fortune'),
- '{site_name}' => get_bloginfo('name'),
- '{site_url}' => home_url(),
- '{date}' => date_i18n(get_option('date_format')),
- '{time}' => date_i18n(get_option('time_format')),
- ];
-
- // Zamenjaj oznake v vsebini in zadevi
- $final_subject = str_replace(array_keys($replacements), array_values($replacements), $subject);
- $final_body = str_replace(array_keys($replacements), array_values($replacements), $body);
-
- // Pridobi nastavitve pošiljatelja
- $from_name = get_option('wheel_email_from_name', get_bloginfo('name'));
- $from_email = get_option('wheel_email_from_email', get_bloginfo('admin_email'));
-
- $headers = [
- 'Content-Type: text/html; charset=UTF-8',
- 'From: ' . $from_name . ' <' . $from_email . '>'
- ];
-
- // Preveri, ali je omogočen SMTP
- if (get_option('wheel_smtp_enabled', false)) {
- // Pošlji preko SMTP z uporabo PHPMailer
- require_once ABSPATH . WPINC . '/PHPMailer/PHPMailer.php';
- require_once ABSPATH . WPINC . '/PHPMailer/SMTP.php';
- require_once ABSPATH . WPINC . '/PHPMailer/Exception.php';
-
- $mail = new PHPMailer\PHPMailer\PHPMailer(true);
- try {
- $mail->isSMTP();
- $mail->Host = get_option('wheel_smtp_host');
- $mail->SMTPAuth = !empty(get_option('wheel_smtp_username'));
- $mail->Username = get_option('wheel_smtp_username');
- $mail->Password = get_option('wheel_smtp_password');
- $mail->Port = get_option('wheel_smtp_port', 587);
-
- $smtp_encryption = get_option('wheel_smtp_encryption', 'tls');
- if ($smtp_encryption === 'ssl') {
- $mail->SMTPSecure = PHPMailer\PHPMailer\PHPMailer::ENCRYPTION_SMTPS;
- } elseif ($smtp_encryption === 'tls') {
- $mail->SMTPSecure = PHPMailer\PHPMailer\PHPMailer::ENCRYPTION_STARTTLS;
- }
-
- $mail->setFrom($from_email, $from_name);
- $mail->addAddress($user->user_email, $user->display_name);
-
- $mail->isHTML(true);
- $mail->CharSet = 'UTF-8';
- $mail->Subject = $final_subject;
- $mail->Body = $final_body;
- $mail->AltBody = wp_strip_all_tags($final_body);
-
- $mail->send();
- wheel_of_fortune_debug_log("Email uspešno poslan preko SMTP na {$user->user_email}.");
-
- } catch (Exception $e) {
- wheel_of_fortune_debug_log("Napaka pri pošiljanju emaila preko SMTP: {$mail->ErrorInfo}");
- }
- } else {
- // Pošlji preko standardne wp_mail() funkcije
- if (wp_mail($user->user_email, $final_subject, $final_body, $headers)) {
- wheel_of_fortune_debug_log("Email uspešno poslan preko wp_mail() na {$user->user_email}.");
- } else {
- wheel_of_fortune_debug_log("Napaka pri pošiljanju emaila preko wp_mail().");
- }
- }
- }
-
- public function ajax_update_wheel_product_spins() {
- check_ajax_referer('wof_update_wheel_product_spins');
- if (!current_user_can('manage_options')) {
- wp_send_json_error(__('Nimaš dovoljenja.', 'wheel-of-fortune'));
- }
- global $wpdb;
- $id = isset($_POST['id']) ? intval($_POST['id']) : 0;
- $spins = isset($_POST['spins']) ? intval($_POST['spins']) : 1;
-
- // Debug informacije
- error_log("=== AJAX UPDATE WHEEL PRODUCT SPINS DEBUG ===");
- error_log("POST data: " . print_r($_POST, true));
- error_log("ID: " . $id);
- error_log("Spins: " . $spins);
-
- if ($id > 0 && $spins > 0) {
- $table = $wpdb->prefix . 'wheel_of_fortune_products';
- error_log("Table: " . $table);
-
- $result = $wpdb->update($table, ['spins_per_purchase' => $spins], ['id' => $id], ['%d'], ['%d']);
- error_log("Update result: " . $result);
- error_log("Last SQL query: " . $wpdb->last_query);
- error_log("Last SQL error: " . $wpdb->last_error);
-
- if ($result !== false) {
- wp_send_json_success();
- }
- }
- wp_send_json_error(__('Napaka pri shranjevanju.', 'wheel-of-fortune'));
- }
-
- public function ajax_delete_wheel_product() {
- check_ajax_referer('wof_delete_wheel_product', '_ajax_nonce');
-
- if (!current_user_can('manage_options')) {
- wp_send_json_error(['message' => __('You do not have permission to perform this action.', 'wheel-of-fortune')]);
- }
-
- $id = isset($_POST['id']) ? intval($_POST['id']) : 0;
-
- if (!$id) {
- wp_send_json_error(['message' => __('Invalid ID.', 'wheel-of-fortune')]);
- }
-
- global $wpdb;
- $table_name = $wpdb->prefix . 'wheel_of_fortune_products';
-
- $result = $wpdb->delete($table_name, ['id' => $id]);
-
- if ($result !== false) {
- wp_send_json_success(['message' => __('Product deleted successfully.', 'wheel-of-fortune')]);
- } else {
- wp_send_json_error(['message' => __('Failed to delete product.', 'wheel-of-fortune')]);
- }
- }
-
- public function ajax_migrate_try_again() {
- check_ajax_referer('wheel_admin_nonce', '_ajax_nonce');
-
- if (!current_user_can('manage_options')) {
- wp_send_json_error(['message' => __('You do not have permission to perform this action.', 'wheel-of-fortune')]);
- }
-
- $this->migrate_add_is_try_again_column();
-
- wp_send_json_success(['message' => __('Migration completed successfully. The is_try_again column has been added to the database.', 'wheel-of-fortune')]);
- }
-
- public function ajax_reset_spins_wheel() {
- check_ajax_referer('wheel_admin_nonce', '_ajax_nonce');
-
- if (!current_user_can('manage_options')) {
- wp_send_json_error(['message' => __('You do not have permission to perform this action.', 'wheel-of-fortune')]);
- }
-
- $wheel_id = isset($_POST['wheel_id']) ? intval($_POST['wheel_id']) : 0;
-
- if (!$wheel_id) {
- wp_send_json_error(['message' => __('Wheel ID is required.', 'wheel-of-fortune')]);
- }
-
- global $wpdb;
- $wheels_table = $wpdb->prefix . 'wof_wheels';
- $spins_table = $wpdb->prefix . 'wheel_spins';
-
- // Preveri, če kolo obstaja
- $wheel_exists = $wpdb->get_var($wpdb->prepare("SELECT id FROM $wheels_table WHERE id = %d", $wheel_id));
-
- if (!$wheel_exists) {
- wp_send_json_error(['message' => __('Selected wheel does not exist.', 'wheel-of-fortune')]);
- }
-
- // Ponastavi spine na 0 za vse uporabnike na tem kolesu
- $result = $wpdb->update(
- $spins_table,
- array('spins_available' => 0),
- array('wheel_id' => $wheel_id),
- array('%d'),
- array('%d')
- );
-
- if ($result !== false) {
- wp_send_json_success([
- 'message' => sprintf(__('All spins for wheel ID %d have been successfully reset to 0.', 'wheel-of-fortune'), $wheel_id),
- 'affected_users' => $result
- ]);
- } else {
- wp_send_json_error(['message' => __('An error occurred while resetting spins.', 'wheel-of-fortune')]);
- }
- }
-
- // --- NOVE METODE ZA CRON ---
- public function add_custom_cron_schedules($schedules) {
- // Lahko pustiš custom interval, če ga uporabljaš še kje drugje, sicer ni potreben
- // $schedules['every_2_minutes'] = array(
- // 'interval' => 120,
- // 'display' => __('Every 2 minutes', 'wheel-of-fortune')
- // );
- return $schedules;
- }
-
- public function execute_daily_spin_cron() {
- wheel_of_fortune_debug_log('CRON: "wof_daily_spin_event" triggered.');
- $wheel_id = get_option('wof_daily_spin_wheel_id');
- if (empty($wheel_id)) {
- wheel_of_fortune_debug_log('CRON: No wheel selected for daily spin. Aborting.');
- return;
- }
- $users = get_users(array('fields' => 'ID'));
- wheel_of_fortune_debug_log('CRON: Found ' . count($users) . ' users to process for wheel ID ' . $wheel_id);
- foreach ($users as $user_id) {
- $last_given_meta_key = '_wof_daily_spin_last_given_' . $wheel_id;
- $last_given_timestamp = get_user_meta($user_id, $last_given_meta_key, true);
- // Sprememba: 24 ur (23*HOUR_IN_SECONDS)
- if (empty($last_given_timestamp) || (time() - $last_given_timestamp > 23 * HOUR_IN_SECONDS)) {
- $ok = wheel_of_fortune_add_spins($user_id, 1, $wheel_id);
- if ($ok) {
- update_user_meta($user_id, $last_given_meta_key, time());
- wheel_of_fortune_debug_log("CRON: Assigned spin to user $user_id for wheel $wheel_id. Result: " . var_export($ok, true));
- } else {
- wheel_of_fortune_debug_log("CRON: Failed to assign spin to user $user_id for wheel $wheel_id.");
- }
- } else {
- wheel_of_fortune_debug_log("CRON: User $user_id already received a spin recently. Skipping.");
- }
- }
- }
-
- // ----------------------------
-}
-
-// Initialize plugin
-function wheel_of_fortune() {
- return WheelOfFortune::get_instance();
-}
-wheel_of_fortune();
-wheel_of_fortune();"""
-
-