6707 lines
264 KiB
Plaintext
6707 lines
264 KiB
Plaintext
"./admin/coupon-test.php" :
|
||
"""
|
||
<?php
|
||
/**
|
||
* Testna skripta za preverjanje različnih načinov ustvarjanja WooCommerce kuponov
|
||
*/
|
||
|
||
// Prepreči neposreden dostop
|
||
if (!defined('ABSPATH')) {
|
||
exit;
|
||
}
|
||
|
||
/**
|
||
* Razred za testiranje različnih metod ustvarjanja WooCommerce kuponov
|
||
*/
|
||
class WheelCouponTester {
|
||
|
||
/**
|
||
* Zažene različne teste za ustvarjanje kuponov
|
||
*
|
||
* @return array Rezultati testov
|
||
*/
|
||
public static function run_tests() {
|
||
$results = array(
|
||
'success' => 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" :
|
||
"""
|
||
<?php
|
||
/**
|
||
* Admin page for editing a single wheel and its prizes
|
||
*/
|
||
if (!defined('ABSPATH')) exit;
|
||
|
||
// Handle form submissions
|
||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
|
||
if ($_POST['action'] === 'add_prize' && check_admin_referer('wheel_prizes_nonce')) {
|
||
global $wpdb;
|
||
$prizes_table = $wpdb->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 '<div class="notice notice-success is-dismissible"><p>' . __('Prize added successfully!', 'wheel-of-fortune') . '</p></div>';
|
||
} else {
|
||
echo '<div class="notice notice-error is-dismissible"><p>' . __('Error adding prize. Please try again.', 'wheel-of-fortune') . '</p></div>';
|
||
}
|
||
} else {
|
||
echo '<div class="notice notice-error is-dismissible"><p>' . __('Please fill in all required fields.', 'wheel-of-fortune') . '</p></div>';
|
||
}
|
||
} 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 '<div class="notice notice-success is-dismissible"><p>' . __('Prize updated successfully!', 'wheel-of-fortune') . '</p></div>';
|
||
} else {
|
||
echo '<div class="notice notice-error is-dismissible"><p>' . __('Error updating prize. Please try again.', 'wheel-of-fortune') . '</p></div>';
|
||
}
|
||
} else {
|
||
echo '<div class="notice notice-error is-dismissible"><p>' . __('Please fill in all required fields.', 'wheel-of-fortune') . '</p></div>';
|
||
}
|
||
}
|
||
}
|
||
|
||
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 '<div class="notice notice-error is-dismissible"><p>' . __('Napaka: Tabela za produkte ne obstaja. Prosimo, deaktivirajte in ponovno aktivirajte plugin.', 'wheel-of-fortune') . '</p></div>';
|
||
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 '<div class="notice notice-error is-dismissible"><p>' . __('Napaka: Izbrano kolo ne obstaja.', 'wheel-of-fortune') . '</p></div>';
|
||
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 '<div class="notice notice-error is-dismissible"><p>' . __('Napaka: Izbrani produkt ne obstaja.', 'wheel-of-fortune') . '</p></div>';
|
||
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 '<div class="notice notice-success is-dismissible"><p>' . __('Produkt je bil uspešno dodan ali posodobljen.', 'wheel-of-fortune') . '</p></div>';
|
||
} else {
|
||
echo '<div class="notice notice-error is-dismissible"><p>' . __('Napaka pri dodajanju produkta. Preveri vnos.', 'wheel-of-fortune') . '</p></div>';
|
||
}
|
||
} else {
|
||
error_log("Validation failed - Wheel ID: $wheel_id, Product ID: $product_id, Spins: $spins_per_purchase");
|
||
echo '<div class="notice notice-error is-dismissible"><p>' . __('Napaka pri dodajanju produkta. Preveri vnos.', 'wheel-of-fortune') . '</p></div>';
|
||
}
|
||
} 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 '<div class="notice notice-success is-dismissible"><p>' . __('Produkt je bil izbrisan.', 'wheel-of-fortune') . '</p></div>';
|
||
}
|
||
}
|
||
}
|
||
|
||
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 '<div class="notice notice-error"><p>' . __('Wheel not found.', 'wheel-of-fortune') . '</p></div>';
|
||
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();
|
||
}
|
||
|
||
?>
|
||
|
||
<div class="wrap wheel-admin-page">
|
||
<h1><?php printf(__('Editing Wheel: %s', 'wheel-of-fortune'), esc_html($wheel['name'])); ?></h1>
|
||
<a href="<?php echo admin_url('admin.php?page=wof-wheels'); ?>">← <?php _e('Back to all wheels', 'wheel-of-fortune'); ?></a>
|
||
|
||
<hr class="wp-header-end">
|
||
|
||
<!-- Gumb za migracijo is_try_again stolpca -->
|
||
<div class="notice notice-info">
|
||
<p><strong><?php _e('Database Migration', 'wheel-of-fortune'); ?>:</strong>
|
||
<?php _e('If you encounter "Unknown column is_try_again" error, click the button below to add the missing column to the database.', 'wheel-of-fortune'); ?>
|
||
<button id="migrate-try-again-btn" class="button button-secondary" style="margin-left: 10px;">
|
||
<?php _e('Add is_try_again Column', 'wheel-of-fortune'); ?>
|
||
</button>
|
||
<span id="migrate-result" style="margin-left: 10px;"></span>
|
||
</p>
|
||
</div>
|
||
|
||
<div class="wheel-card">
|
||
<h2><?php echo esc_html__('Prizes for this Wheel', 'wheel-of-fortune'); ?></h2>
|
||
|
||
<?php if ($total_probability > 1): ?>
|
||
<div class="notice notice-error"><p><?php printf(__('Warning: The total probability is %s, which is greater than 1 (100%%). Please adjust.', 'wheel-of-fortune'), '<strong>' . esc_html($total_probability) . '</strong>'); ?></p></div>
|
||
<?php elseif ($total_probability > 0 && $total_probability < 1): ?>
|
||
<div class="notice notice-warning"><p><?php printf(__('Notice: The total probability is %s, which is less than 1 (100%%).', 'wheel-of-fortune'), '<strong>' . esc_html($total_probability) . '</strong>'); ?></p></div>
|
||
<?php endif; ?>
|
||
|
||
<p><button class="button button-primary add-new-prize"><?php _e('Add New Prize', 'wheel-of-fortune'); ?></button></p>
|
||
|
||
<table class="wheel-prizes-table widefat fixed striped">
|
||
<thead>
|
||
<tr>
|
||
<th><?php _e('ID', 'wheel-of-fortune'); ?></th>
|
||
<th><?php _e('Name', 'wheel-of-fortune'); ?></th>
|
||
<th><?php _e('Description', 'wheel-of-fortune'); ?></th>
|
||
<th><?php _e('Probability', 'wheel-of-fortune'); ?></th>
|
||
<th><?php _e('Status', 'wheel-of-fortune'); ?></th>
|
||
<th><?php _e('Actions', 'wheel-of-fortune'); ?></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<?php if (empty($prizes)): ?>
|
||
<tr><td colspan="6"><?php _e('No prizes found. Add your first prize using the button above.', 'wheel-of-fortune'); ?></td></tr>
|
||
<?php else: ?>
|
||
<?php foreach ($prizes as $prize): ?>
|
||
<tr>
|
||
<td><?php echo esc_html($prize['id']); ?></td>
|
||
<td><?php echo esc_html($prize['name']); ?></td>
|
||
<td><?php echo esc_html($prize['description']); ?></td>
|
||
<td><?php echo esc_html($prize['probability']); ?></td>
|
||
<td><?php echo $prize['is_active'] ? __('Active', 'wheel-of-fortune') : __('Inactive', 'wheel-of-fortune'); ?></td>
|
||
<td>
|
||
<button class="button edit-prize" data-id="<?php echo esc_attr($prize['id']); ?>"><?php _e('Edit', 'wheel-of-fortune'); ?></button>
|
||
<button class="button delete-prize" data-id="<?php echo esc_attr($prize['id']); ?>"><?php _e('Delete', 'wheel-of-fortune'); ?></button>
|
||
</td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
<?php endif; ?>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
<div class="wheel-card">
|
||
<h2><?php echo esc_html__('Add New Prize to this Wheel', 'wheel-of-fortune'); ?></h2>
|
||
<form method="post" action="">
|
||
<?php wp_nonce_field('wheel_prizes_nonce'); ?>
|
||
<input type="hidden" name="action" value="add_prize">
|
||
<input type="hidden" name="wheel_id" value="<?php echo esc_attr($wheel_id); ?>">
|
||
<table class="wheel-form-table">
|
||
<?php include 'partials/prize-form-fields.php'; ?>
|
||
</table>
|
||
<p class="submit"><input type="submit" class="button button-primary" value="<?php esc_attr_e('Add Prize', 'wheel-of-fortune'); ?>"></p>
|
||
</form>
|
||
</div>
|
||
|
||
<div class="wheel-card">
|
||
<h2><?php echo esc_html__('Produkti & spini', 'wheel-of-fortune'); ?></h2>
|
||
<table class="wheel-products-table widefat fixed striped">
|
||
<thead>
|
||
<tr>
|
||
<th><?php _e('Produkt', 'wheel-of-fortune'); ?></th>
|
||
<th><?php _e('Število spinov na nakup', 'wheel-of-fortune'); ?></th>
|
||
<th><?php _e('Akcije', 'wheel-of-fortune'); ?></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<?php if (empty($products)): ?>
|
||
<tr><td colspan="3"><?php _e('Ni povezanih produktov.', 'wheel-of-fortune'); ?></td></tr>
|
||
<?php else: ?>
|
||
<?php foreach ($products as $prod): ?>
|
||
<?php $wc_product = wc_get_product($prod['product_id']); ?>
|
||
<tr>
|
||
<td><?php echo $wc_product ? esc_html($wc_product->get_name()) : esc_html($prod['product_id']); ?></td>
|
||
<td class="spins-editable" data-id="<?php echo esc_attr($prod['id']); ?>"><?php echo intval($prod['spins_per_purchase']); ?></td>
|
||
<td>
|
||
<button class="button edit-wheel-product" data-id="<?php echo esc_attr($prod['id']); ?>"><?php _e('Uredi', 'wheel-of-fortune'); ?></button>
|
||
<button class="button delete-wheel-product" data-id="<?php echo esc_attr($prod['id']); ?>"><?php _e('Izbriši', 'wheel-of-fortune'); ?></button>
|
||
</td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
<?php endif; ?>
|
||
</tbody>
|
||
</table>
|
||
<h3><?php _e('Dodaj produkt', 'wheel-of-fortune'); ?></h3>
|
||
<form method="post" action="">
|
||
<?php wp_nonce_field('wheel_products_nonce'); ?>
|
||
<input type="hidden" name="action" value="add_wheel_product">
|
||
<input type="hidden" name="wheel_id" value="<?php echo esc_attr($wheel_id); ?>">
|
||
<p>
|
||
<label for="product_id"><?php _e('Izberi produkt:', 'wheel-of-fortune'); ?></label>
|
||
<select name="product_id" id="product_id" required>
|
||
<option value=""><?php _e('Izberi produkt', 'wheel-of-fortune'); ?></option>
|
||
<?php foreach ($all_products as $product): ?>
|
||
<option value="<?php echo esc_attr($product->get_id()); ?>"><?php echo esc_html($product->get_name()); ?></option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
</p>
|
||
<p>
|
||
<label for="spins_per_purchase"><?php _e('Število spinov na nakup:', 'wheel-of-fortune'); ?></label>
|
||
<input type="number" name="spins_per_purchase" id="spins_per_purchase" min="1" value="1" required style="width: 80px;">
|
||
</p>
|
||
<p class="submit">
|
||
<input type="submit" class="button button-primary" value="<?php esc_attr_e('Dodaj', 'wheel-of-fortune'); ?>">
|
||
</p>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Edit Prize Modal (ostaja večinoma nespremenjen, wheel_id se doda dinamično z JS) -->
|
||
<div id="edit-prize-modal" style="display: none; position: fixed; z-index: 1000; left: 0; top: 0; width: 100%; height: 100%; overflow: auto; background-color: rgba(0,0,0,0.4);" data-wheel-id="<?php echo esc_attr($wheel_id); ?>">
|
||
<div style="background-color: #fefefe; margin: 5% auto; padding: 20px; border: 1px solid #888; width: 60%; max-width: 700px;">
|
||
<span class="close" style="color: #aaa; float: right; font-size: 28px; font-weight: bold; cursor: pointer;">×</span>
|
||
<h2><?php echo esc_html__('Edit Prize', 'wheel-of-fortune'); ?></h2>
|
||
<form id="edit-prize-form" method="post" action="">
|
||
<?php wp_nonce_field('wheel_prizes_nonce'); ?>
|
||
<input type="hidden" name="action" value="edit_prize">
|
||
<input type="hidden" id="edit-prize-id" name="prize_id" value="">
|
||
<input type="hidden" id="edit-wheel-id" name="wheel_id" value="<?php echo esc_attr($wheel_id); ?>">
|
||
<table class="wheel-form-table">
|
||
<tr><th scope="row"><label for="edit-prize-name"><?php _e('Prize Name', 'wheel-of-fortune'); ?></label></th><td><input type="text" id="edit-prize-name" name="prize_name" class="regular-text" required></td></tr>
|
||
<tr><th scope="row"><label for="edit-prize-description"><?php _e('Description', 'wheel-of-fortune'); ?></label></th><td><textarea id="edit-prize-description" name="prize_description" rows="3" class="large-text"></textarea></td></tr>
|
||
<tr><th scope="row"><label for="edit-prize-probability"><?php _e('Probability', 'wheel-of-fortune'); ?></label></th><td><input type="number" id="edit-prize-probability" name="prize_probability" step="any" min="0" max="1" required><p class="description"><?php _e('Enter a value between 0 and 1. Use 0 for prizes that cannot be won.', 'wheel-of-fortune'); ?></p></td></tr>
|
||
<tr><th scope="row"><?php _e('Status', 'wheel-of-fortune'); ?></th><td><label for="edit-prize-is-active"><input type="checkbox" id="edit-prize-is-active" name="prize_is_active" value="1"><?php _e('Prize is active', 'wheel-of-fortune'); ?></label></td></tr>
|
||
<tr><th scope="row"><label for="edit-prize-redemption-code"><?php _e('Redemption Code', 'wheel-of-fortune'); ?></label></th><td><input type="text" id="edit-prize-redemption-code" name="prize_redemption_code" class="regular-text"><p class="description"><?php _e('Optional code for the user to redeem the prize.', 'wheel-of-fortune'); ?></p></td></tr>
|
||
<tr><th scope="row"><label for="edit-prize-is-discount"><?php _e('Is Discount?', 'wheel-of-fortune'); ?></label></th><td><input type="checkbox" id="edit-prize-is-discount" name="prize_is_discount" value="1"><p class="description"><?php _e('Check if the prize is a discount.', 'wheel-of-fortune'); ?></p></td></tr>
|
||
<tr><th scope="row"><label for="edit-prize-discount-value"><?php _e('Discount Value (%)', 'wheel-of-fortune'); ?></label></th><td><input type="number" id="edit-prize-discount-value" name="prize_discount_value" step="0.01" min="0" max="100"><p class="description"><?php _e('Enter the discount value in %.', 'wheel-of-fortune'); ?></p></td></tr>
|
||
<tr><th scope="row"><label for="edit-prize-is-try-again"><?php _e('Is Try Again?', 'wheel-of-fortune'); ?></label></th><td><input type="checkbox" id="edit-prize-is-try-again" name="prize_is_try_again" value="1"><p class="description"><?php _e('Check if the prize is a try again.', 'wheel-of-fortune'); ?></p></td></tr>
|
||
<tr><th scope="row"><label for="edit-prize-email-subject"><?php _e('Email Subject', 'wheel-of-fortune'); ?></label></th><td><input type="text" id="edit-prize-email-subject" name="prize_email_subject" class="large-text"><p class="description"><?php _e('Subject for this prize\'s email. If empty, the default subject will be used.', 'wheel-of-fortune'); ?></p></td></tr>
|
||
<tr><th scope="row"><label for="edit-prize-email-template"><?php _e('Email Template', 'wheel-of-fortune'); ?></label></th><td><textarea id="edit-prize-email-template" name="prize_email_template" rows="10" class="large-text code"></textarea><p class="description"><?php _e('Available template tags:', 'wheel-of-fortune'); ?> <code>{user_name}</code>, <code>{prize_name}</code>, etc.</p></td></tr>
|
||
</table>
|
||
<p class="submit"><input type="submit" class="button button-primary" value="<?php esc_attr_e('Save Changes', 'wheel-of-fortune'); ?>"></p>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
jQuery(document).ready(function($) {
|
||
$('.delete-wheel-product').on('click', function(e) {
|
||
e.preventDefault();
|
||
if (!confirm('Ali res želiš izbrisati ta produkt?')) return;
|
||
var row = $(this).closest('tr');
|
||
var id = $(this).data('id');
|
||
$.post(ajaxurl, {
|
||
action: 'wof_delete_wheel_product',
|
||
id: id,
|
||
_ajax_nonce: '<?php echo wp_create_nonce('wof_delete_wheel_product'); ?>'
|
||
}, function(response) {
|
||
if (response.success) {
|
||
row.fadeOut(300, function() { $(this).remove(); });
|
||
} else {
|
||
alert(response.data || 'Napaka pri brisanju.');
|
||
}
|
||
});
|
||
});
|
||
|
||
$('.spins-editable').on('click', function() {
|
||
var td = $(this);
|
||
if (td.find('input').length) return;
|
||
var current = td.text();
|
||
var id = td.data('id');
|
||
var input = $('<input type="number" min="1" style="width:60px;">').val(current);
|
||
td.html(input);
|
||
input.focus();
|
||
input.on('blur', function() {
|
||
var val = input.val();
|
||
if (val && val != current) {
|
||
$.post(ajaxurl, {
|
||
action: 'wof_update_wheel_product_spins',
|
||
id: id,
|
||
spins: val,
|
||
_ajax_nonce: '<?php echo wp_create_nonce('wof_update_wheel_product_spins'); ?>'
|
||
}, function(response) {
|
||
if (response.success) {
|
||
td.text(val);
|
||
} else {
|
||
alert(response.data || 'Napaka pri shranjevanju.');
|
||
td.text(current);
|
||
}
|
||
});
|
||
} else {
|
||
td.text(current);
|
||
}
|
||
});
|
||
});
|
||
});
|
||
</script>
|
||
|
||
<script>
|
||
jQuery(document).ready(function($) {
|
||
// Gumb za migracijo is_try_again stolpca
|
||
$('#migrate-try-again-btn').on('click', function(e) {
|
||
e.preventDefault();
|
||
|
||
const button = $(this);
|
||
const resultSpan = $('#migrate-result');
|
||
|
||
button.prop('disabled', true).text('<?php _e('Running migration...', 'wheel-of-fortune'); ?>');
|
||
resultSpan.html('');
|
||
|
||
$.ajax({
|
||
url: ajaxurl,
|
||
method: 'POST',
|
||
data: {
|
||
action: 'wheel_migrate_try_again',
|
||
_ajax_nonce: '<?php echo wp_create_nonce('wheel_admin_nonce'); ?>'
|
||
},
|
||
success: function(response) {
|
||
if (response.success) {
|
||
resultSpan.html('<span style="color: green;">✓ ' + response.data.message + '</span>');
|
||
button.text('<?php _e('Migration Completed', 'wheel-of-fortune'); ?>').addClass('button-primary');
|
||
} else {
|
||
resultSpan.html('<span style="color: red;">✗ ' + (response.data.message || '<?php _e('Migration failed', 'wheel-of-fortune'); ?>') + '</span>');
|
||
button.prop('disabled', false).text('<?php _e('Add is_try_again Column', 'wheel-of-fortune'); ?>');
|
||
}
|
||
},
|
||
error: function() {
|
||
resultSpan.html('<span style="color: red;">✗ <?php _e('Network error occurred', 'wheel-of-fortune'); ?></span>');
|
||
button.prop('disabled', false).text('<?php _e('Add is_try_again Column', 'wheel-of-fortune'); ?>');
|
||
}
|
||
});
|
||
});
|
||
});
|
||
</script> """
|
||
|
||
|
||
"./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('<p>' + response.data.message + '</p>').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('<p>' + errorMessage + '</p>').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('<p>' + errorMessage + '</p>').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(`<h3>Congratulations!</h3><p>You've won: <strong>${prize.name}</strong></p>`);
|
||
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(`<p>${response.data.message || 'An error occurred.'}</p>`);
|
||
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(`<p>${errorMsg}</p>`);
|
||
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" :
|
||
"""
|
||
<?php
|
||
/**
|
||
* Reusable form fields for adding/editing prizes
|
||
*/
|
||
if (!defined('ABSPATH')) exit;
|
||
?>
|
||
<tr>
|
||
<th scope="row"><label for="prize_name"><?php _e('Prize Name', 'wheel-of-fortune'); ?></label></th>
|
||
<td><input type="text" id="prize_name" name="prize_name" class="regular-text" required></td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row"><label for="prize_description"><?php _e('Description', 'wheel-of-fortune'); ?></label></th>
|
||
<td><textarea id="prize_description" name="prize_description" rows="3" class="large-text"></textarea></td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row"><label for="prize_probability"><?php _e('Probability', 'wheel-of-fortune'); ?></label></th>
|
||
<td>
|
||
<input type="number" id="prize_probability" name="prize_probability" step="any" min="0" max="1" required>
|
||
<p class="description"><?php _e('Enter a value between 0 and 1 (e.g., 0.1 for 10% chance). Use 0 for prizes that cannot be won.', 'wheel-of-fortune'); ?></p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row"><?php _e('Status', 'wheel-of-fortune'); ?></th>
|
||
<td>
|
||
<label for="prize_is_active">
|
||
<input type="checkbox" id="prize_is_active" name="prize_is_active" value="1" checked>
|
||
<?php _e('Prize is active', 'wheel-of-fortune'); ?>
|
||
</label>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row"><label for="prize_redemption_code"><?php _e('Redemption Code', 'wheel-of-fortune'); ?></label></th>
|
||
<td>
|
||
<input type="text" id="prize_redemption_code" name="prize_redemption_code" class="regular-text">
|
||
<p class="description"><?php _e('Optional code for the user to redeem the prize.', 'wheel-of-fortune'); ?></p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row"><label for="prize_email_subject"><?php _e('Email Subject', 'wheel-of-fortune'); ?></label></th>
|
||
<td>
|
||
<input type="text" id="prize_email_subject" name="prize_email_subject" class="large-text">
|
||
<p class="description"><?php _e('Subject for this prize\'s email. If empty, the default subject will be used.', 'wheel-of-fortune'); ?></p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row"><label for="prize_email_template"><?php _e('Email Template', 'wheel-of-fortune'); ?></label></th>
|
||
<td>
|
||
<textarea id="prize_email_template" name="prize_email_template" rows="10" class="large-text code"></textarea>
|
||
<p class="description"><?php _e('Content for this prize\'s email. Leave blank for default template.', 'wheel-of-fortune'); ?></p>
|
||
<p><?php _e('Available template tags:', 'wheel-of-fortune'); ?></p>
|
||
<ul class="wheel-template-tags">
|
||
<li><code>{user_name}</code>, <code>{user_email}</code>, <code>{prize_name}</code>, <code>{prize_description}</code>, <code>{redemption_code}</code>, <code>{site_name}</code>, <code>{site_url}</code>, <code>{date}</code>, <code>{time}</code></li>
|
||
</ul>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row"><label for="prize_is_discount"><?php _e('Je discount?', 'wheel-of-fortune'); ?></label></th>
|
||
<td>
|
||
<input type="checkbox" id="prize_is_discount" name="prize_is_discount" value="1">
|
||
<p class="description"><?php _e('Označi, če je nagrada popust.', 'wheel-of-fortune'); ?></p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row"><label for="prize_discount_value"><?php _e('Vrednost kupona (%)', 'wheel-of-fortune'); ?></label></th>
|
||
<td>
|
||
<input type="number" id="prize_discount_value" name="prize_discount_value" step="0.01" min="0" max="100">
|
||
<p class="description"><?php _e('Vnesi vrednost popusta v %.', 'wheel-of-fortune'); ?></p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row"><label for="prize_is_try_again"><?php _e('Try Again?', 'wheel-of-fortune'); ?></label></th>
|
||
<td>
|
||
<input type="checkbox" id="prize_is_try_again" name="prize_is_try_again" value="1">
|
||
<p class="description"><?php _e('Označi, če je ta nagrada "Try Again" (ponovni poskus).', 'wheel-of-fortune'); ?></p>
|
||
</td>
|
||
</tr>"""
|
||
|
||
|
||
"./admin/settings-page.php" :
|
||
"""
|
||
<?php
|
||
/**
|
||
* Administratorska stran za nastavitve vtičnika Kolo Sreče
|
||
*/
|
||
|
||
// Prepreči neposreden dostop
|
||
if (!defined('ABSPATH')) {
|
||
exit;
|
||
}
|
||
|
||
global $wpdb;
|
||
|
||
// Preveri, če ima uporabnik pravice za dostop
|
||
if (!current_user_can('manage_options')) {
|
||
return;
|
||
}
|
||
|
||
// Shrani nastavitve
|
||
if (isset($_POST['wheel_save_settings']) && check_admin_referer('wheel_settings_nonce')) {
|
||
// Časovna omejitev
|
||
$cooldown_minutes = isset($_POST['wheel_cooldown_minutes']) ? intval($_POST['wheel_cooldown_minutes']) : 0;
|
||
update_option('wheel_cooldown_minutes', $cooldown_minutes);
|
||
|
||
// Maksimalno število spinov
|
||
$max_spins = isset($_POST['wheel_max_spins']) ? intval($_POST['wheel_max_spins']) : 0;
|
||
update_option('wheel_max_spins', $max_spins);
|
||
|
||
// Email obvestila
|
||
$send_emails = isset($_POST['wheel_send_emails']) ? true : false;
|
||
update_option('wheel_send_emails', $send_emails);
|
||
|
||
// SMTP nastavitve
|
||
$smtp_enabled = isset($_POST['wheel_smtp_enabled']) ? true : false;
|
||
update_option('wheel_smtp_enabled', $smtp_enabled);
|
||
|
||
$smtp_host = isset($_POST['wheel_smtp_host']) ? sanitize_text_field($_POST['wheel_smtp_host']) : '';
|
||
update_option('wheel_smtp_host', $smtp_host);
|
||
|
||
$smtp_port = isset($_POST['wheel_smtp_port']) ? sanitize_text_field($_POST['wheel_smtp_port']) : '587';
|
||
update_option('wheel_smtp_port', $smtp_port);
|
||
|
||
$smtp_encryption = isset($_POST['wheel_smtp_encryption']) ? sanitize_text_field($_POST['wheel_smtp_encryption']) : 'tls';
|
||
update_option('wheel_smtp_encryption', $smtp_encryption);
|
||
|
||
$smtp_username = isset($_POST['wheel_smtp_username']) ? sanitize_text_field($_POST['wheel_smtp_username']) : '';
|
||
update_option('wheel_smtp_username', $smtp_username);
|
||
|
||
// POPRAVEK: Gesla se ne sme sanitizirati s sanitize_text_field, ker lahko vsebuje posebne znake.
|
||
$smtp_password = isset($_POST['wheel_smtp_password']) ? wp_unslash($_POST['wheel_smtp_password']) : '';
|
||
update_option('wheel_smtp_password', $smtp_password);
|
||
|
||
$email_from_name = isset($_POST['wheel_email_from_name']) ? sanitize_text_field($_POST['wheel_email_from_name']) : get_bloginfo('name');
|
||
update_option('wheel_email_from_name', $email_from_name);
|
||
|
||
$email_from_email = isset($_POST['wheel_email_from_email']) ? sanitize_email($_POST['wheel_email_from_email']) : get_bloginfo('admin_email');
|
||
update_option('wheel_email_from_email', $email_from_email);
|
||
|
||
// Izdelki, ki podeljujejo spine
|
||
$spin_products = array();
|
||
if (isset($_POST['product_ids']) && isset($_POST['product_spins'])) {
|
||
$product_ids = $_POST['product_ids'];
|
||
$product_spins = $_POST['product_spins'];
|
||
|
||
foreach ($product_ids as $key => $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');
|
||
?>
|
||
|
||
<div class="wrap wheel-admin-page">
|
||
<h1><?php echo esc_html__('Kolo Sreče - Nastavitve', 'wheel-of-fortune'); ?></h1>
|
||
|
||
<h2 class="nav-tab-wrapper">
|
||
<a href="#" class="nav-tab nav-tab-active" data-target="general-settings"><?php echo esc_html__('Splošne nastavitve', 'wheel-of-fortune'); ?></a>
|
||
<a href="#" class="nav-tab" data-target="product-settings"><?php echo esc_html__('Izdelki', 'wheel-of-fortune'); ?></a>
|
||
<a href="#" class="nav-tab" data-target="wheel-preview"><?php echo esc_html__('Predogled', 'wheel-of-fortune'); ?></a>
|
||
</h2>
|
||
|
||
<form method="post" action="">
|
||
<?php wp_nonce_field('wheel_settings_nonce'); ?>
|
||
|
||
<div id="general-settings" class="wheel-tab-content">
|
||
<div class="wheel-card">
|
||
<h2><?php echo esc_html__('Splošne nastavitve', 'wheel-of-fortune'); ?></h2>
|
||
|
||
<table class="wheel-form-table">
|
||
<tr>
|
||
<th scope="row">
|
||
<label for="wheel_cooldown_minutes"><?php echo esc_html__('Časovna omejitev (minute)', 'wheel-of-fortune'); ?></label>
|
||
</th>
|
||
<td>
|
||
<input type="number" id="wheel_cooldown_minutes" name="wheel_cooldown_minutes" value="<?php echo esc_attr($cooldown_minutes); ?>" min="0" step="1" />
|
||
<p class="description"><?php echo esc_html__('Število minut, ki mora preteči med dvema vrtljajema. Vrednost 0 pomeni brez omejitve.', 'wheel-of-fortune'); ?></p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row">
|
||
<label for="wheel_max_spins"><?php echo esc_html__('Maksimalno število spinov', 'wheel-of-fortune'); ?></label>
|
||
</th>
|
||
<td>
|
||
<input type="number" id="wheel_max_spins" name="wheel_max_spins" value="<?php echo esc_attr($max_spins); ?>" min="0" step="1" />
|
||
<p class="description"><?php echo esc_html__('Maksimalno število spinov, ki jih lahko ima uporabnik. Vrednost 0 pomeni brez omejitve.', 'wheel-of-fortune'); ?></p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row">
|
||
<label for="wof_daily_spin_wheel_id"><?php echo esc_html__('Kolo za dnevni spin', 'wheel-of-fortune'); ?></label>
|
||
</th>
|
||
<td>
|
||
<select id="wof_daily_spin_wheel_id" name="wof_daily_spin_wheel_id">
|
||
<option value=""><?php echo esc_html__('Izberi kolo', 'wheel-of-fortune'); ?></option>
|
||
<?php foreach ($wheels as $wheel): ?>
|
||
<option value="<?php echo esc_attr($wheel['id']); ?>" <?php selected($daily_spin_wheel_id, $wheel['id']); ?>><?php echo esc_html($wheel['name']); ?></option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
<p class="description"><?php echo esc_html__('Vsi registrirani uporabniki bodo vsakih 24 ur prejeli 1 spin na izbranem kolesu.', 'wheel-of-fortune'); ?></p>
|
||
</td>
|
||
</tr>
|
||
<!-- Možnost za pošiljanje e-pošte je odstranjena, saj se e-pošta pošlje vedno -->
|
||
<input type="hidden" name="wheel_send_emails" value="1" />
|
||
</table>
|
||
</div>
|
||
|
||
<div class="wheel-card">
|
||
<h2><?php echo esc_html__('SMTP nastavitve', 'wheel-of-fortune'); ?></h2>
|
||
<p class="description"><?php echo esc_html__('Nastavitve za pošiljanje e-pošte preko SMTP strežnika. Če so te nastavitve omogočene, bo vtičnik uporabljal SMTP namesto privzete WordPress funkcije za pošiljanje e-pošte.', 'wheel-of-fortune'); ?></p>
|
||
|
||
<table class="wheel-form-table">
|
||
<tr>
|
||
<th scope="row">
|
||
<?php echo esc_html__('Uporabi SMTP', 'wheel-of-fortune'); ?>
|
||
</th>
|
||
<td>
|
||
<label for="wheel_smtp_enabled">
|
||
<input type="checkbox" id="wheel_smtp_enabled" name="wheel_smtp_enabled" <?php checked(get_option('wheel_smtp_enabled', false)); ?> />
|
||
<?php echo esc_html__('Omogoči SMTP za pošiljanje e-pošte', 'wheel-of-fortune'); ?>
|
||
</label>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row">
|
||
<label for="wheel_smtp_host"><?php echo esc_html__('SMTP gostitelj', 'wheel-of-fortune'); ?></label>
|
||
</th>
|
||
<td>
|
||
<input type="text" id="wheel_smtp_host" name="wheel_smtp_host" value="<?php echo esc_attr(get_option('wheel_smtp_host', '')); ?>" class="regular-text" />
|
||
<p class="description"><?php echo esc_html__('Npr. smtp.gmail.com', 'wheel-of-fortune'); ?></p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row">
|
||
<label for="wheel_smtp_port"><?php echo esc_html__('SMTP vrata', 'wheel-of-fortune'); ?></label>
|
||
</th>
|
||
<td>
|
||
<input type="text" id="wheel_smtp_port" name="wheel_smtp_port" value="<?php echo esc_attr(get_option('wheel_smtp_port', '587')); ?>" />
|
||
<p class="description"><?php echo esc_html__('Običajno 587 (TLS) ali 465 (SSL)', 'wheel-of-fortune'); ?></p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row">
|
||
<label for="wheel_smtp_encryption"><?php echo esc_html__('Šifriranje', 'wheel-of-fortune'); ?></label>
|
||
</th>
|
||
<td>
|
||
<select id="wheel_smtp_encryption" name="wheel_smtp_encryption">
|
||
<option value="tls" <?php selected(get_option('wheel_smtp_encryption', 'tls'), 'tls'); ?>><?php echo esc_html__('TLS', 'wheel-of-fortune'); ?></option>
|
||
<option value="ssl" <?php selected(get_option('wheel_smtp_encryption', 'tls'), 'ssl'); ?>><?php echo esc_html__('SSL', 'wheel-of-fortune'); ?></option>
|
||
<option value="" <?php selected(get_option('wheel_smtp_encryption', 'tls'), ''); ?>><?php echo esc_html__('Brez', 'wheel-of-fortune'); ?></option>
|
||
</select>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row">
|
||
<label for="wheel_smtp_username"><?php echo esc_html__('SMTP uporabniško ime', 'wheel-of-fortune'); ?></label>
|
||
</th>
|
||
<td>
|
||
<input type="text" id="wheel_smtp_username" name="wheel_smtp_username" value="<?php echo esc_attr(get_option('wheel_smtp_username', '')); ?>" class="regular-text" />
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row">
|
||
<label for="wheel_smtp_password"><?php echo esc_html__('SMTP geslo', 'wheel-of-fortune'); ?></label>
|
||
</th>
|
||
<td>
|
||
<input type="password" id="wheel_smtp_password" name="wheel_smtp_password" value="<?php echo esc_attr(get_option('wheel_smtp_password', '')); ?>" class="regular-text" />
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row">
|
||
<label for="wheel_email_from_name"><?php echo esc_html__('Ime pošiljatelja', 'wheel-of-fortune'); ?></label>
|
||
</th>
|
||
<td>
|
||
<input type="text" id="wheel_email_from_name" name="wheel_email_from_name" value="<?php echo esc_attr(get_option('wheel_email_from_name', get_bloginfo('name'))); ?>" class="regular-text" />
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row">
|
||
<label for="wheel_email_from_email"><?php echo esc_html__('E-pošta pošiljatelja', 'wheel-of-fortune'); ?></label>
|
||
</th>
|
||
<td>
|
||
<input type="email" id="wheel_email_from_email" name="wheel_email_from_email" value="<?php echo esc_attr(get_option('wheel_email_from_email', get_bloginfo('admin_email'))); ?>" class="regular-text" />
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row">
|
||
<?php echo esc_html__('Preizkusi nastavitve', 'wheel-of-fortune'); ?>
|
||
</th>
|
||
<td>
|
||
<div style="display: flex; align-items: center; gap: 10px; flex-wrap: wrap;">
|
||
<input type="email" id="test-email-recipient" class="regular-text" placeholder="<?php esc_attr_e('Email for testing', 'wheel-of-fortune'); ?>" value="<?php echo esc_attr(wp_get_current_user()->user_email); ?>" />
|
||
<button type="button" id="test-email-button" class="button button-secondary"><?php echo esc_html__('Pošlji testno e-pošto', 'wheel-of-fortune'); ?></button>
|
||
<span class="spinner" style="float: none; vertical-align: middle;"></span>
|
||
</div>
|
||
<p class="description"><?php echo esc_html__('Vnesite e-poštni naslov in kliknite gumb, da preizkusite trenutno vnešene (ne nujno shranjene) nastavitve.', 'wheel-of-fortune'); ?></p>
|
||
<div id="test-email-result" style="margin-top: 10px;"></div>
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
</div>
|
||
|
||
<div class="wheel-card">
|
||
<h2><?php echo esc_html__('Upravljanje s spini', 'wheel-of-fortune'); ?></h2>
|
||
|
||
<div class="wheel-form-table">
|
||
<h3><?php echo esc_html__('Ročno dodajanje spinov', 'wheel-of-fortune'); ?></h3>
|
||
<div>
|
||
<?php wp_nonce_field('wheel_add_spins_nonce', 'wheel_add_spins_nonce'); ?>
|
||
<table class="form-table">
|
||
<tr>
|
||
<th scope="row">
|
||
<label for="wheel_user_id"><?php echo esc_html__('Uporabnik', 'wheel-of-fortune'); ?></label>
|
||
</th>
|
||
<td>
|
||
<select id="wheel_user_id" class="wheel-user-select">
|
||
<option value=""><?php echo esc_html__('Izberite uporabnika', 'wheel-of-fortune'); ?></option>
|
||
</select>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row">
|
||
<label for="wheel_spins_to_add"><?php echo esc_html__('Število spinov', 'wheel-of-fortune'); ?></label>
|
||
</th>
|
||
<td>
|
||
<input type="number" id="wheel_spins_to_add" value="1" min="1" step="1" />
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
<p class="submit">
|
||
<button type="button" id="wheel_add_spins_button" class="button button-primary"><?php echo esc_html__('Dodaj spine', 'wheel-of-fortune'); ?></button>
|
||
</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="wheel-form-table">
|
||
<h3><?php echo esc_html__('Ponastavitev spinov', 'wheel-of-fortune'); ?></h3>
|
||
<p class="description"><?php echo esc_html__('Ponastavi število spinov za vse uporabnike na 0.', 'wheel-of-fortune'); ?></p>
|
||
<p>
|
||
<button type="button" id="wheel_reset_all_spins" class="button button-secondary"><?php echo esc_html__('Ponastavi vse spine', 'wheel-of-fortune'); ?></button>
|
||
<span class="spinner" style="float: none; vertical-align: middle;"></span>
|
||
</p>
|
||
<div id="wheel_reset_result" style="margin-top: 10px;"></div>
|
||
</div>
|
||
|
||
<!-- Dodaj nov razdelek za testiranje kuponov -->
|
||
<div class="wheel-form-table">
|
||
<h3><?php echo esc_html__('Testiranje ustvarjanja kuponov', 'wheel-of-fortune'); ?></h3>
|
||
<p class="description"><?php echo esc_html__('Ta funkcija bo preizkusila različne metode za ustvarjanje WooCommerce kuponov in našla tisto, ki deluje na vašem sistemu.', 'wheel-of-fortune'); ?></p>
|
||
<p>
|
||
<button type="button" id="wheel_test_coupons" class="button button-secondary"><?php echo esc_html__('Testiraj ustvarjanje kuponov', 'wheel-of-fortune'); ?></button>
|
||
<span class="spinner coupon-test-spinner" style="float: none; vertical-align: middle;"></span>
|
||
</p>
|
||
<div id="wheel_coupon_test_result" style="margin-top: 10px;"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="product-settings" class="wheel-tab-content" style="display:none;">
|
||
<div class="wheel-card">
|
||
<h2><?php echo esc_html__('Izdelki, ki podeljujejo spine', 'wheel-of-fortune'); ?></h2>
|
||
|
||
<p><?php echo esc_html__('Nastavite izdelke, ki bodo ob nakupu podelili določeno število spinov.', 'wheel-of-fortune'); ?></p>
|
||
|
||
<table class="wheel-products-table widefat">
|
||
<thead>
|
||
<tr>
|
||
<th><?php echo esc_html__('ID izdelka', 'wheel-of-fortune'); ?></th>
|
||
<th><?php echo esc_html__('Ime izdelka', 'wheel-of-fortune'); ?></th>
|
||
<th><?php echo esc_html__('Število spinov', 'wheel-of-fortune'); ?></th>
|
||
<th><?php echo esc_html__('Akcije', 'wheel-of-fortune'); ?></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<?php if (empty($spin_products)): ?>
|
||
<tr>
|
||
<td colspan="4"><?php echo esc_html__('Ni nastavljenih izdelkov.', 'wheel-of-fortune'); ?></td>
|
||
</tr>
|
||
<?php else: ?>
|
||
<?php foreach ($spin_products as $product_id => $spins): ?>
|
||
<?php $product = wc_get_product($product_id); ?>
|
||
<?php if ($product): ?>
|
||
<tr>
|
||
<td>
|
||
<input type="hidden" name="product_ids[]" value="<?php echo esc_attr($product_id); ?>" />
|
||
<?php echo esc_html($product_id); ?>
|
||
</td>
|
||
<td><?php echo esc_html($product->get_name()); ?></td>
|
||
<td>
|
||
<input type="number" name="product_spins[]" value="<?php echo esc_attr($spins); ?>" min="1" step="1" />
|
||
</td>
|
||
<td>
|
||
<a href="#" class="delete-product" data-id="<?php echo esc_attr($product_id); ?>"><?php echo esc_html__('Odstrani', 'wheel-of-fortune'); ?></a>
|
||
</td>
|
||
</tr>
|
||
<?php endif; ?>
|
||
<?php endforeach; ?>
|
||
<?php endif; ?>
|
||
</tbody>
|
||
<tfoot>
|
||
<tr>
|
||
<td>
|
||
<input type="number" id="new-product-id" placeholder="<?php echo esc_attr__('ID izdelka', 'wheel-of-fortune'); ?>" />
|
||
</td>
|
||
<td id="new-product-name"></td>
|
||
<td>
|
||
<input type="number" id="new-product-spins" placeholder="<?php echo esc_attr__('Število spinov', 'wheel-of-fortune'); ?>" min="1" step="1" />
|
||
</td>
|
||
<td>
|
||
<button type="button" id="add-product-button" class="button button-secondary"><?php echo esc_html__('Dodaj izdelek', 'wheel-of-fortune'); ?></button>
|
||
</td>
|
||
</tr>
|
||
</tfoot>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="wheel-preview" class="wheel-tab-content" style="display:none;">
|
||
<div class="wheel-card">
|
||
<h2><?php echo esc_html__('Predogled kolesa', 'wheel-of-fortune'); ?></h2>
|
||
|
||
<div class="wheel-preview-container">
|
||
<div id="wheel-preview-svg">
|
||
<?php
|
||
$wheel = wheel_of_fortune();
|
||
$prizes = $wheel->get_wheel_prizes();
|
||
echo $wheel->generate_wheel_svg($prizes);
|
||
?>
|
||
</div>
|
||
</div>
|
||
|
||
<p class="description"><?php echo esc_html__('To je predogled kolesa, ki ga bodo videli uporabniki. Za spreminjanje nagrad pojdite na stran "Nagrade".', 'wheel-of-fortune'); ?></p>
|
||
</div>
|
||
</div>
|
||
|
||
<p class="submit">
|
||
<input type="submit" name="wheel_save_settings" class="button button-primary" value="<?php echo esc_attr__('Shrani nastavitve', 'wheel-of-fortune'); ?>" />
|
||
</p>
|
||
</form>
|
||
</div>
|
||
|
||
<script>
|
||
jQuery(document).ready(function($) {
|
||
// Iskanje izdelka po ID
|
||
$('#new-product-id').on('change', function() {
|
||
var productId = $(this).val();
|
||
|
||
if (productId) {
|
||
$.ajax({
|
||
url: ajaxurl,
|
||
type: 'POST',
|
||
data: {
|
||
action: 'wheel_get_product_name',
|
||
product_id: productId,
|
||
_wpnonce: '<?php echo wp_create_nonce('wheel_product_nonce'); ?>'
|
||
},
|
||
success: function(response) {
|
||
if (response.success) {
|
||
$('#new-product-name').text(response.data.name);
|
||
} else {
|
||
$('#new-product-name').text('<?php echo esc_js(__('Izdelek ni najden', 'wheel-of-fortune')); ?>');
|
||
}
|
||
},
|
||
error: function() {
|
||
$('#new-product-name').text('<?php echo esc_js(__('Napaka pri iskanju izdelka', 'wheel-of-fortune')); ?>');
|
||
}
|
||
});
|
||
} else {
|
||
$('#new-product-name').text('');
|
||
}
|
||
});
|
||
|
||
// Dodajanje novega izdelka
|
||
$('#add-product-button').on('click', function() {
|
||
var productId = $('#new-product-id').val();
|
||
var spins = $('#new-product-spins').val();
|
||
var productName = $('#new-product-name').text();
|
||
|
||
if (!productId || !spins || productName === '<?php echo esc_js(__('Izdelek ni najden', 'wheel-of-fortune')); ?>') {
|
||
alert('<?php echo esc_js(__('Vnesite veljaven ID izdelka in število spinov', 'wheel-of-fortune')); ?>');
|
||
return;
|
||
}
|
||
|
||
var newRow = '<tr>' +
|
||
'<td><input type="hidden" name="product_ids[]" value="' + productId + '" />' + productId + '</td>' +
|
||
'<td>' + productName + '</td>' +
|
||
'<td><input type="number" name="product_spins[]" value="' + spins + '" min="1" step="1" /></td>' +
|
||
'<td><a href="#" class="delete-product" data-id="' + productId + '"><?php echo esc_js(__('Odstrani', 'wheel-of-fortune')); ?></a></td>' +
|
||
'</tr>';
|
||
|
||
var tbody = $('.wheel-products-table tbody');
|
||
if (tbody.find('tr:first td').length === 1) {
|
||
tbody.empty();
|
||
}
|
||
|
||
tbody.append(newRow);
|
||
|
||
$('#new-product-id').val('');
|
||
$('#new-product-spins').val('');
|
||
$('#new-product-name').text('');
|
||
});
|
||
|
||
// Brisanje izdelka
|
||
$('.wheel-products-table').on('click', '.delete-product', function(e) {
|
||
e.preventDefault();
|
||
|
||
var row = $(this).closest('tr');
|
||
row.remove();
|
||
|
||
var tbody = $('.wheel-products-table tbody');
|
||
if (tbody.find('tr').length === 0) {
|
||
tbody.append('<tr><td colspan="4"><?php echo esc_js(__('Ni nastavljenih izdelkov.', 'wheel-of-fortune')); ?></td></tr>');
|
||
}
|
||
});
|
||
|
||
// Ponastavi vse spine
|
||
$('#wheel_reset_all_spins').on('click', function() {
|
||
if (confirm('<?php echo esc_js(__('Ali ste prepričani, da želite ponastaviti vse spine za vse uporabnike? Tega ni mogoče razveljaviti!', 'wheel-of-fortune')); ?>')) {
|
||
$.ajax({
|
||
url: ajaxurl,
|
||
type: 'POST',
|
||
data: {
|
||
action: 'wheel_reset_all_spins',
|
||
_wpnonce: '<?php echo wp_create_nonce('wheel_reset_spins_nonce'); ?>'
|
||
},
|
||
success: function(response) {
|
||
if (response.success) {
|
||
alert('<?php echo esc_js(__('Vsi spini so bili uspešno ponastavljeni.', 'wheel-of-fortune')); ?>');
|
||
} else {
|
||
alert('<?php echo esc_js(__('Napaka pri ponastavljanju spinov:', 'wheel-of-fortune')); ?> ' + response.data.message);
|
||
}
|
||
},
|
||
error: function() {
|
||
alert('<?php echo esc_js(__('Prišlo je do napake pri komunikaciji s strežnikom.', 'wheel-of-fortune')); ?>');
|
||
}
|
||
});
|
||
}
|
||
});
|
||
|
||
// Iskanje uporabnikov
|
||
$('#wheel_user_id').on('change', function() {
|
||
var userId = $(this).val();
|
||
|
||
if (userId) {
|
||
$.ajax({
|
||
url: ajaxurl,
|
||
type: 'POST',
|
||
data: {
|
||
action: 'wheel_get_user_info',
|
||
user_id: userId,
|
||
_wpnonce: '<?php echo wp_create_nonce('wheel_user_info_nonce'); ?>'
|
||
},
|
||
success: function(response) {
|
||
if (response.success) {
|
||
$('#wheel_user_info').html(response.data.info);
|
||
} else {
|
||
$('#wheel_user_info').html('<?php echo esc_js(__('Uporabnik ni najden', 'wheel-of-fortune')); ?>');
|
||
}
|
||
},
|
||
error: function() {
|
||
$('#wheel_user_info').html('<?php echo esc_js(__('Napaka pri iskanju uporabnika', 'wheel-of-fortune')); ?>');
|
||
}
|
||
});
|
||
} else {
|
||
$('#wheel_user_info').html('');
|
||
}
|
||
});
|
||
|
||
// Dodaj spine uporabniku
|
||
$('#wheel_add_spins_button').on('click', function() {
|
||
var userId = $('#wheel_user_id').val();
|
||
var spins = $('#wheel_spins_to_add').val();
|
||
|
||
if (!userId || !spins) {
|
||
alert('<?php echo esc_js(__('Izberite uporabnika in vnesite število spinov', 'wheel-of-fortune')); ?>');
|
||
return;
|
||
}
|
||
|
||
$.ajax({
|
||
url: ajaxurl,
|
||
type: 'POST',
|
||
data: {
|
||
action: 'wheel_add_user_spins',
|
||
user_id: userId,
|
||
spins: spins,
|
||
_wpnonce: '<?php echo wp_create_nonce('wheel_add_spins_nonce'); ?>'
|
||
},
|
||
success: function(response) {
|
||
if (response.success) {
|
||
alert('<?php echo esc_js(__('Spini so bili uspešno dodani.', 'wheel-of-fortune')); ?>');
|
||
$('#wheel_user_id').val('');
|
||
$('#wheel_spins_to_add').val('');
|
||
} else {
|
||
alert('<?php echo esc_js(__('Napaka pri dodajanju spinov:', 'wheel-of-fortune')); ?> ' + response.data.message);
|
||
}
|
||
},
|
||
error: function() {
|
||
alert('<?php echo esc_js(__('Prišlo je do napake pri komunikaciji s strežnikom.', 'wheel-of-fortune')); ?>');
|
||
}
|
||
});
|
||
});
|
||
|
||
// Testiranje ustvarjanja kuponov
|
||
$('#wheel_test_coupons').on('click', function() {
|
||
var $button = $(this);
|
||
var $spinner = $('.coupon-test-spinner');
|
||
var $result = $('#wheel_coupon_test_result');
|
||
|
||
$button.prop('disabled', true);
|
||
$spinner.addClass('is-active');
|
||
$result.html('');
|
||
|
||
$.ajax({
|
||
url: ajaxurl,
|
||
type: 'POST',
|
||
data: {
|
||
action: 'wheel_test_coupons',
|
||
nonce: wheel_admin_nonce
|
||
},
|
||
dataType: 'json',
|
||
success: function(response) {
|
||
$button.prop('disabled', false);
|
||
$spinner.removeClass('is-active');
|
||
|
||
if (response.success) {
|
||
var html = '<div class="notice notice-success"><p><strong>' + response.data.message + '</strong></p>';
|
||
|
||
// Prikaži podrobne rezultate testov
|
||
html += '<table class="widefat" style="margin-top:10px;">';
|
||
html += '<thead><tr><th>Metoda</th><th>Rezultat</th><th>Sporočilo</th></tr></thead><tbody>';
|
||
|
||
$.each(response.data.tests, function(method, result) {
|
||
var statusClass = result.success ? 'success' : 'error';
|
||
var statusText = result.success ? '✅ Uspešno' : '❌ Neuspešno';
|
||
|
||
html += '<tr class="' + statusClass + '">';
|
||
html += '<td><strong>' + method + '</strong></td>';
|
||
html += '<td>' + statusText + '</td>';
|
||
html += '<td>' + result.message + '</td>';
|
||
html += '</tr>';
|
||
});
|
||
|
||
html += '</tbody></table>';
|
||
|
||
if (response.data.working_method) {
|
||
html += '<p><strong><?php echo esc_js(__('Priporočilo:', 'wheel-of-fortune')); ?></strong> ';
|
||
html += '<?php echo esc_js(__('Uporabite metodo', 'wheel-of-fortune')); ?> <code>' + response.data.working_method + '</code> <?php echo esc_js(__('za ustvarjanje kuponov.', 'wheel-of-fortune')); ?></p>';
|
||
|
||
// Dodaj gumb za shranjevanje najboljše metode
|
||
html += '<p><button type="button" class="button button-primary save-best-method" data-method="' + response.data.working_method + '">';
|
||
html += '<?php echo esc_js(__('Shrani to metodo kot privzeto', 'wheel-of-fortune')); ?></button></p>';
|
||
}
|
||
|
||
html += '</div>';
|
||
$result.html(html);
|
||
|
||
// Dodaj poslušalec dogodkov za gumb za shranjevanje najboljše metode
|
||
$('.save-best-method').on('click', function() {
|
||
var method = $(this).data('method');
|
||
saveBestMethod(method);
|
||
});
|
||
} else {
|
||
$result.html('<div class="notice notice-error"><p><strong><?php echo esc_js(__('Napaka pri testiranju:', 'wheel-of-fortune')); ?></strong> ' + response.data.message + '</p></div>');
|
||
}
|
||
},
|
||
error: function(xhr, status, error) {
|
||
$button.prop('disabled', false);
|
||
$spinner.removeClass('is-active');
|
||
$result.html('<div class="notice notice-error"><p><strong><?php echo esc_js(__('Prišlo je do napake pri testiranju:', 'wheel-of-fortune')); ?></strong> ' + error + '</p></div>');
|
||
}
|
||
});
|
||
});
|
||
|
||
// Funkcija za shranjevanje najboljše metode
|
||
function saveBestMethod(method) {
|
||
var $result = $('#wheel_coupon_test_result');
|
||
|
||
$.ajax({
|
||
url: ajaxurl,
|
||
type: 'POST',
|
||
data: {
|
||
action: 'wheel_save_best_coupon_method',
|
||
method: method,
|
||
nonce: wheel_admin_nonce
|
||
},
|
||
dataType: 'json',
|
||
success: function(response) {
|
||
if (response.success) {
|
||
$result.prepend('<div class="notice notice-success is-dismissible"><p>' + response.data.message + '</p></div>');
|
||
} else {
|
||
$result.prepend('<div class="notice notice-error is-dismissible"><p>' + response.data.message + '</p></div>');
|
||
}
|
||
},
|
||
error: function(xhr, status, error) {
|
||
$result.prepend('<div class="notice notice-error is-dismissible"><p><?php echo esc_js(__('Napaka pri shranjevanju metode:', 'wheel-of-fortune')); ?> ' + error + '</p></div>');
|
||
}
|
||
});
|
||
}
|
||
});
|
||
</script> """
|
||
|
||
|
||
"./admin/stats-page.php" :
|
||
"""
|
||
<?php
|
||
/**
|
||
* Stran s statistiko za Kolo Sreče
|
||
*/
|
||
|
||
// Prepreči neposreden dostop
|
||
if (!defined('ABSPATH')) {
|
||
exit;
|
||
}
|
||
|
||
// Preveri, če ima uporabnik pravice za dostop
|
||
if (!current_user_can('manage_options')) {
|
||
return;
|
||
}
|
||
|
||
// Pridobi podatke o uporabnikih
|
||
global $wpdb;
|
||
$users_table = $wpdb->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 '<div class="notice notice-success is-dismissible"><p>' .
|
||
__('Nagrada je bila označena kot unovčena.', 'wheel-of-fortune') .
|
||
'</p></div>';
|
||
}
|
||
|
||
// 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 '<div class="notice notice-success is-dismissible"><p>' .
|
||
sprintf(__('Vsi spini za kolo ID %d so bili uspešno ponastavljeni na 0.', 'wheel-of-fortune'), $wheel_id) .
|
||
'</p></div>';
|
||
} else {
|
||
echo '<div class="notice notice-error is-dismissible"><p>' .
|
||
__('Prišlo je do napake pri ponastavitvi spinov.', 'wheel-of-fortune') .
|
||
'</p></div>';
|
||
}
|
||
} else {
|
||
echo '<div class="notice notice-error is-dismissible"><p>' .
|
||
__('Izbrano kolo ne obstaja.', 'wheel-of-fortune') .
|
||
'</p></div>';
|
||
}
|
||
}
|
||
|
||
// 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
|
||
);
|
||
}
|
||
|
||
?>
|
||
|
||
<div class="wrap">
|
||
<h1><?php echo esc_html__('Statistika Kolesa Sreče', 'wheel-of-fortune'); ?></h1>
|
||
|
||
<!-- Gumb za ponastavitev spinov za izbrano kolo -->
|
||
<div class="notice notice-warning" style="margin: 20px 0;">
|
||
<p>
|
||
<strong><?php echo esc_html__('Ponastavitev spinov', 'wheel-of-fortune'); ?>:</strong>
|
||
<?php echo esc_html__('To dejanje bo ponastavilo vse spine na 0 za vse uporabnike na izbranem kolesu. To dejanje ni mogoče razveljaviti.', 'wheel-of-fortune'); ?>
|
||
<form method="post" style="display: inline-block; margin-left: 10px;">
|
||
<?php wp_nonce_field('reset_spins_wheel_nonce', 'reset_spins_wheel_nonce'); ?>
|
||
<input type="hidden" name="wheel_id" value="<?php echo esc_attr($selected_wheel_id); ?>">
|
||
<button type="submit" name="reset_all_spins_wheel" class="button button-secondary"
|
||
onclick="return confirm('<?php echo esc_js(__('Ste prepričani, da želite ponastaviti vse spine na 0 za vse uporabnike na tem kolesu? To dejanje ni mogoče razveljaviti.', 'wheel-of-fortune')); ?>')">
|
||
<?php echo esc_html__('Ponastavi vse spine na 0 za to kolo', 'wheel-of-fortune'); ?>
|
||
</button>
|
||
</form>
|
||
</p>
|
||
</div>
|
||
|
||
<!-- Izbira kolesa -->
|
||
<div class="tablenav top">
|
||
<div class="alignleft actions">
|
||
<form method="get" style="display: inline-block; margin-right: 20px;">
|
||
<input type="hidden" name="page" value="wof-stats">
|
||
<label for="wheel-select"><?php echo esc_html__('Izberi kolo:', 'wheel-of-fortune'); ?></label>
|
||
<select name="wheel_id" id="wheel-select" onchange="this.form.submit()">
|
||
<?php foreach ($wheels as $wheel): ?>
|
||
<option value="<?php echo esc_attr($wheel['id']); ?>" <?php selected($selected_wheel_id, $wheel['id']); ?>>
|
||
<?php echo esc_html($wheel['name']); ?>
|
||
</option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
</form>
|
||
|
||
<form method="get" style="display: inline-block;">
|
||
<input type="hidden" name="page" value="wof-stats">
|
||
<input type="hidden" name="wheel_id" value="<?php echo esc_attr($selected_wheel_id); ?>">
|
||
<label for="user-search" class="screen-reader-text"><?php echo esc_html__('Iskanje uporabnikov:', 'wheel-of-fortune'); ?></label>
|
||
<input type="search" id="user-search" name="s" value="<?php echo isset($_GET['s']) ? esc_attr($_GET['s']) : ''; ?>">
|
||
<input type="submit" class="button" value="<?php echo esc_attr__('Išči uporabnike', 'wheel-of-fortune'); ?>">
|
||
</form>
|
||
</div>
|
||
<br class="clear">
|
||
</div>
|
||
|
||
|
||
<h2><?php echo sprintf(esc_html__('Seznam uporabnikov s spini za kolo: %s', 'wheel-of-fortune'), esc_html($selected_wheel['name'])); ?></h2>
|
||
|
||
<!-- Filtriranje uporabnikov -->
|
||
<div class="user-filters" style="margin: 20px 0; padding: 15px; background: #f9f9f9; border: 1px solid #ddd; border-radius: 5px;">
|
||
<h4><?php echo esc_html__('Filtriranje uporabnikov', 'wheel-of-fortune'); ?></h4>
|
||
<div style="display: flex; gap: 15px; align-items: center; flex-wrap: wrap;">
|
||
<div>
|
||
<label for="filter-spins"><?php echo esc_html__('Preostali spini:', 'wheel-of-fortune'); ?></label>
|
||
<select id="filter-spins" style="margin-left: 5px;">
|
||
<option value=""><?php echo esc_html__('Vsi', 'wheel-of-fortune'); ?></option>
|
||
<option value="0"><?php echo esc_html__('0 spinov (porabili)', 'wheel-of-fortune'); ?></option>
|
||
<option value="1"><?php echo esc_html__('1 spin', 'wheel-of-fortune'); ?></option>
|
||
<option value="2"><?php echo esc_html__('2 spina', 'wheel-of-fortune'); ?></option>
|
||
<option value="3"><?php echo esc_html__('3 spini', 'wheel-of-fortune'); ?></option>
|
||
<option value="4"><?php echo esc_html__('4 spini', 'wheel-of-fortune'); ?></option>
|
||
<option value="5"><?php echo esc_html__('5+ spinov', 'wheel-of-fortune'); ?></option>
|
||
</select>
|
||
</div>
|
||
<div>
|
||
<label for="filter-total-spins"><?php echo esc_html__('Skupno spinov:', 'wheel-of-fortune'); ?></label>
|
||
<select id="filter-total-spins" style="margin-left: 5px;">
|
||
<option value=""><?php echo esc_html__('Vsi', 'wheel-of-fortune'); ?></option>
|
||
<option value="0"><?php echo esc_html__('0', 'wheel-of-fortune'); ?></option>
|
||
<option value="1"><?php echo esc_html__('1', 'wheel-of-fortune'); ?></option>
|
||
<option value="2-5"><?php echo esc_html__('2-5', 'wheel-of-fortune'); ?></option>
|
||
<option value="6-10"><?php echo esc_html__('6-10', 'wheel-of-fortune'); ?></option>
|
||
<option value="11+"><?php echo esc_html__('11+', 'wheel-of-fortune'); ?></option>
|
||
</select>
|
||
</div>
|
||
<div>
|
||
<button type="button" onclick="filterUsers()" class="button button-primary"><?php echo esc_html__('Potrdi filtriranje', 'wheel-of-fortune'); ?></button>
|
||
<button type="button" onclick="clearFilters()" class="button" style="margin-left: 10px;"><?php echo esc_html__('Počisti filtre', 'wheel-of-fortune'); ?></button>
|
||
</div>
|
||
</div>
|
||
<div id="filter-results" style="margin-top: 10px; font-weight: bold; color: #0073aa;"></div>
|
||
</div>
|
||
|
||
<table class="wp-list-table widefat fixed striped" id="users-table">
|
||
<thead>
|
||
<tr>
|
||
<th scope="col"><?php echo esc_html__('ID', 'wheel-of-fortune'); ?></th>
|
||
<th scope="col"><?php echo esc_html__('E-pošta', 'wheel-of-fortune'); ?></th>
|
||
<th scope="col"><?php echo esc_html__('Skupno št. spinov', 'wheel-of-fortune'); ?></th>
|
||
<th scope="col"><?php echo esc_html__('Preostali spini', 'wheel-of-fortune'); ?></th>
|
||
<th scope="col"><?php echo esc_html__('Zadnji spin', 'wheel-of-fortune'); ?></th>
|
||
<th scope="col"><?php echo esc_html__('Akcije', 'wheel-of-fortune'); ?></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<?php if (empty($users_with_spins)) : ?>
|
||
<tr>
|
||
<td colspan="6"><?php echo esc_html__('Ni uporabnikov z dodeljenimi spini.', 'wheel-of-fortune'); ?></td>
|
||
</tr>
|
||
<?php else : ?>
|
||
<?php foreach ($users_with_spins as $user) : ?>
|
||
<tr<?php echo ($selected_user_id == $user['ID']) ? ' class="active"' : ''; ?>>
|
||
<td><?php echo esc_html($user['ID']); ?></td>
|
||
<td><?php echo esc_html($user['user_email']); ?></td>
|
||
<td><?php echo esc_html($user['total_spins']); ?></td>
|
||
<td><?php echo esc_html($user['spins_available']); ?></td>
|
||
<td><?php echo !empty($user['last_spin_date']) ? esc_html(date_i18n(get_option('date_format') . ' ' . get_option('time_format'), strtotime($user['last_spin_date']))) : '-'; ?></td>
|
||
<td>
|
||
<a href="<?php echo esc_url(add_query_arg('user_id', $user['ID'])); ?>" class="button"><?php echo esc_html__('Podrobnosti', 'wheel-of-fortune'); ?></a>
|
||
</td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
<?php endif; ?>
|
||
</tbody>
|
||
</table>
|
||
|
||
<?php if ($selected_user_id > 0) : ?>
|
||
<?php $selected_user = get_userdata($selected_user_id); ?>
|
||
<?php if ($selected_user) : ?>
|
||
<h2><?php echo sprintf(esc_html__('Podrobnosti za uporabnika: %s', 'wheel-of-fortune'), esc_html($selected_user->display_name)); ?></h2>
|
||
|
||
<table class="form-table">
|
||
<tr>
|
||
<th scope="row"><?php echo esc_html__('ID uporabnika', 'wheel-of-fortune'); ?></th>
|
||
<td><?php echo esc_html($selected_user_id); ?></td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row"><?php echo esc_html__('E-pošta', 'wheel-of-fortune'); ?></th>
|
||
<td><?php echo esc_html($selected_user->user_email); ?></td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row"><?php echo esc_html__('Skupno število spinov', 'wheel-of-fortune'); ?></th>
|
||
<td>
|
||
<?php
|
||
$total_spins = $wpdb->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);
|
||
?>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row"><?php echo esc_html__('Preostali spini', 'wheel-of-fortune'); ?></th>
|
||
<td>
|
||
<?php
|
||
$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
|
||
));
|
||
echo esc_html($spins ?: 0);
|
||
?>
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
|
||
<h3><?php echo esc_html__('Zgodovina nagrad', 'wheel-of-fortune'); ?></h3>
|
||
|
||
<?php if (empty($user_prizes)) : ?>
|
||
<p><?php echo esc_html__('Ta uporabnik še ni prejel nobene nagrade.', 'wheel-of-fortune'); ?></p>
|
||
<?php else : ?>
|
||
<table class="wp-list-table widefat fixed striped">
|
||
<thead>
|
||
<tr>
|
||
<th scope="col"><?php echo esc_html__('ID', 'wheel-of-fortune'); ?></th>
|
||
<th scope="col"><?php echo esc_html__('Nagrada', 'wheel-of-fortune'); ?></th>
|
||
<th scope="col"><?php echo esc_html__('Opis', 'wheel-of-fortune'); ?></th>
|
||
<th scope="col"><?php echo esc_html__('Datum', 'wheel-of-fortune'); ?></th>
|
||
<th scope="col"><?php echo esc_html__('Status', 'wheel-of-fortune'); ?></th>
|
||
<th scope="col"><?php echo esc_html__('Akcije', 'wheel-of-fortune'); ?></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<?php foreach ($user_prizes as $prize) : ?>
|
||
<tr>
|
||
<td><?php echo esc_html($prize['id']); ?></td>
|
||
<td><?php echo esc_html($prize['prize_name']); ?></td>
|
||
<td><?php echo esc_html($prize['prize_description']); ?></td>
|
||
<td><?php echo esc_html(date_i18n(get_option('date_format') . ' ' . get_option('time_format'), strtotime($prize['spin_date']))); ?></td>
|
||
<td>
|
||
<?php echo $prize['redeemed'] ?
|
||
'<span class="dashicons dashicons-yes" style="color: green;"></span> ' . esc_html__('Unovčeno', 'wheel-of-fortune') :
|
||
'<span class="dashicons dashicons-no" style="color: red;"></span> ' . esc_html__('Neunovčeno', 'wheel-of-fortune');
|
||
?>
|
||
</td>
|
||
<td>
|
||
<?php if (!$prize['redeemed']) : ?>
|
||
<form method="post" style="display: inline;">
|
||
<?php wp_nonce_field('mark_prize_redeemed_nonce', 'mark_prize_redeemed_nonce'); ?>
|
||
<input type="hidden" name="prize_id" value="<?php echo esc_attr($prize['id']); ?>">
|
||
<button type="submit" name="mark_redeemed" class="button"><?php echo esc_html__('Označi kot unovčeno', 'wheel-of-fortune'); ?></button>
|
||
</form>
|
||
<?php endif; ?>
|
||
</td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
</tbody>
|
||
</table>
|
||
<?php endif; ?>
|
||
<?php else : ?>
|
||
<p><?php echo esc_html__('Uporabnik ni bil najden.', 'wheel-of-fortune'); ?></p>
|
||
<?php endif; ?>
|
||
<?php endif; ?>
|
||
</div>
|
||
|
||
<script>
|
||
// Funkcija za filtriranje uporabnikov
|
||
function filterUsers() {
|
||
const filterSpins = document.getElementById('filter-spins').value;
|
||
const filterTotalSpins = document.getElementById('filter-total-spins').value;
|
||
const table = document.getElementById('users-table');
|
||
const tbody = table.getElementsByTagName('tbody')[0];
|
||
|
||
if (!tbody) {
|
||
console.error('Tabela ni najdena');
|
||
return;
|
||
}
|
||
|
||
const rows = tbody.getElementsByTagName('tr');
|
||
let visibleCount = 0;
|
||
|
||
console.log('Filtriranje uporabnikov:', { filterSpins, filterTotalSpins, totalRows: rows.length });
|
||
|
||
for (let i = 0; i < rows.length; i++) {
|
||
const row = rows[i];
|
||
const cells = row.getElementsByTagName('td');
|
||
|
||
if (cells.length < 4) {
|
||
console.log('Preskočena vrstica (premalo stolpcev):', cells.length);
|
||
continue; // Preskoči header vrstice ali vrstice brez dovolj stolpcev
|
||
}
|
||
|
||
// Debug: prikaži vsebino vseh stolpcev
|
||
console.log(`Vrstica ${i} stolpci:`, {
|
||
stolpec0: cells[0] ? cells[0].textContent.trim() : 'N/A',
|
||
stolpec1: cells[1] ? cells[1].textContent.trim() : 'N/A',
|
||
stolpec2: cells[2] ? cells[2].textContent.trim() : 'N/A',
|
||
stolpec3: cells[3] ? cells[3].textContent.trim() : 'N/A',
|
||
stolpec4: cells[4] ? cells[4].textContent.trim() : 'N/A',
|
||
stolpec5: cells[5] ? cells[5].textContent.trim() : 'N/A'
|
||
});
|
||
|
||
const currentSpins = parseInt(cells[3].textContent.trim()) || 0; // Preostali spini (4. stolpec)
|
||
const totalSpins = parseInt(cells[2].textContent.trim()) || 0; // Skupno št. spinov (3. stolpec)
|
||
|
||
console.log(`Vrstica ${i}: currentSpins=${currentSpins}, totalSpins=${totalSpins}`);
|
||
|
||
let showRow = true;
|
||
|
||
// Filtriranje po preostalih spinih
|
||
if (filterSpins !== '') {
|
||
if (filterSpins === '0') {
|
||
showRow = showRow && (currentSpins === 0);
|
||
} else if (filterSpins === '1') {
|
||
showRow = showRow && (currentSpins === 1);
|
||
} else if (filterSpins === '2') {
|
||
showRow = showRow && (currentSpins === 2);
|
||
} else if (filterSpins === '3') {
|
||
showRow = showRow && (currentSpins === 3);
|
||
} else if (filterSpins === '4') {
|
||
showRow = showRow && (currentSpins === 4);
|
||
} else if (filterSpins === '5') {
|
||
showRow = showRow && (currentSpins >= 5);
|
||
}
|
||
}
|
||
|
||
// Filtriranje po skupnem številu spinov
|
||
if (filterTotalSpins !== '') {
|
||
if (filterTotalSpins === '0') {
|
||
showRow = showRow && (totalSpins === 0);
|
||
} else if (filterTotalSpins === '1') {
|
||
showRow = showRow && (totalSpins === 1);
|
||
} else if (filterTotalSpins === '2-5') {
|
||
showRow = showRow && (totalSpins >= 2 && totalSpins <= 5);
|
||
} else if (filterTotalSpins === '6-10') {
|
||
showRow = showRow && (totalSpins >= 6 && totalSpins <= 10);
|
||
} else if (filterTotalSpins === '11+') {
|
||
showRow = showRow && (totalSpins >= 11);
|
||
}
|
||
}
|
||
|
||
// Prikaži/skrij vrstico
|
||
if (showRow) {
|
||
row.style.display = '';
|
||
visibleCount++;
|
||
console.log(`Prikazana vrstica ${i}`);
|
||
} else {
|
||
row.style.display = 'none';
|
||
console.log(`Skrita vrstica ${i}`);
|
||
}
|
||
}
|
||
|
||
console.log(`Filtriranje končano: ${visibleCount} od ${rows.length} vrstic prikazanih`);
|
||
|
||
// Posodobi števec rezultatov
|
||
updateFilterResults(visibleCount, rows.length);
|
||
}
|
||
|
||
function clearFilters() {
|
||
document.getElementById('filter-spins').value = '';
|
||
document.getElementById('filter-total-spins').value = '';
|
||
filterUsers();
|
||
}
|
||
|
||
function updateFilterResults(visible, total) {
|
||
const resultsDiv = document.getElementById('filter-results');
|
||
if (visible === total) {
|
||
resultsDiv.innerHTML = '<?php echo esc_js(__('Prikazani vsi uporabniki:', 'wheel-of-fortune')); ?> ' + total;
|
||
} else {
|
||
resultsDiv.innerHTML = '<?php echo esc_js(__('Prikazano:', 'wheel-of-fortune')); ?> ' + visible + ' <?php echo esc_js(__('od', 'wheel-of-fortune')); ?> ' + total + ' <?php echo esc_js(__('uporabnikov', 'wheel-of-fortune')); ?>';
|
||
}
|
||
}
|
||
|
||
// Testna funkcija za preverjanje strukture tabele
|
||
function testTableStructure() {
|
||
const table = document.getElementById('users-table');
|
||
if (!table) {
|
||
console.log('Tabela ni najdena!');
|
||
return;
|
||
}
|
||
|
||
const tbody = table.getElementsByTagName('tbody')[0];
|
||
if (!tbody) {
|
||
console.log('Tbody ni najden!');
|
||
return;
|
||
}
|
||
|
||
const rows = tbody.getElementsByTagName('tr');
|
||
console.log(`Najdenih ${rows.length} vrstic v tabeli`);
|
||
|
||
if (rows.length > 0) {
|
||
const firstRow = rows[0];
|
||
const cells = firstRow.getElementsByTagName('td');
|
||
console.log(`Prva vrstica ima ${cells.length} stolpcev`);
|
||
|
||
for (let i = 0; i < cells.length; i++) {
|
||
console.log(`Stolpec ${i}: "${cells[i].textContent.trim()}"`);
|
||
}
|
||
}
|
||
}
|
||
|
||
// Inicializiraj števec rezultatov ob nalaganju strani
|
||
jQuery(document).ready(function($) {
|
||
// Gumb za ponastavitev spinov preko AJAX
|
||
$('button[name="reset_all_spins_wheel"]').on('click', function(e) {
|
||
e.preventDefault();
|
||
|
||
const button = $(this);
|
||
const originalText = button.text();
|
||
const wheelId = $('input[name="wheel_id"]').val();
|
||
|
||
if (!confirm('<?php echo esc_js(__('Ste prepričani, da želite ponastaviti vse spine na 0 za vse uporabnike na tem kolesu? To dejanje ni mogoče razveljaviti.', 'wheel-of-fortune')); ?>')) {
|
||
return;
|
||
}
|
||
|
||
button.prop('disabled', true).text('<?php echo esc_js(__('Ponastavljam spine...', 'wheel-of-fortune')); ?>');
|
||
|
||
$.ajax({
|
||
url: ajaxurl,
|
||
method: 'POST',
|
||
data: {
|
||
action: 'wheel_reset_spins_wheel',
|
||
wheel_id: wheelId,
|
||
_ajax_nonce: '<?php echo wp_create_nonce('wheel_admin_nonce'); ?>'
|
||
},
|
||
success: function(response) {
|
||
if (response.success) {
|
||
// Prikaži uspešno sporočilo
|
||
$('<div class="notice notice-success is-dismissible"><p>' + response.data.message + '</p></div>')
|
||
.insertAfter('h1')
|
||
.delay(3000)
|
||
.fadeOut();
|
||
|
||
// Osveži stran po 2 sekundah
|
||
setTimeout(function() {
|
||
location.reload();
|
||
}, 2000);
|
||
} else {
|
||
alert(response.data.message || '<?php echo esc_js(__('Prišlo je do napake.', 'wheel-of-fortune')); ?>');
|
||
button.prop('disabled', false).text(originalText);
|
||
}
|
||
},
|
||
error: function() {
|
||
alert('<?php echo esc_js(__('Prišlo je do napake pri komunikaciji s strežnikom.', 'wheel-of-fortune')); ?>');
|
||
button.prop('disabled', false).text(originalText);
|
||
}
|
||
});
|
||
});
|
||
|
||
// Posodobi števec rezultatov ob nalaganju strani
|
||
const table = document.getElementById('users-table');
|
||
if (table) {
|
||
const rows = table.getElementsByTagName('tbody')[0].getElementsByTagName('tr');
|
||
updateFilterResults(rows.length, rows.length);
|
||
|
||
// Testiraj strukturo tabele
|
||
testTableStructure();
|
||
}
|
||
});
|
||
</script> """
|
||
|
||
|
||
"./admin/users-page.php" :
|
||
"""
|
||
<?php
|
||
/**
|
||
* Stran za upravljanje uporabnikov in spinov za Kolo Sreče
|
||
*/
|
||
|
||
// Prepreči neposreden dostop
|
||
if (!defined('ABSPATH')) {
|
||
exit;
|
||
}
|
||
|
||
// Preveri, če ima uporabnik pravice za dostop
|
||
if (!current_user_can('manage_options')) {
|
||
return;
|
||
}
|
||
|
||
// Pridobi vsa kolesa
|
||
global $wpdb;
|
||
$wheels_table = $wpdb->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 '<div class="notice notice-success is-dismissible"><p>' .
|
||
sprintf(__('Uporabniku ID %d je bilo uspešno dodanih %d spinov za kolo %s.', 'wheel-of-fortune'), $user_id, $spins, $selected_wheel['name']) .
|
||
'</p></div>';
|
||
}
|
||
}
|
||
|
||
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 '<div class="notice notice-success is-dismissible"><p>' .
|
||
sprintf(__('Spini uporabnika ID %d za kolo %s so bili uspešno ponastavljeni na 0.', 'wheel-of-fortune'), $user_id, $selected_wheel['name']) .
|
||
'</p></div>';
|
||
}
|
||
}
|
||
|
||
// 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
|
||
);
|
||
}
|
||
}
|
||
|
||
?>
|
||
|
||
<div class="wrap">
|
||
<h1><?php echo esc_html__('Uporabniki in spini', 'wheel-of-fortune'); ?></h1>
|
||
|
||
<!-- Izbira kolesa -->
|
||
<div class="tablenav top">
|
||
<div class="alignleft actions">
|
||
<form method="get" style="display: inline-block; margin-right: 20px;">
|
||
<input type="hidden" name="page" value="wof-users">
|
||
<label for="wheel-select"><?php echo esc_html__('Izberi kolo:', 'wheel-of-fortune'); ?></label>
|
||
<select name="wheel_id" id="wheel-select" onchange="this.form.submit()">
|
||
<?php foreach ($wheels as $wheel): ?>
|
||
<option value="<?php echo esc_attr($wheel['id']); ?>" <?php selected($selected_wheel_id, $wheel['id']); ?>>
|
||
<?php echo esc_html($wheel['name']); ?>
|
||
</option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
</form>
|
||
|
||
<form method="get" style="display: inline-block;">
|
||
<input type="hidden" name="page" value="wof-users">
|
||
<input type="hidden" name="wheel_id" value="<?php echo esc_attr($selected_wheel_id); ?>">
|
||
<label for="user-search" class="screen-reader-text"><?php echo esc_html__('Iskanje uporabnikov:', 'wheel-of-fortune'); ?></label>
|
||
<input type="search" id="user-search" name="s" value="<?php echo esc_attr($search); ?>">
|
||
<input type="submit" class="button" value="<?php echo esc_attr__('Išči uporabnike', 'wheel-of-fortune'); ?>">
|
||
</form>
|
||
</div>
|
||
<br class="clear">
|
||
</div>
|
||
|
||
<div class="wheel-users-container">
|
||
<div class="wheel-users-list">
|
||
<h2><?php echo sprintf(esc_html__('Seznam uporabnikov s spini za kolo: %s', 'wheel-of-fortune'), esc_html($selected_wheel['name'])); ?></h2>
|
||
|
||
<table class="wp-list-table widefat fixed striped">
|
||
<thead>
|
||
<tr>
|
||
<th scope="col"><?php echo esc_html__('ID', 'wheel-of-fortune'); ?></th>
|
||
<th scope="col"><?php echo esc_html__('E-pošta', 'wheel-of-fortune'); ?></th>
|
||
<th scope="col"><?php echo esc_html__('Skupno št. spinov', 'wheel-of-fortune'); ?></th>
|
||
<th scope="col"><?php echo esc_html__('Preostali spini', 'wheel-of-fortune'); ?></th>
|
||
<th scope="col"><?php echo esc_html__('Akcije', 'wheel-of-fortune'); ?></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<?php if (empty($users)) : ?>
|
||
<tr>
|
||
<td colspan="5"><?php echo esc_html__('Ni najdenih uporabnikov s spini.', 'wheel-of-fortune'); ?></td>
|
||
</tr>
|
||
<?php else : ?>
|
||
<?php foreach ($users as $user) : ?>
|
||
<tr<?php echo ($selected_user_id == $user['ID']) ? ' class="active"' : ''; ?>>
|
||
<td><?php echo esc_html($user['ID']); ?></td>
|
||
<td><?php echo esc_html($user['user_email']); ?></td>
|
||
<td><?php echo esc_html($user['total_spins']); ?></td>
|
||
<td><?php echo esc_html($user['spins_available']); ?></td>
|
||
<td>
|
||
<a href="<?php echo esc_url(add_query_arg('edit_user', $user['ID'])); ?>" class="button"><?php echo esc_html__('Podrobnosti', 'wheel-of-fortune'); ?></a>
|
||
</td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
<?php endif; ?>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
<?php if ($selected_user) : ?>
|
||
<div class="wheel-user-edit">
|
||
<h2><?php echo sprintf(esc_html__('Podrobnosti za uporabnika: %s', 'wheel-of-fortune'), esc_html($selected_user->display_name)); ?></h2>
|
||
|
||
<table class="form-table">
|
||
<tr>
|
||
<th scope="row"><?php echo esc_html__('ID uporabnika', 'wheel-of-fortune'); ?></th>
|
||
<td><?php echo esc_html($selected_user_id); ?></td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row"><?php echo esc_html__('E-pošta', 'wheel-of-fortune'); ?></th>
|
||
<td><?php echo esc_html($selected_user->user_email); ?></td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row"><?php echo esc_html__('Skupno število spinov', 'wheel-of-fortune'); ?></th>
|
||
<td>
|
||
<?php
|
||
$total_spins = $wpdb->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);
|
||
?>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row"><?php echo esc_html__('Preostali spini', 'wheel-of-fortune'); ?></th>
|
||
<td><?php echo esc_html($spins); ?></td>
|
||
</tr>
|
||
</table>
|
||
|
||
<div class="wheel-user-actions">
|
||
<div class="wheel-action-box">
|
||
<h3><?php echo esc_html__('Dodaj spine', 'wheel-of-fortune'); ?></h3>
|
||
<form method="post" action="">
|
||
<?php wp_nonce_field('wheel_add_spins_nonce', 'wheel_add_spins_nonce'); ?>
|
||
<input type="hidden" name="user_id" value="<?php echo esc_attr($selected_user_id); ?>">
|
||
<input type="hidden" name="wheel_id" value="<?php echo esc_attr($selected_wheel_id); ?>">
|
||
|
||
<p>
|
||
<label for="spins"><?php echo esc_html__('Število spinov za dodati:', 'wheel-of-fortune'); ?></label>
|
||
<input type="number" id="spins" name="spins" value="1" min="1" class="regular-text" required>
|
||
</p>
|
||
|
||
<p class="submit">
|
||
<input type="submit" name="add_spins_submit" class="button button-primary" value="<?php echo esc_attr__('Dodaj spine', 'wheel-of-fortune'); ?>">
|
||
</p>
|
||
</form>
|
||
</div>
|
||
|
||
<div class="wheel-action-box">
|
||
<h3><?php echo esc_html__('Ponastavi spine', 'wheel-of-fortune'); ?></h3>
|
||
<form method="post" action="">
|
||
<?php wp_nonce_field('wheel_reset_spins_nonce', 'wheel_reset_spins_nonce'); ?>
|
||
<input type="hidden" name="user_id" value="<?php echo esc_attr($selected_user_id); ?>">
|
||
<input type="hidden" name="wheel_id" value="<?php echo esc_attr($selected_wheel_id); ?>">
|
||
|
||
<p><?php echo esc_html__('S klikom na gumb boste ponastavili število spinov uporabnika na 0.', 'wheel-of-fortune'); ?></p>
|
||
|
||
<p class="submit">
|
||
<input type="submit" name="reset_spins_submit" class="button button-secondary" value="<?php echo esc_attr__('Ponastavi spine na 0', 'wheel-of-fortune'); ?>" onclick="return confirm('<?php echo esc_js(__('Ali ste prepričani, da želite ponastaviti spine tega uporabnika na 0?', 'wheel-of-fortune')); ?>');">
|
||
</p>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<h3><?php echo esc_html__('Prejete nagrade', 'wheel-of-fortune'); ?></h3>
|
||
|
||
<?php if (empty($user_prizes)) : ?>
|
||
<p><?php echo esc_html__('Ta uporabnik še ni prejel nobene nagrade.', 'wheel-of-fortune'); ?></p>
|
||
<?php else : ?>
|
||
<table class="wp-list-table widefat fixed striped">
|
||
<thead>
|
||
<tr>
|
||
<th scope="col"><?php echo esc_html__('ID', 'wheel-of-fortune'); ?></th>
|
||
<th scope="col"><?php echo esc_html__('Nagrada', 'wheel-of-fortune'); ?></th>
|
||
<th scope="col"><?php echo esc_html__('Opis', 'wheel-of-fortune'); ?></th>
|
||
<th scope="col"><?php echo esc_html__('Datum', 'wheel-of-fortune'); ?></th>
|
||
<th scope="col"><?php echo esc_html__('Status', 'wheel-of-fortune'); ?></th>
|
||
<th scope="col"><?php echo esc_html__('Akcije', 'wheel-of-fortune'); ?></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<?php foreach ($user_prizes as $prize) : ?>
|
||
<tr>
|
||
<td><?php echo esc_html($prize['id']); ?></td>
|
||
<td><?php echo esc_html($prize['prize_name']); ?></td>
|
||
<td><?php echo esc_html($prize['prize_description']); ?></td>
|
||
<td><?php echo esc_html(date_i18n(get_option('date_format') . ' ' . get_option('time_format'), strtotime($prize['spin_date']))); ?></td>
|
||
<td>
|
||
<?php echo $prize['redeemed'] ?
|
||
'<span class="dashicons dashicons-yes" style="color: green;"></span> ' . esc_html__('Unovčeno', 'wheel-of-fortune') :
|
||
'<span class="dashicons dashicons-no" style="color: red;"></span> ' . esc_html__('Neunovčeno', 'wheel-of-fortune');
|
||
?>
|
||
</td>
|
||
<td>
|
||
<?php if (!$prize['redeemed']) : ?>
|
||
<form method="post" action="<?php echo esc_url(admin_url('admin.php?page=wheel-stats&user_id=' . $selected_user_id)); ?>">
|
||
<?php wp_nonce_field('mark_prize_redeemed_nonce', 'mark_prize_redeemed_nonce'); ?>
|
||
<input type="hidden" name="prize_id" value="<?php echo esc_attr($prize['id']); ?>">
|
||
<button type="submit" name="mark_redeemed" class="button"><?php echo esc_html__('Označi kot unovčeno', 'wheel-of-fortune'); ?></button>
|
||
</form>
|
||
<?php endif; ?>
|
||
</td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
</tbody>
|
||
</table>
|
||
<?php endif; ?>
|
||
</div>
|
||
<?php elseif ($selected_user_id > 0) : ?>
|
||
<div class="wheel-user-edit">
|
||
<p><?php echo esc_html__('Uporabnik ni bil najden.', 'wheel-of-fortune'); ?></p>
|
||
</div>
|
||
<?php else : ?>
|
||
<div class="wheel-user-edit">
|
||
<p><?php echo esc_html__('Izberite uporabnika za prikaz podrobnosti.', 'wheel-of-fortune'); ?></p>
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
|
||
<style>
|
||
.wheel-users-container {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 20px;
|
||
margin-top: 20px;
|
||
}
|
||
|
||
.wheel-users-list {
|
||
flex: 2;
|
||
min-width: 500px;
|
||
}
|
||
|
||
.wheel-user-edit {
|
||
flex: 1;
|
||
min-width: 300px;
|
||
background: #fff;
|
||
padding: 15px;
|
||
border: 1px solid #ccd0d4;
|
||
box-shadow: 0 1px 1px rgba(0,0,0,.04);
|
||
}
|
||
|
||
.wheel-user-actions {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 20px;
|
||
margin-top: 20px;
|
||
}
|
||
|
||
.wheel-action-box {
|
||
flex: 1;
|
||
min-width: 250px;
|
||
padding: 15px;
|
||
background: #f9f9f9;
|
||
border: 1px solid #e5e5e5;
|
||
}
|
||
</style>
|
||
</div>
|
||
</div> """
|
||
|
||
|
||
"./admin/wheels-page.php" :
|
||
"""
|
||
<?php
|
||
/**
|
||
* Admin page for managing multiple wheels
|
||
*/
|
||
if (!defined('ABSPATH')) exit;
|
||
|
||
global $wpdb;
|
||
$wheels_table = $wpdb->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 '<div class="notice notice-success is-dismissible"><p>' . __('New wheel created successfully!', 'wheel-of-fortune') . '</p></div>';
|
||
} else {
|
||
echo '<div class="notice notice-error is-dismissible"><p>' . __('Please provide a name for the wheel.', 'wheel-of-fortune') . '</p></div>';
|
||
}
|
||
}
|
||
|
||
// 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 '<div class="notice notice-success is-dismissible"><p>' . __('Wheel deleted successfully.', 'wheel-of-fortune') . '</p></div>';
|
||
} else {
|
||
echo '<div class="notice notice-error is-dismissible"><p>' . __('The default wheel cannot be deleted.', 'wheel-of-fortune') . '</p></div>';
|
||
}
|
||
}
|
||
|
||
|
||
$wheels = $wpdb->get_results("SELECT * FROM $wheels_table ORDER BY id ASC", ARRAY_A);
|
||
?>
|
||
|
||
<div class="wrap wheel-admin-page">
|
||
<h1><?php echo esc_html__('Wheels of Fortune', 'wheel-of-fortune'); ?></h1>
|
||
|
||
<div id="col-container" class="wp-clearfix">
|
||
<div id="col-left">
|
||
<div class="col-wrap">
|
||
<div class="form-wrap">
|
||
<h2><?php echo esc_html__('Add New Wheel', 'wheel-of-fortune'); ?></h2>
|
||
<form method="post" action="">
|
||
<?php wp_nonce_field('wof_add_wheel_nonce'); ?>
|
||
<div class="form-field">
|
||
<label for="wheel_name"><?php _e('Wheel Name', 'wheel-of-fortune'); ?></label>
|
||
<input type="text" name="wheel_name" id="wheel_name" required>
|
||
<p><?php _e('The name is how it appears on your site.', 'wheel-of-fortune'); ?></p>
|
||
</div>
|
||
<p class="submit">
|
||
<input type="submit" name="add_wheel_submit" id="submit" class="button button-primary" value="<?php _e('Add New Wheel', 'wheel-of-fortune'); ?>">
|
||
</p>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="col-right">
|
||
<div class="col-wrap">
|
||
<table class="wp-list-table widefat fixed striped">
|
||
<thead>
|
||
<tr>
|
||
<th scope="col" class="manage-column"><?php _e('ID', 'wheel-of-fortune'); ?></th>
|
||
<th scope="col" class="manage-column"><?php _e('Name', 'wheel-of-fortune'); ?></th>
|
||
<th scope="col" class="manage-column"><?php _e('Shortcode', 'wheel-of-fortune'); ?></th>
|
||
<th scope="col" class="manage-column"><?php _e('Actions', 'wheel-of-fortune'); ?></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<?php if (!empty($wheels)): ?>
|
||
<?php foreach ($wheels as $wheel): ?>
|
||
<tr>
|
||
<td><?php echo esc_html($wheel['id']); ?></td>
|
||
<td>
|
||
<strong><a href="<?php echo admin_url('admin.php?page=wof-edit-wheel&wheel_id=' . $wheel['id']); ?>"><?php echo esc_html($wheel['name']); ?></a></strong>
|
||
</td>
|
||
<td>
|
||
<code>[wheel_of_fortune id="<?php echo esc_attr($wheel['slug']); ?>"]</code>
|
||
</td>
|
||
<td>
|
||
<a href="<?php echo admin_url('admin.php?page=wof-edit-wheel&wheel_id=' . $wheel['id']); ?>"><?php _e('Edit', 'wheel-of-fortune'); ?></a>
|
||
<?php if ($wheel['id'] != 1): // Cannot delete default wheel ?>
|
||
| <a href="<?php echo wp_nonce_url(admin_url('admin.php?page=wof-wheels&action=delete&wheel_id=' . $wheel['id']), 'wof_delete_wheel_' . $wheel['id']); ?>" class="delete-link" style="color:red;" onclick="return confirm('<?php _e('Are you sure you want to delete this wheel? This cannot be undone.', 'wheel-of-fortune'); ?>');"><?php _e('Delete', 'wheel-of-fortune'); ?></a>
|
||
<?php endif; ?>
|
||
</td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
<?php else: ?>
|
||
<tr>
|
||
<td colspan="4"><?php _e('No wheels found.', 'wheel-of-fortune'); ?></td>
|
||
</tr>
|
||
<?php endif; ?>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>"""
|
||
|
||
|
||
"./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 = '<p><strong>' + prize.name + '</strong></p>';
|
||
} else {
|
||
html = '<h3>' + l10n.congratulations + '</h3><p>' + l10n.you_won + ' <strong>' + prize.name + '</strong></p>';
|
||
}
|
||
if (window.wof_spin_result.discount_code) {
|
||
html += '<p>' + l10n.discount_code_sent + '</p>';
|
||
}
|
||
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('<p>' + message + '</p>').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 <EMAIL@ADDRESS>\n"
|
||
"Language-Team: LANGUAGE <LL@li.org>\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 <a href=\"%s\">prijaviti</a>."
|
||
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" :
|
||
"""
|
||
<?php
|
||
/**
|
||
* Template for the Wheel of Fortune shortcode.
|
||
*
|
||
* This template is included from the shortcode function and has access to:
|
||
* @var int $wheel_id
|
||
* @var array $prizes
|
||
* @var int $spins_left
|
||
*/
|
||
if (!defined('ABSPATH')) exit;
|
||
?>
|
||
|
||
<div class="wheel-container">
|
||
<div class="wheel-wrapper">
|
||
<div class="wheel-svg">
|
||
<?php echo $this->generate_wheel_svg($prizes); ?>
|
||
</div>
|
||
<div class="wheel-pointer">
|
||
<!-- SVG za puščico je lahko tukaj ali v CSS kot background-image -->
|
||
<svg width="60" height="70" viewBox="0 0 60 70" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M30 70L58.286 17.5H1.714L30 70Z" fill="#D9D9D9"/><path d="M30 70L58.286 17.5H1.714L30 70Z" stroke="black" stroke-width="2"/><circle cx="30" cy="15" r="15" fill="#C4C4C4" stroke="black" stroke-width="2"/></svg>
|
||
</div>
|
||
<div class="wheel-button-container">
|
||
<button class="wheel-button" <?php echo ($spins_left <= 0) ? 'disabled' : ''; ?>>
|
||
<?php echo ($spins_left > 0) ? esc_html($l10n['spin_button']) : esc_html($l10n['no_spins_left']); ?>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="wheel-info">
|
||
<div class="wheel-spins-counter">
|
||
<?php _e('Spins left:', 'wheel-of-fortune'); ?> <span><?php echo esc_html($spins_left); ?></span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="wheel-result" style="display: none;"></div>
|
||
</div> """
|
||
|
||
|
||
"./templates/emails/default-prize-email.html" :
|
||
"""
|
||
<!DOCTYPE html>
|
||
<html>
|
||
<head>
|
||
<title>Congratulations on your win!</title>
|
||
</head>
|
||
<body style="font-family: Arial, sans-serif; margin: 20px; padding: 0; background-color: #f4f4f4;">
|
||
<table align="center" border="0" cellpadding="0" cellspacing="0" width="600" style="border-collapse: collapse; background-color: #ffffff; border: 1px solid #dddddd;">
|
||
<tr>
|
||
<td align="center" bgcolor="#70bbd9" style="padding: 40px 0 30px 0; color: #ffffff; font-size: 28px; font-weight: bold;">
|
||
Congratulations, {user_name}!
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td bgcolor="#ffffff" style="padding: 40px 30px 40px 30px;">
|
||
<h1 style="color: #333333;">You've won a prize!</h1>
|
||
<p style="color: #555555; font-size: 16px;">
|
||
You just won a fantastic prize on our Wheel of Fortune:
|
||
</p>
|
||
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="margin-top: 20px;">
|
||
<tr>
|
||
<td width="150" style="font-weight: bold;">Prize:</td>
|
||
<td>{prize_name}</td>
|
||
</tr>
|
||
<tr>
|
||
<td style="font-weight: bold;">Description:</td>
|
||
<td>{prize_description}</td>
|
||
</tr>
|
||
<tr>
|
||
<td style="font-weight: bold;">Redemption code:</td>
|
||
<td><strong>{redemption_code}</strong></td>
|
||
</tr>
|
||
</table>
|
||
<p style="color: #555555; font-size: 16px; margin-top: 30px;">
|
||
To redeem your prize, follow the instructions on our website or contact our support team.
|
||
</p>
|
||
<p style="color: #555555; font-size: 16px;">
|
||
Thank you for participating!
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td bgcolor="#eeeeee" style="padding: 30px 30px 30px 30px; text-align: center; color: #888888; font-size: 12px;">
|
||
This is an automated message. Please do not reply to this email.<br/>
|
||
© {date} <a href="{site_url}" style="color: #888888;">{site_name}</a>. All rights reserved.
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
</body>
|
||
</html> """
|
||
|
||
|
||
"./templates/wheel.php" :
|
||
"""
|
||
<?php
|
||
/**
|
||
* Template for displaying the wheel of fortune
|
||
*
|
||
* @var array $atts Shortcode attributes
|
||
*/
|
||
|
||
// Prevent direct access
|
||
if (!defined('ABSPATH')) {
|
||
exit;
|
||
}
|
||
|
||
// Get number of available spins for this specific wheel
|
||
$user_id = get_current_user_id();
|
||
$wheel_id = isset($template_vars['wheel_id']) ? $template_vars['wheel_id'] : 1;
|
||
global $wpdb;
|
||
$spins_table = $wpdb->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();
|
||
|
||
?>
|
||
<div id="<?php echo esc_attr($wheel_id_html); ?>" class="<?php echo esc_attr(implode(' ', $container_classes)); ?>">
|
||
<!-- SVG Filters and Gradients for 3D effects -->
|
||
<svg width="0" height="0" style="position: absolute;">
|
||
<!-- Gradients for wheel segments -->
|
||
<linearGradient id="gradientYellow" x1="0%" y1="0%" x2="0%" y2="100%">
|
||
<stop offset="0%" stop-color="#ffdd00" />
|
||
<stop offset="100%" stop-color="#ffaa00" />
|
||
</linearGradient>
|
||
<linearGradient id="gradientGreen" x1="0%" y1="0%" x2="0%" y2="100%">
|
||
<stop offset="0%" stop-color="#88ff00" />
|
||
<stop offset="100%" stop-color="#44cc00" />
|
||
</linearGradient>
|
||
<linearGradient id="gradientRed" x1="0%" y1="0%" x2="0%" y2="100%">
|
||
<stop offset="0%" stop-color="#ff5500" />
|
||
<stop offset="100%" stop-color="#cc3300" />
|
||
</linearGradient>
|
||
<linearGradient id="gradientPink" x1="0%" y1="0%" x2="0%" y2="100%">
|
||
<stop offset="0%" stop-color="#ff44aa" />
|
||
<stop offset="100%" stop-color="#cc2288" />
|
||
</linearGradient>
|
||
<linearGradient id="gradientBlue" x1="0%" y1="0%" x2="0%" y2="100%">
|
||
<stop offset="0%" stop-color="#00ccff" />
|
||
<stop offset="100%" stop-color="#0088cc" />
|
||
</linearGradient>
|
||
|
||
<!-- Hub gradients -->
|
||
<radialGradient id="hubGradient" cx="50%" cy="50%" r="50%" fx="50%" fy="50%">
|
||
<stop offset="0%" stop-color="#dddddd" />
|
||
<stop offset="70%" stop-color="#999999" />
|
||
<stop offset="100%" stop-color="#666666" />
|
||
</radialGradient>
|
||
|
||
<radialGradient id="buttonGradient" cx="50%" cy="30%" r="70%" fx="50%" fy="30%">
|
||
<stop offset="0%" stop-color="#330066" />
|
||
<stop offset="100%" stop-color="#220044" />
|
||
</radialGradient>
|
||
|
||
<!-- Chrome effect for pegs -->
|
||
<linearGradient id="chromeGradient" x1="0%" y1="0%" x2="100%" y2="100%">
|
||
<stop offset="0%" stop-color="#ffffff" />
|
||
<stop offset="25%" stop-color="#f0f0f0" />
|
||
<stop offset="50%" stop-color="#d0d0d0" />
|
||
<stop offset="75%" stop-color="#a0a0a0" />
|
||
<stop offset="100%" stop-color="#808080" />
|
||
</linearGradient>
|
||
|
||
<!-- Pointer gradients -->
|
||
<linearGradient id="pointerGradient" x1="0%" y1="0%" x2="100%" y2="100%">
|
||
<stop offset="0%" stop-color="#e0e0e0" />
|
||
<stop offset="50%" stop-color="#b0b0b0" />
|
||
<stop offset="100%" stop-color="#707070" />
|
||
</linearGradient>
|
||
|
||
<linearGradient id="pointerShineGradient" x1="0%" y1="0%" x2="100%" y2="100%">
|
||
<stop offset="0%" stop-color="#ffffff" />
|
||
<stop offset="100%" stop-color="rgba(255,255,255,0)" />
|
||
</linearGradient>
|
||
|
||
<!-- Filters for 3D effects -->
|
||
<filter id="bevel" x="-10%" y="-10%" width="120%" height="120%">
|
||
<feGaussianBlur in="SourceAlpha" stdDeviation="2" result="blur"/>
|
||
<feOffset in="blur" dx="2" dy="2" result="offsetBlur"/>
|
||
<feSpecularLighting in="blur" surfaceScale="5" specularConstant="1" specularExponent="20" lighting-color="#ffffff" result="specOut">
|
||
<fePointLight x="-5000" y="-10000" z="20000"/>
|
||
</feSpecularLighting>
|
||
<feComposite in="specOut" in2="SourceAlpha" operator="in" result="specOut2"/>
|
||
<feComposite in="SourceGraphic" in2="specOut2" operator="arithmetic" k1="0" k2="1" k3="1" k4="0" result="litPaint"/>
|
||
<feMerge>
|
||
<feMergeNode in="offsetBlur"/>
|
||
<feMergeNode in="litPaint"/>
|
||
</feMerge>
|
||
</filter>
|
||
|
||
<filter id="innerShadow" x="-20%" y="-20%" width="140%" height="140%">
|
||
<feGaussianBlur in="SourceAlpha" stdDeviation="3" result="blur"/>
|
||
<feOffset in="blur" dx="3" dy="3" result="offsetBlur"/>
|
||
<feComposite in="offsetBlur" in2="SourceAlpha" operator="in" result="innerShadow"/>
|
||
<feComposite in="SourceGraphic" in2="innerShadow" operator="over"/>
|
||
</filter>
|
||
|
||
<filter id="glow" x="-20%" y="-20%" width="140%" height="140%">
|
||
<feGaussianBlur in="SourceGraphic" stdDeviation="5" result="blur"/>
|
||
<feComposite in="blur" in2="SourceGraphic" operator="over"/>
|
||
</filter>
|
||
|
||
<filter id="neonGlow" x="-20%" y="-20%" width="140%" height="140%">
|
||
<feGaussianBlur in="SourceGraphic" stdDeviation="5" result="blur"/>
|
||
<feComposite in="blur" in2="SourceGraphic" operator="over"/>
|
||
</filter>
|
||
|
||
<filter id="neonGlowBright" x="-20%" y="-20%" width="140%" height="140%">
|
||
<feGaussianBlur in="SourceGraphic" stdDeviation="8" result="blur"/>
|
||
<feComposite in="blur" in2="SourceGraphic" operator="over"/>
|
||
</filter>
|
||
|
||
<filter id="pegGlow" x="-50%" y="-50%" width="200%" height="200%">
|
||
<feGaussianBlur in="SourceGraphic" stdDeviation="2" result="blur"/>
|
||
<feComposite in="blur" in2="SourceGraphic" operator="over"/>
|
||
</filter>
|
||
|
||
<filter id="textShadow" x="-10%" y="-10%" width="120%" height="120%">
|
||
<feDropShadow dx="1" dy="1" stdDeviation="1" flood-color="#000000" flood-opacity="0.7"/>
|
||
</filter>
|
||
|
||
<filter id="innerGlow" x="-20%" y="-20%" width="140%" height="140%">
|
||
<feGaussianBlur in="SourceGraphic" stdDeviation="10" result="blur"/>
|
||
<feComposite in="blur" in2="SourceGraphic" operator="atop"/>
|
||
</filter>
|
||
|
||
<filter id="buttonGlow" x="-30%" y="-30%" width="160%" height="160%">
|
||
<feGaussianBlur in="SourceGraphic" stdDeviation="5" result="blur"/>
|
||
<feComposite in="blur" in2="SourceGraphic" operator="over"/>
|
||
</filter>
|
||
|
||
<filter id="chromeEffect" x="-30%" y="-30%" width="160%" height="160%">
|
||
<feGaussianBlur in="SourceAlpha" stdDeviation="2" result="blur"/>
|
||
<feSpecularLighting in="blur" surfaceScale="5" specularConstant="1" specularExponent="20" lighting-color="#ffffff" result="specOut">
|
||
<fePointLight x="-5000" y="-10000" z="20000"/>
|
||
</feSpecularLighting>
|
||
<feComposite in="specOut" in2="SourceAlpha" operator="in" result="specOut2"/>
|
||
<feComposite in="SourceGraphic" in2="specOut2" operator="arithmetic" k1="0" k2="1" k3="1" k4="0"/>
|
||
</filter>
|
||
|
||
<filter id="pointerShadow" x="-30%" y="-30%" width="160%" height="160%">
|
||
<feDropShadow dx="2" dy="4" stdDeviation="3" flood-color="#000000" flood-opacity="0.5"/>
|
||
</filter>
|
||
</svg>
|
||
|
||
<!-- Wheel Pointer (Arrow) -->
|
||
<div class="wheel-pointer">
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 100">
|
||
<!-- Base/Mount -->
|
||
<rect x="15" y="0" width="50" height="15" rx="5" ry="5" fill="url(#pointerGradient)" filter="url(#bevel)" />
|
||
|
||
<!-- Arrow body -->
|
||
<path d="M25,10 L25,50 L15,50 L40,85 L65,50 L55,50 L55,10 Z"
|
||
fill="url(#pointerGradient)"
|
||
stroke="#505050"
|
||
stroke-width="2"
|
||
filter="url(#pointerShadow)" />
|
||
|
||
<!-- Highlight on arrow (3D effect) -->
|
||
<path d="M30,15 L30,45 L20,45 L40,75 L60,45 L50,45 L50,15 Z"
|
||
fill="url(#pointerShineGradient)"
|
||
opacity="0.3" />
|
||
|
||
<!-- Center bolt -->
|
||
<circle cx="40" cy="25" r="5" fill="url(#chromeGradient)" filter="url(#chromeEffect)" />
|
||
</svg>
|
||
</div>
|
||
|
||
<div class="wheel-wrapper">
|
||
<?php
|
||
if (!empty($prizes)) {
|
||
echo $wheel->generate_wheel_svg($prizes);
|
||
} else {
|
||
echo '<div class="wheel-error">' . esc_html__('Error loading the wheel. No prizes available.', 'wheel-of-fortune') . '</div>';
|
||
}
|
||
?>
|
||
</div>
|
||
|
||
<div class="wheel-spins-counter">
|
||
<?php echo esc_html__('Remaining spins:', 'wheel-of-fortune'); ?> <span><?php echo esc_html($spins); ?></span>
|
||
</div>
|
||
|
||
<button class="wheel-button" <?php echo ($spins <= 0) ? 'disabled' : ''; ?>>
|
||
<?php echo esc_html__('SPIN', 'wheel-of-fortune'); ?>
|
||
</button>
|
||
|
||
<div class="wheel-result"></div>
|
||
</div>
|
||
|
||
<script type="text/javascript">
|
||
// Additional initialization for this specific wheel
|
||
jQuery(document).ready(function($) {
|
||
if (typeof wheel_params !== 'undefined') {
|
||
console.log('Wheel of Fortune initialized: <?php echo esc_js($wheel_id_html); ?>');
|
||
} else {
|
||
console.error('Wheel of Fortune: wheel_params is not defined. Check if the plugin is properly loaded.');
|
||
}
|
||
});
|
||
</script> """
|
||
|
||
|
||
"./wheel-of-fortune.php" :
|
||
"""
|
||
<?php
|
||
/**
|
||
* Plugin Name: Wheel of Fortune
|
||
* Plugin URI: https://example.com/wheel-of-fortune
|
||
* Description: A Wheel of Fortune for WooCommerce that allows users to spin a wheel for prizes.
|
||
* Version: 1.0.1
|
||
* Author: Mark Poljansek
|
||
* Author URI: https://example.com
|
||
* Text Domain: wheel-of-fortune
|
||
* Domain Path: /languages
|
||
* Requires at least: 5.6
|
||
* Requires PHP: 7.2
|
||
* WC requires at least: 4.0
|
||
* WC tested up to: 6.0
|
||
* License: GPL v2 or later
|
||
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
||
*/
|
||
|
||
// Prevent direct access
|
||
if (!defined('ABSPATH')) {
|
||
exit;
|
||
}
|
||
|
||
// Plugin constants
|
||
define('WHEEL_OF_FORTUNE_VERSION', '1.0.1');
|
||
define('WHEEL_OF_FORTUNE_PLUGIN_DIR', plugin_dir_path(__FILE__));
|
||
define('WHEEL_OF_FORTUNE_PLUGIN_URL', plugin_dir_url(__FILE__));
|
||
define('WHEEL_OF_FORTUNE_PLUGIN_FILE', __FILE__);
|
||
define('WHEEL_OF_FORTUNE_DEBUG', true); // OBVEZNO NASTAVITE NA true
|
||
|
||
/**
|
||
* Helper function for debug logging
|
||
*/
|
||
function wheel_of_fortune_debug_log($message) {
|
||
if (defined('WHEEL_OF_FORTUNE_DEBUG') && WHEEL_OF_FORTUNE_DEBUG) {
|
||
if (is_array($message) || is_object($message)) {
|
||
error_log('Wheel of Fortune Debug: ' . print_r($message, true));
|
||
} else {
|
||
error_log('Wheel of Fortune Debug: ' . $message);
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Helper function to manually add spins to a user
|
||
*/
|
||
function wheel_of_fortune_add_spins($user_id, $spins, $wheel_id = 1) { // Privzeto kolo je 1
|
||
if (!$user_id || !is_numeric($spins) || $spins <= 0 || !is_numeric($wheel_id)) {
|
||
wheel_of_fortune_debug_log("add_spins: Invalid parameters provided. User: $user_id, Spins: $spins, Wheel: $wheel_id");
|
||
return false;
|
||
}
|
||
|
||
global $wpdb;
|
||
$table_spins = $wpdb->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 "<h2>" . __("This page is deprecated. Please manage prizes under a specific wheel.", "wheel-of-fortune") . "</h2>";
|
||
}
|
||
|
||
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 of Fortune: Default wheel not found. -->';
|
||
}
|
||
}
|
||
|
||
$wheel_id = $wheel['id'];
|
||
|
||
if (!is_user_logged_in()) {
|
||
return '<div class="wheel-login-required">' . sprintf(__('You need to <a href="%s">log in</a> to participate in this game.', 'wheel-of-fortune'), wp_login_url(get_permalink())) . '</div>';
|
||
}
|
||
|
||
$prizes = $this->get_wheel_prizes($wheel_id);
|
||
if (empty($prizes)) {
|
||
return '<!-- Wheel of Fortune: No prizes available for this wheel. -->';
|
||
}
|
||
|
||
$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 <textPath> 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 '<div class="wheel-error">' . esc_html__('No prizes available.', 'wheel-of-fortune') . '</div>';
|
||
}
|
||
|
||
// SVG dimensions and parameters
|
||
$cx = 350;
|
||
$cy = 350;
|
||
$outer_radius = 330;
|
||
$inner_radius = 70;
|
||
$angle = 360 / $num_prizes;
|
||
|
||
// Initialize SVG parts
|
||
$defs = '<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 .= "<path d='{$path_data}' class='wheel-segment' fill='{$segment_color}' />";
|
||
|
||
// --- 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 .= "<line x1='{$divider_x1}' y1='{$divider_y1}' x2='{$divider_x2}' y2='{$divider_y2}' class='wheel-divider' />";
|
||
$segments_paths .= "<circle cx='" . ($cx + ($outer_radius - 5) * cos($start_rad)) . "' cy='" . ($cy + ($outer_radius - 5) * sin($start_rad)) . "' r='5' class='wheel-peg' />";
|
||
|
||
// --- 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 .= "<text class='wheel-text' dominant-baseline='middle' x='{$text_x}' y='{$text_y}' transform='rotate({$rotate},{$text_x},{$text_y})'>{$prize['name']}</text>";
|
||
}
|
||
|
||
$defs .= '</defs>';
|
||
|
||
// Assemble the final SVG
|
||
$svg = '<svg viewBox="0 0 700 700" class="wheel">';
|
||
$svg .= $defs; // Add definitions first
|
||
$svg .= '<circle cx="' . $cx . '" cy="' . $cy . '" r="' . $outer_radius . '" class="wheel-frame" />';
|
||
$svg .= '<circle cx="' . $cx . '" cy="' . $cy . '" r="' . ($outer_radius - 10) . '" class="wheel-light-track" />';
|
||
$svg .= $segments_paths; // Add all segments, dividers, and pegs
|
||
$svg .= '<circle cx="' . $cx . '" cy="' . $cy . '" r="' . $inner_radius . '" class="wheel-hub-outer" />';
|
||
$svg .= '<circle cx="' . $cx . '" cy="' . $cy . '" r="' . ($inner_radius - 8) . '" class="wheel-hub-inner" />';
|
||
$svg .= $text_paths; // Add all text paths on top of segments
|
||
$svg .= '<circle cx="' . $cx . '" cy="' . $cy . '" r="' . ($inner_radius - 16) . '" class="wheel-hub-button" />';
|
||
$svg .= "<text x='{$cx}' y='" . ($cy + 8) . "' class='wheel-hub-text' text-anchor='middle'>SPIN</text>";
|
||
$svg .= '</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,<br><br>This is a test email from the Wheel of Fortune plugin.<br><br>If you received this message, your email settings seem to be working.<br><br><strong>Current Settings Used for This Test:</strong><br><ul><li><strong>Use SMTP:</strong> %2$s</li><li><strong>Host:</strong> %3$s</li><li><strong>Port:</strong> %4$s</li><li><strong>Encryption:</strong> %5$s</li><li><strong>Username:</strong> %6$s</li><li><strong>Sender Name:</strong> %7$s</li><li><strong>Sender Email:</strong> %8$s</li></ul><br>Best regards,<br>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();"""
|
||
|
||
|