From 94b354f7fbc880bef41649a29f469aa8f4fc1b9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mark=20Poljan=C5=A1ek?= Date: Thu, 20 Nov 2025 22:49:40 +0100 Subject: [PATCH] Ignore code_export.txt and untrack from repo --- code_export.txt | 6706 ----------------------------------------------- 1 file changed, 6706 deletions(-) delete mode 100644 code_export.txt 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'); -?> - -
-

- - - -
- - -
-
-

- - - - - - - - - - - - - - - - -
- - - -

-
- - - -

-
- - - -

-
-
- -
-

-

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - -

-
- - - -

-
- - - -
- - - -
- - - -
- - - -
- - - -
- - -
- - - -
-

-
-
-
- -
-

- -
-

-
- - - - - - - - - - -
- - - -
- - - -
-

- -

-
-
- -
-

-

-

- - -

-
-
- - -
-

-

-

- - -

-
-
-
-
- - - - - -

- -

-
-
- - """ - - -"./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)); ?>

- - - - - - - - - - - - - - - - - - -
user_email); ?>
- get_var($wpdb->prepare( - "SELECT COUNT(*) FROM {$log_table} WHERE user_id = %d AND wheel_id = %d", - $selected_user_id, $selected_wheel_id - )); - echo esc_html($total_spins); - ?> -
- get_var($wpdb->prepare( - "SELECT spins_available FROM {$spins_table} WHERE user_id = %d AND wheel_id = %d", - $selected_user_id, $selected_wheel_id - )); - echo esc_html($spins ?: 0); - ?> -
- -

- - -

- - - - - - - - - - - - - - - - - - - - - - - - -
- ' . 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)); ?>

- - - - - - - - - - - - - - - - - - -
user_email); ?>
- get_var($wpdb->prepare( - "SELECT COUNT(*) FROM {$log_table} WHERE user_id = %d AND wheel_id = %d", - $selected_user_id, $selected_wheel_id - )); - echo esc_html($total_spins); - ?> -
- - - -

- - -

- - - - - - - - - - - - - - - - - - - - - - - - -
- ' . 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); ?> -
-
- - -
-
- -
-
- -
-
- -
-
- - -
""" - - -"./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 ''; - } - - $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$s
  • Host: %3$s
  • Port: %4$s
  • Encryption: %5$s
  • Username: %6$s
  • Sender Name: %7$s
  • Sender 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();""" - -