100, 'width' => 300, 'flex-height' => true, 'flex-width' => true, )); // Registriraj navigacijske menije register_nav_menus(array( 'primary' => esc_html__('Primary Menu', 'grilctours'), 'footer' => esc_html__('Footer Menu', 'grilctours'), )); } add_action('after_setup_theme', 'grilctours_setup'); /** * Registracija stilov in skript */ function grilctours_scripts() { // Glavni CSS wp_enqueue_style('grilctours-style', get_stylesheet_uri()); // Google Fonts wp_enqueue_style('google-fonts', 'https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap'); // Glavni JavaScript wp_enqueue_script('grilctours-script', get_template_directory_uri() . '/js/script.js', array('jquery'), '1.0.0', true); } add_action('wp_enqueue_scripts', 'grilctours_scripts'); // Dodaj podporo za media uploader v admin function grilctours_admin_scripts($hook) { global $post_type; // Naloži skripte za edit in add new strani za individual_tour in experience_journey if (($hook == 'post.php' || $hook == 'post-new.php') && ($post_type == 'individual_tour' || $post_type == 'experience_journey')) { wp_enqueue_media(); wp_enqueue_script('grilctours-admin-script', get_template_directory_uri() . '/admin-scripts.js', array('jquery'), '1.0.0', true); } } add_action('admin_enqueue_scripts', 'grilctours_admin_scripts'); // Registracija Custom Post Type za Experience Journey function register_experience_journey_post_type() { $labels = array( 'name' => 'Experience Journeys', 'singular_name' => 'Experience Journey', 'menu_name' => 'Experience Journeys', 'add_new' => 'Add New Journey', 'add_new_item' => 'Add New Journey', 'edit_item' => 'Edit Journey', 'new_item' => 'New Journey', 'view_item' => 'View Journey', 'search_items' => 'Search Journeys', 'not_found' => 'No journeys found', 'not_found_in_trash' => 'No journeys found in Trash' ); $args = array( 'labels' => $labels, 'public' => true, 'has_archive' => true, 'menu_icon' => 'dashicons-palmtree', 'supports' => array('title', 'editor', 'thumbnail', 'excerpt'), 'rewrite' => array('slug' => 'journeys'), 'show_in_rest' => true, 'menu_position' => 5 ); register_post_type('experience_journey', $args); } add_action('init', 'register_experience_journey_post_type'); // Registracija Custom Post Type za Individual Tour function register_individual_tour_post_type() { $labels = array( 'name' => 'Individual Tours', 'singular_name' => 'Individual Tour', 'menu_name' => 'Individual Tours', 'add_new' => 'Add New Tour', 'add_new_item' => 'Add New Tour', 'edit_item' => 'Edit Tour', 'new_item' => 'New Tour', 'view_item' => 'View Tour', 'search_items' => 'Search Tours', 'not_found' => 'No tours found', 'not_found_in_trash' => 'No tours found in Trash' ); $args = array( 'labels' => $labels, 'public' => true, 'has_archive' => true, 'menu_icon' => 'dashicons-location', 'supports' => array('title', 'editor', 'thumbnail'), 'rewrite' => array('slug' => 'tours'), 'show_in_rest' => true, 'menu_position' => 6 ); register_post_type('individual_tour', $args); } add_action('init', 'register_individual_tour_post_type'); // Vključi datoteko za meta polja tur require_once get_template_directory() . '/tour-meta-fields.php'; // Registracija meta boxov za Experience Journey function register_experience_journey_meta_boxes() { add_meta_box( 'experience_journey_details', 'Journey Details', 'render_experience_journey_meta_box', 'experience_journey', 'normal', 'high' ); } add_action('add_meta_boxes', 'register_experience_journey_meta_boxes'); // Render meta box za Experience Journey function render_experience_journey_meta_box($post) { $target_audience = get_post_meta($post->ID, '_target_audience', true); $journey_image = get_post_meta($post->ID, '_journey_image', true); $short_title = get_post_meta($post->ID, '_short_title', true); $page_title = get_post_meta($post->ID, '_page_title', true); wp_nonce_field('experience_journey_nonce', 'experience_journey_nonce'); ?>
"; foreach ($extras as $extra) { $extras_list .= "Name: $name
Email: $email
Phone: " . ($phone ? $phone : "Not provided") . "
Date: $date
Number of participants: $participants
Country: " . ($country ? $country : "Not provided") . "
Selected extras: $extras_list
Ni najdenih Experience Journeys za razporejanje.
add_control(new Journey_Order_Control( $wp_customize, 'experience_journey_order_control', array( 'label' => 'Razporeditev Experience Journeys', 'section' => 'experience_journey_order_section', 'settings' => 'experience_journey_order', 'journeys' => $journey_choices, ) )); } add_action('customize_register', 'grilctours_customize_journey_order'); /** * Dodaj JavaScript in CSS za Customizer */ function grilctours_customizer_scripts() { wp_enqueue_script('jquery-ui-sortable'); // Dodaj JavaScript za sortiranje $script = " jQuery(document).ready(function($) { // Počakaj, da se DOM naloži, preden inicializiramo sortable setTimeout(function() { console.log('Inicializacija journey sortable seznama...'); // Poišči sortable seznam var sortableList = $('.journey-sortable-list'); if (sortableList.length) { console.log('Sortable seznam najden, inicializam...'); sortableList.sortable({ items: '.sortable-journey-item', handle: '.dashicons-move', placeholder: 'sortable-journey-placeholder', update: function(event, ui) { console.log('Vrstni red posodobljen'); // Zberi ID-je v novem vrstnem redu var ids = []; $('.sortable-journey-item').each(function() { ids.push($(this).data('journey-id')); }); // Posodobi skrito polje var inputField = sortableList.siblings('input[type=\"hidden\"]'); inputField.val(ids.join(',')).trigger('change'); console.log('Nova vrednost:', ids.join(',')); } }); console.log('Sortable inicializiran!'); } else { console.log('Sortable seznam ni bil najden!'); } }, 1000); }); "; wp_add_inline_script('jquery-ui-sortable', $script); // Dodaj CSS stile $style = " .journey-sortable-list { margin: 15px 0; padding: 0; list-style: none; } .sortable-journey-item { background: #fff; border: 1px solid #ddd; padding: 10px; margin-bottom: 10px; display: flex; align-items: center; cursor: move; border-radius: 3px; } .sortable-journey-item .dashicons-move { margin-right: 10px; color: #555; } .sortable-journey-item:hover { background: #f9f9f9; border-color: #999; } .sortable-journey-placeholder { border: 2px dashed #bbb; background: #f7f7f7; height: 40px; margin-bottom: 10px; } "; wp_add_inline_style('customize-controls', $style); } add_action('customize_controls_enqueue_scripts', 'grilctours_customizer_scripts'); /** * Omogoči admin skripte za posamezne tipe objav */ // ... existing code ... // Začasno odstranjeno zaradi napake // require_once get_template_directory() . '/mytheme-customizer.php'; // Preveri če je WooCommerce aktiviran function is_woocommerce_activated() { return class_exists('WooCommerce'); } // Vključi Stripe PHP knjižnico in inicializiraj samo če je WooCommerce aktiviran function init_stripe() { if (!is_woocommerce_activated()) { return; } // Preveri če obstaja composer autoload $autoload_path = get_template_directory() . '/vendor/autoload.php'; if (!file_exists($autoload_path)) { error_log('Stripe PHP library not found. Please run composer require stripe/stripe-php'); return; } // Vključi composer autoload require_once $autoload_path; // Preveri če je Stripe razred na voljo if (!class_exists('\Stripe\Stripe')) { error_log('Stripe PHP class not found after including autoload.php'); return; } try { // Nastavi Stripe API ključ \Stripe\Stripe::setApiKey('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'); } catch (Exception $e) { error_log('Error initializing Stripe: ' . $e->getMessage()); } } // Inicializiraj Stripe po tem, ko je WordPress naložen add_action('init', 'init_stripe', 20); // AJAX handler za obdelavo rezervacije ture function process_tour_booking() { if (!is_woocommerce_activated()) { wp_send_json_error(['message' => 'WooCommerce is not activated']); return; } check_ajax_referer('process_tour_booking', 'security'); try { // Preveri obvezna polja in izpiši natančen razlog napake $required_fields = [ 'name' => 'Full Name', 'email' => 'Email', 'date' => 'Departure Date', 'participants' => 'Number of Participants' ]; $missing_fields = []; foreach ($required_fields as $field => $label) { if (empty($_POST[$field])) { $missing_fields[] = $label; } } if (!empty($missing_fields)) { throw new Exception('The following fields are required: ' . implode(', ', $missing_fields)); } // Dodatno preverjanje veljavnosti e-pošte if (!filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) { throw new Exception('Please enter a valid email address.'); } // Preveri, da je število udeležencev najmanj 1 if (intval($_POST['participants']) < 1) { throw new Exception('Number of participants must be at least 1.'); } // Datum mora biti v prihodnosti $departure_date = new DateTime($_POST['date']); $today = new DateTime(); $today->setTime(0, 0, 0); // Nastavi čas na začetek dneva if ($departure_date < $today) { throw new Exception('Departure date must be in the future.'); } // Ustvari WooCommerce naročilo $order = wc_create_order(); // Dodaj podatke o stranki $order->set_billing_first_name($_POST['name']); $order->set_billing_email($_POST['email']); // Dodaj podatke o turi $tour_id = intval($_POST['tour_id']); $tour_name = sanitize_text_field($_POST['tour_name']); $participants = intval($_POST['participants']); $total_price = floatval($_POST['total_price']); // Pridobi WooCommerce produkt preko SKU-ja $product_id = wc_get_product_id_by_sku('tour-' . $tour_id); if (!$product_id) { // Poskusimo pridobiti produkt direktno po ID-ju $product = wc_get_product($tour_id); if (!$product) { throw new Exception('Tour product not found. Please contact administrator.'); } } else { $product = wc_get_product($product_id); if (!$product) { throw new Exception('Failed to load tour product'); } } // Dodaj produkt v naročilo $item_id = $order->add_product($product, $participants); // Dodaj datum odhoda kot meta podatek postavke if ($item_id) { wc_add_order_item_meta($item_id, '_tour_date', sanitize_text_field($_POST['date'])); } // Dodaj dodatke, če obstajajo if (!empty($_POST['extras'])) { $extras = json_decode(stripslashes($_POST['extras']), true); if (!is_array($extras)) { $extras = json_decode($_POST['extras'], true); // Poskusi brez stripslashes } if (is_array($extras)) { foreach ($extras as $extra) { // Preveri, da ima ekstra vse potrebne podatke if (empty($extra['name']) || !isset($extra['price'])) { continue; } // Ustvari nov produkt za dodatek $extra_product = new WC_Product_Simple(); $extra_product->set_name($extra['name']); $extra_product->set_regular_price(strval($extra['price'])); $extra_product->set_status('private'); $extra_product->set_catalog_visibility('hidden'); $extra_product->save(); // Dodaj dodatek v naročilo $order->add_product($extra_product, 1); // Dodaj meta podatke $order->add_meta_data('_extra_' . sanitize_title($extra['name']), true); // Izbriši začasni produkt wp_delete_post($extra_product->get_id(), true); } } } // Dodaj single supplement, če je potrebno if (!empty($_POST['single_supplement']) && ($_POST['single_supplement'] === 'true' || $_POST['single_supplement'] === true)) { $tour_duration = intval(get_post_meta($tour_id, '_tour_duration', true)); $single_supplement = 100 * $tour_duration; // 100€ na dan $order->add_fee('Single Supplement', $single_supplement); } // Nastavi skupno ceno $order->calculate_totals(); $order->set_total($total_price); // Shrani meta podatke $order->update_meta_data('_tour_date', sanitize_text_field($_POST['date'])); $order->update_meta_data('_participants', $participants); // Preračunaj skupno vrednost in določi znesek plačila glede na izbrani tip plačila $payment_type = isset($_POST['payment_type']) ? sanitize_text_field($_POST['payment_type']) : 'full'; $payment_amount = isset($_POST['payment_amount']) ? floatval($_POST['payment_amount']) : $total_price; // Shrani informacije o plačilu $order->update_meta_data('_payment_type', $payment_type); if ($payment_type === 'partial') { // Izračunaj zneske za delno plačilo $deposit_amount = $payment_amount; // že nastavljen na 30% v JavaScript $remaining_amount = $total_price - $deposit_amount; // Shrani podatke o delnem plačilu $order->update_meta_data('_deposit_amount', $deposit_amount); $order->update_meta_data('_remaining_amount', $remaining_amount); $order->update_meta_data('_is_deposit_paid', false); $order->update_meta_data('_is_remaining_paid', false); // Dodaj opombo naročilu o delnem plačilu $order->add_order_note(sprintf( 'Partial payment selected. Deposit: €%.2f, Remaining: €%.2f', $deposit_amount, $remaining_amount )); } // Shrani naročilo $order->save(); // Ustvari Stripe Payment Intent try { // Če je izbrano delno plačilo, uporabi znesek pologa namesto celotnega zneska $payment_amount_cents = intval($payment_amount * 100); // Stripe uporablja cente $payment_intent = \Stripe\PaymentIntent::create([ 'amount' => $payment_amount_cents, 'currency' => 'eur', 'metadata' => [ 'order_id' => $order->get_id(), 'tour_name' => $tour_name, 'tour_date' => $_POST['date'], 'payment_type' => $payment_type, 'total_price' => $total_price ] ]); // Shrani Payment Intent ID v naročilo $order->update_meta_data('_stripe_payment_intent', $payment_intent->id); $order->save(); // Vrni uspeh in client secret wp_send_json_success([ 'client_secret' => $payment_intent->client_secret, 'thank_you_url' => $order->get_checkout_order_received_url(), 'order_id' => $order->get_id(), 'payment_type' => $payment_type, 'payment_amount' => $payment_amount ]); } catch (\Stripe\Exception\ApiErrorException $e) { // Če Stripe vrne napako, izbriši naročilo in vrni napako $order->delete(true); throw new Exception('Payment processing error: ' . $e->getMessage()); } } catch (Exception $e) { error_log('Tour booking error: ' . $e->getMessage()); wp_send_json_error(['message' => $e->getMessage()]); } } add_action('wp_ajax_process_tour_booking', 'process_tour_booking'); add_action('wp_ajax_nopriv_process_tour_booking', 'process_tour_booking'); // Webhook handler za Stripe dogodke function handle_stripe_webhook() { $payload = @file_get_contents('php://input'); $event = null; try { $event = \Stripe\Event::constructFrom( json_decode($payload, true) ); } catch(\UnexpectedValueException $e) { http_response_code(400); exit(); } if ($event->type === 'payment_intent.succeeded') { $payment_intent = $event->data->object; // Najdi WooCommerce naročilo $orders = wc_get_orders([ 'meta_key' => '_stripe_payment_intent', 'meta_value' => $payment_intent->id, 'limit' => 1 ]); if (!empty($orders)) { $order = $orders[0]; // Pridobi podatke o plačilu $payment_type = get_post_meta($order->get_id(), '_payment_type', true); $payment_amount = $payment_intent->amount / 100; // Pretvori iz centov if ($payment_type === 'partial') { // Če gre za delno plačilo $is_deposit_paid = get_post_meta($order->get_id(), '_is_deposit_paid', true); if (!$is_deposit_paid) { // Označi polog kot plačan update_post_meta($order->get_id(), '_is_deposit_paid', true); // Dodaj opombo naročilu $deposit_amount = get_post_meta($order->get_id(), '_deposit_amount', true); $remaining_amount = get_post_meta($order->get_id(), '_remaining_amount', true); $order->add_order_note(sprintf( 'Deposit of €%.2f received. Remaining balance: €%.2f', $deposit_amount, $remaining_amount )); // Posodobi status naročila na "on-hold" ali podobno $order->update_status('on-hold', 'Deposit payment received. Awaiting final payment.'); } else { // Če gre za plačilo preostalega zneska update_post_meta($order->get_id(), '_is_remaining_paid', true); $order->payment_complete($payment_intent->id); $order->add_order_note('Final payment completed via Stripe (Payment Intent ID: ' . $payment_intent->id . ')'); } } else { // Če gre za polno plačilo, označi naročilo kot plačano $order->payment_complete($payment_intent->id); $order->add_order_note('Stripe payment completed (Payment Intent ID: ' . $payment_intent->id . ')'); } $order->save(); } } http_response_code(200); } // Dodaj rewrite pravilo za Stripe webhook function add_stripe_webhook_endpoint() { add_rewrite_rule('^stripe-webhook/?$', 'index.php?stripe-webhook=1', 'top'); } add_action('init', 'add_stripe_webhook_endpoint'); // Registriraj query var za webhook function add_stripe_webhook_query_var($vars) { $vars[] = 'stripe-webhook'; return $vars; } add_filter('query_vars', 'add_stripe_webhook_query_var'); // Poslušaj za webhook zahtevke function listen_for_stripe_webhook() { if (get_query_var('stripe-webhook')) { handle_stripe_webhook(); exit; } } add_action('parse_request', 'listen_for_stripe_webhook'); // Funkcija za kreiranje/posodabljanje WooCommerce produkta ob shranjevanju Individual Tour-a function create_wc_product_from_tour($post_id) { // Preveri če je WooCommerce aktiviran if (!class_exists('WooCommerce')) { return; } // Preveri če je post type Individual Tour if (get_post_type($post_id) !== 'individual_tour') { return; } // Preveri če je to avtomatsko shranjevanje if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) { return; } // Pridobi podatke o turi $tour_title = get_the_title($post_id); $tour_price = floatval(get_post_meta($post_id, '_tour_price', true)); $tour_description = get_post_field('post_content', $post_id); // Če cena ni nastavljena, nastavi na 0 if (!$tour_price) { $tour_price = 0; } // Preveri če produkt že obstaja (uporabi SKU za povezavo) $product_id = wc_get_product_id_by_sku('tour-' . $post_id); if ($product_id) { // Posodobi obstoječ produkt $product = wc_get_product($product_id); if ($product) { $product->set_name($tour_title); $product->set_regular_price(strval($tour_price)); $product->set_description($tour_description); $product->save(); } } else { // Ustvari nov produkt $product = new WC_Product_Simple(); $product->set_name($tour_title); $product->set_regular_price(strval($tour_price)); $product->set_description($tour_description); $product->set_sku('tour-' . $post_id); $product->set_status('publish'); // Nastavi featured image če obstaja $hero_image_id = get_post_meta($post_id, '_hero_image', true); if ($hero_image_id) { $product->set_image_id($hero_image_id); } $product->save(); } } // Odstrani staro akcijo remove_action('save_post_individual_tour', 'create_wc_product_from_tour'); // Dodaj novo akcijo, ki se sproži po shranjevanju meta podatkov add_action('updated_post_meta', 'update_wc_product_on_meta_update', 10, 4); // Funkcija za posodobitev WooCommerce produkta ob spremembi meta podatkov function update_wc_product_on_meta_update($meta_id, $post_id, $meta_key, $_meta_value) { // Preveri če je pravi meta ključ in post type if ($meta_key === '_tour_price' && get_post_type($post_id) === 'individual_tour') { create_wc_product_from_tour($post_id); } } // Dodaj akcijo za kreiranje produkta ob objavi ture add_action('wp_insert_post', function($post_id, $post) { if ($post->post_type === 'individual_tour' && $post->post_status === 'publish') { create_wc_product_from_tour($post_id); } }, 10, 2); // Izbriši WooCommerce produkt ko se izbriše Individual Tour function delete_wc_product_with_tour($post_id) { if (!class_exists('WooCommerce')) { return; } if (get_post_type($post_id) !== 'individual_tour') { return; } $product_id = wc_get_product_id_by_sku('tour-' . $post_id); if ($product_id) { wp_delete_post($product_id, true); } } add_action('before_delete_post', 'delete_wc_product_with_tour'); // Funkcija za dodajanje ture v košarico function add_tour_to_cart() { try { // Preveri nonce za varnost if (!isset($_POST['security']) || !wp_verify_nonce($_POST['security'], 'add_tour_to_cart')) { wp_send_json_error(array('message' => 'Security check failed')); return; } // Preveri če so vsi potrebni podatki prisotni $required_fields = array('tour_id', 'participants', 'date', 'name', 'email'); foreach ($required_fields as $field) { if (!isset($_POST[$field]) || empty($_POST[$field])) { wp_send_json_error(array('message' => "Missing required field: {$field}")); return; } } // Pridobi podatke iz zahtevka $tour_id = intval($_POST['tour_id']); $participants = intval($_POST['participants']); $date = sanitize_text_field($_POST['date']); $name = sanitize_text_field($_POST['name']); $email = sanitize_email($_POST['email']); // Preveri če je WooCommerce aktiviran if (!class_exists('WooCommerce')) { wp_send_json_error(array('message' => 'WooCommerce is not active')); return; } // Pridobi WooCommerce product ID $product_id = wc_get_product_id_by_sku('tour-' . $tour_id); if (!$product_id) { wp_send_json_error(array('message' => 'Product not found')); return; } // Počisti košarico WC()->cart->empty_cart(); // Dodaj produkt v košarico $cart_item_data = array( 'tour_date' => $date, 'participants' => $participants, 'customer_name' => $name, 'customer_email' => $email ); $added = WC()->cart->add_to_cart($product_id, $participants, 0, array(), $cart_item_data); if ($added) { wp_send_json_success(array( 'message' => 'Tour added to cart', 'checkout_url' => wc_get_checkout_url() )); } else { wp_send_json_error(array('message' => 'Failed to add tour to cart')); } } catch (Exception $e) { wp_send_json_error(array( 'message' => 'An error occurred: ' . $e->getMessage(), 'error' => $e->getTraceAsString() )); } } // Registriraj AJAX akcije add_action('wp_ajax_add_tour_to_cart', 'add_tour_to_cart'); add_action('wp_ajax_nopriv_add_tour_to_cart', 'add_tour_to_cart'); // Prikaži dodatne podatke v košarici in na checkout strani function display_cart_item_custom_meta($item_data, $cart_item) { if (isset($cart_item['tour_date'])) { $item_data[] = array( 'key' => 'Departure Date', 'value' => wc_clean($cart_item['tour_date']) ); } if (isset($cart_item['customer_name'])) { $item_data[] = array( 'key' => 'Customer Name', 'value' => wc_clean($cart_item['customer_name']) ); } if (isset($cart_item['customer_email'])) { $item_data[] = array( 'key' => 'Customer Email', 'value' => wc_clean($cart_item['customer_email']) ); } return $item_data; } add_filter('woocommerce_get_item_data', 'display_cart_item_custom_meta', 10, 2); // Shrani dodatne podatke v naročilo function add_custom_meta_to_order_items($item, $cart_item_key, $values, $order) { if (isset($values['tour_date'])) { $item->add_meta_data('Departure Date', $values['tour_date']); } if (isset($values['customer_name'])) { $item->add_meta_data('Customer Name', $values['customer_name']); } if (isset($values['customer_email'])) { $item->add_meta_data('Customer Email', $values['customer_email']); } } add_action('woocommerce_checkout_create_order_line_item', 'add_custom_meta_to_order_items', 10, 4); // Dodaj order bump template na checkout stran function add_order_bump_to_checkout() { include_once get_template_directory() . '/woocommerce/checkout/order-bump.php'; } // Odstrani stari hook remove_action('woocommerce_review_order_before_payment', 'add_order_bump_to_checkout'); // Dodaj nove hooke za različne lokacije add_action('woocommerce_checkout_before_order_review', 'add_order_bump_to_checkout'); add_action('woocommerce_before_checkout_form', 'add_order_bump_to_checkout'); // AJAX handler za posodobitev košarice z extras-i function handle_update_cart_extras() { check_ajax_referer('update_order_review', 'security'); if (!isset($_POST['extras'])) { wp_send_json_error('No extras provided'); return; } $extras = json_decode(stripslashes($_POST['extras']), true); // Odstrani obstoječe extras iz košarice foreach (WC()->cart->get_cart() as $cart_item_key => $cart_item) { if (isset($cart_item['is_extra']) && $cart_item['is_extra']) { WC()->cart->remove_cart_item($cart_item_key); } } // Pridobi tour ID iz prvega izdelka v košarici $tour_id = null; foreach (WC()->cart->get_cart() as $cart_item) { if (isset($cart_item['product_id'])) { $product = wc_get_product($cart_item['product_id']); if ($product) { $sku = $product->get_sku(); if (strpos($sku, 'tour-') === 0) { $tour_id = str_replace('tour-', '', $sku); break; } } } } if (!$tour_id) { wp_send_json_error('No tour found in cart'); return; } // Pridobi available extras za tour $available_extras = get_post_meta($tour_id, '_available_extras', true); // Dodaj izbrane extras v košarico foreach ($extras as $extra) { $index = $extra['index']; if (isset($available_extras[$index])) { $extra_data = $available_extras[$index]; // Ustvari nov produkt za extra $extra_product = new WC_Product_Simple(); $extra_product->set_name($extra_data['name']); $extra_product->set_price($extra_data['price']); $extra_product->set_status('private'); $extra_product->save(); // Dodaj extra v košarico WC()->cart->add_to_cart($extra_product->get_id(), 1, 0, array(), array( 'is_extra' => true, 'tour_id' => $tour_id, 'extra_data' => $extra_data )); // Izbriši začasni produkt wp_delete_post($extra_product->get_id(), true); } } WC()->cart->calculate_totals(); wp_send_json_success(); } add_action('wp_ajax_update_cart_extras', 'handle_update_cart_extras'); add_action('wp_ajax_nopriv_update_cart_extras', 'handle_update_cart_extras'); // Prikaži extra podatke v košarici in naročilu function display_cart_item_extra_meta($item_data, $cart_item) { if (isset($cart_item['is_extra']) && $cart_item['is_extra']) { $item_data[] = array( 'key' => 'Type', 'value' => 'Tour Extra' ); } return $item_data; } add_filter('woocommerce_get_item_data', 'display_cart_item_extra_meta', 10, 2); // Shrani extra podatke v naročilo function save_order_item_extra_meta($item, $cart_item_key, $values, $order) { if (isset($values['is_extra']) && $values['is_extra']) { $item->add_meta_data('_is_extra', true); $item->add_meta_data('_tour_id', $values['tour_id']); $item->add_meta_data('_extra_data', $values['extra_data']); } } add_action('woocommerce_checkout_create_order_line_item', 'save_order_item_extra_meta', 10, 4); /** * Prikaži dodatne podatke o turi v košarici */ function display_tour_cart_item_data($item_data, $cart_item) { if (isset($cart_item['tour_date'])) { $item_data[] = array( 'key' => 'Date', 'value' => $cart_item['tour_date'] ); } if (isset($cart_item['participants'])) { $item_data[] = array( 'key' => 'Participants', 'value' => $cart_item['participants'] ); } return $item_data; } add_filter('woocommerce_get_item_data', 'display_tour_cart_item_data', 10, 2); /** * Shrani dodatne podatke o turi v naročilo */ function save_tour_order_item_meta($item, $cart_item_key, $values, $order) { if (isset($values['tour_date'])) { $item->add_meta_data('Date', $values['tour_date']); } if (isset($values['participants'])) { $item->add_meta_data('Participants', $values['participants']); } if (isset($values['is_tour_extra'])) { $item->add_meta_data('_is_tour_extra', true); if (isset($values['tour_id'])) { $item->add_meta_data('_tour_id', $values['tour_id']); } } } add_action('woocommerce_checkout_create_order_line_item', 'save_tour_order_item_meta', 10, 4); // Preusmeri na custom Thank You stran po uspešnem plačilu function redirect_to_custom_thank_you_page($order_received_url, $order) { return home_url('/thank-you/'); } add_filter('woocommerce_get_checkout_order_received_url', 'redirect_to_custom_thank_you_page', 10, 2); /** * Dodaj Customizer kontrolo za "drag & drop" Individual Tours znotraj Experience Journeyev */ function grilctours_customize_individual_tour_order($wp_customize) { // Dodaj sekcijo $wp_customize->add_section('individual_tour_order_section', array( 'title' => __('Individual Tours Order', 'grilctours'), 'priority' => 210, )); // Definiraj razred znotraj funkcije, samo ko je potreben class Individual_Tour_Order_Control extends WP_Customize_Control { public $type = 'individual_tour_order'; public $tours = array(); public $journey_id = 0; public function render_content() { // Edinstveni ID za ta kontrolnik $list_id = 'sortable-tour-list-' . $this->journey_id; ?> 'experience_journey', 'posts_per_page' => -1, 'orderby' => 'title', 'order' => 'ASC', )); // Za vsak Experience Journey dodaj kontrolo za Individual Tours foreach ($journeys as $journey) { $journey_id = $journey->ID; $journey_title = $journey->post_title; // Pridobi vse Individual Tours za ta Experience Journey $tours = get_posts(array( 'post_type' => 'individual_tour', 'posts_per_page' => -1, 'meta_query' => array( array( 'key' => '_experience_journey', 'value' => $journey_id, 'compare' => '=' ) ) )); // Če ni Individual Tours za ta Journey, preskoči if (empty($tours)) { continue; } // Ustvari nastavitev za ta Journey $setting_id = 'individual_tour_order_' . $journey_id; $wp_customize->add_setting($setting_id, array( 'default' => '', 'type' => 'option', 'capability' => 'edit_theme_options', 'transport' => 'refresh', )); // Pridobi shranjeni vrstni red $saved_order = get_option($setting_id, ''); $order_array = !empty($saved_order) ? explode(',', $saved_order) : array(); // Sortiraj ture glede na obstoječ vrstni red $ordered_tours = array(); // Najprej dodaj tiste v shranjenem vrstnem redu foreach ($order_array as $id) { foreach ($tours as $index => $tour) { if ($tour->ID == $id) { $ordered_tours[] = $tour; unset($tours[$index]); break; } } } // Dodaj preostale na konec $ordered_tours = array_merge($ordered_tours, $tours); // Dodaj kontrolo $wp_customize->add_control( new Individual_Tour_Order_Control( $wp_customize, $setting_id, array( 'label' => sprintf(__('Tours in %s', 'grilctours'), $journey_title), 'description' => __('Drag and drop tours to change their order.', 'grilctours'), 'section' => 'individual_tour_order_section', 'tours' => $ordered_tours, 'journey_id' => $journey_id, ) ) ); } } add_action('customize_register', 'grilctours_customize_individual_tour_order'); /** * Razširi obstoječe JS in CSS za podporo urejanju Individual Tours */ function grilctours_customize_individual_tour_scripts() { $script = " jQuery(document).ready(function($) { setTimeout(function() { console.log('Začenjam inicializacijo sortable za Individual Tours...'); // Poišči vse sortable sezname Individual Tours var sortableLists = $('.sortable-tours-list'); if (sortableLists.length) { console.log('Najdenih', sortableLists.length, 'sortable seznamov za Individual Tours'); sortableLists.each(function() { var journeyId = $(this).data('journey-id'); var listId = $(this).attr('id'); console.log('Inicializiram seznam:', listId, 'za Journey ID:', journeyId); try { $(this).sortable({ containment: 'parent', cursor: 'move', handle: '.dashicons-menu', items: '.sortable-item', revert: true, tolerance: 'pointer', update: function(event, ui) { var ids = []; $(this).find('.sortable-item').each(function() { ids.push($(this).attr('data-id')); }); // Posodobi vrednost kontrole var settingId = 'individual_tour_order_' + journeyId; var inputField = $('input[data-customize-setting-link=\"' + settingId + '\"]'); console.log('Posodabljam', settingId, 'nova vrednost:', ids.join(',')); inputField.val(ids.join(',')).trigger('change'); } }).disableSelection(); console.log('Sortable uspešno inicializiran za', listId); } catch (e) { console.error('Napaka pri inicializaciji sortable za', listId, ':', e); } }); } else { console.log('Ni najdenih sortable seznamov za Individual Tours'); } }, 1500); }); "; wp_add_inline_script('jquery-ui-sortable', $script); } add_action('customize_controls_enqueue_scripts', 'grilctours_customize_individual_tour_scripts'); /** * Funkcija za urejanje vrstnega reda Experience Journeys glede na nastavitev v Customizer-ju * * @param WP_Query $query Query objekt */ function grilctours_order_experience_journeys($query) { // Izvajaj samo za glavne poizvedbe in experience_journey post type if (!is_admin() && $query->is_main_query() && (is_post_type_archive('experience_journey') || is_home() || is_front_page())) { // Pridobi shranjeni vrstni red $saved_order = get_option('experience_journey_order', ''); // Če je vrstni red definiran if (!empty($saved_order)) { $order_array = explode(',', $saved_order); // Uporabi shranjen vrstni red za poizvedbo if (!empty($order_array)) { $query->set('post_type', 'experience_journey'); $query->set('posts_per_page', -1); $query->set('orderby', 'post__in'); $query->set('post__in', $order_array); } } } } add_action('pre_get_posts', 'grilctours_order_experience_journeys'); /** * Dodaj nastavitve za Custom Inquiry sekcijo v WordPress Customizer */ function grilctours_customize_inquiry_section($wp_customize) { // Sekcija za nastavitve Custom Inquiry $wp_customize->add_section('inquiry_section_settings', array( 'title' => __('Inquiry Section Settings', 'grilctours'), 'priority' => 107, )); // Naslov sekcije $wp_customize->add_setting('inquiry_section_title', array( 'default' => 'Ready to Plan Your Custom Journey?', 'sanitize_callback' => 'sanitize_text_field', 'transport' => 'refresh', )); $wp_customize->add_control('inquiry_section_title', array( 'label' => __('Section Title', 'grilctours'), 'section' => 'inquiry_section_settings', 'type' => 'text', )); // Opis sekcije $wp_customize->add_setting('inquiry_section_description', array( 'default' => 'A world of moonlit forests and twisting turquoise rivers, Slovenia is a fairytale destination. Home to storybook castles, historic towns, and picturesque alpine landscapes; let us create your perfect holiday experience.', 'sanitize_callback' => 'wp_kses_post', 'transport' => 'refresh', )); $wp_customize->add_control('inquiry_section_description', array( 'label' => __('Section Description', 'grilctours'), 'section' => 'inquiry_section_settings', 'type' => 'textarea', )); // Gumb besedilo $wp_customize->add_setting('inquiry_button_text', array( 'default' => 'START PLANNING', 'sanitize_callback' => 'sanitize_text_field', 'transport' => 'refresh', )); $wp_customize->add_control('inquiry_button_text', array( 'label' => __('Button Text', 'grilctours'), 'section' => 'inquiry_section_settings', 'type' => 'text', )); // Ozadje sekcije $wp_customize->add_setting('inquiry_section_background', array( 'default' => '', 'sanitize_callback' => 'esc_url_raw', 'transport' => 'refresh', )); $wp_customize->add_control(new WP_Customize_Image_Control($wp_customize, 'inquiry_section_background', array( 'label' => __('Section Background Image', 'grilctours'), 'section' => 'inquiry_section_settings', 'settings' => 'inquiry_section_background', ))); } add_action('customize_register', 'grilctours_customize_inquiry_section'); /** * Custom Inquiry Ajax Handler */ function handle_custom_inquiry_form() { // Beležimo začetek funkcije error_log('Custom inquiry form submission started'); // Preveri nonce (varnost) if (!isset($_POST['security']) || !wp_verify_nonce($_POST['security'], 'custom_inquiry_nonce')) { error_log('Invalid security token in custom inquiry form'); wp_send_json_error('Invalid security token'); return; } // Pridobi podatke iz obrazca $name = isset($_POST['name']) ? sanitize_text_field($_POST['name']) : ''; $email = isset($_POST['email']) ? sanitize_email($_POST['email']) : ''; $travel_date = isset($_POST['travel_date']) ? sanitize_text_field($_POST['travel_date']) : 'Not specified'; $travelers = isset($_POST['travelers']) ? intval($_POST['travelers']) : 0; $destination = isset($_POST['destination']) ? sanitize_text_field($_POST['destination']) : 'Not specified'; $message = isset($_POST['message']) ? sanitize_textarea_field($_POST['message']) : ''; // Beleži prejete podatke error_log('Form data: Name=' . $name . ', Email=' . $email . ', Date=' . $travel_date . ', Travelers=' . $travelers); error_log('Form additional data: Destination=' . $destination . ', Message=' . substr($message, 0, 50) . (strlen($message) > 50 ? '...' : '')); // Preveri obvezna polja if (empty($name) || empty($email)) { error_log('Missing required fields in custom inquiry form'); wp_send_json_error('Please fill in all required fields.'); return; } // Nastavi fiksni e-poštni naslov prejemnika $admin_email = 'info@europewonder.com'; // Fiksni e-poštni naslov $to = $admin_email; error_log('Sending inquiry to admin email: ' . $to); // Nastavi zadevo $subject = 'New Custom Journey Inquiry from ' . $name; // Priprava sporočila $body = "A new inquiry has been submitted through your website:
| Name: | " . esc_html($name) . " |
|---|---|
| Email: | " . esc_html($email) . " |
| Planned Travel Date: | " . esc_html($travel_date) . " |
| Number of Travelers: | " . esc_html($travelers) . " |
| Preferred Destination(s): | " . esc_html($destination) . " |
| Message: | " . nl2br(esc_html($message)) . " |
Dear " . esc_html($name) . ",
Thank you for your interest in our custom journey services. We have received your inquiry and will get back to you as soon as possible to discuss your travel plans.
Here's a summary of the information you provided:
If you have any additional questions or information to add, please feel free to reply to this email.
Best regards,
Europe Wonder Team
A new message has been submitted through your website's contact form:
| Name: | " . esc_html($name) . " |
|---|---|
| Email: | " . esc_html($email) . " |
| Subject: | " . esc_html($subject) . " |
| Message: | " . nl2br(esc_html($message)) . " |
Dear " . esc_html($name) . ",
Thank you for contacting Europe Wonder. We have received your message and will get back to you as soon as possible.
Here's a copy of the message you sent us:
Subject: " . esc_html($subject) . "
Message:
" . nl2br(esc_html($message)) . "
If you have any additional questions, please feel free to reply to this email.
Best regards,
Europe Wonder Team