--- a/wp-event-solution/build/js/dashboard.asset.php
+++ b/wp-event-solution/build/js/dashboard.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('moment', 'react', 'react-dom', 'wp-api-fetch', 'wp-block-editor', 'wp-block-library', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-dom-ready', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n', 'wp-keyboard-shortcuts', 'wp-media-utils', 'wp-primitives', 'wp-url'), 'version' => '0be6e5000bae13320915');
+<?php return array('dependencies' => array('moment', 'react', 'react-dom', 'wp-api-fetch', 'wp-block-editor', 'wp-block-library', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-dom-ready', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n', 'wp-keyboard-shortcuts', 'wp-media-utils', 'wp-primitives', 'wp-url'), 'version' => '2c596ce1f8051d99b271');
--- a/wp-event-solution/build/js/feedback-modal.asset.php
+++ b/wp-event-solution/build/js/feedback-modal.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'wp-element', 'wp-i18n'), 'version' => 'd35bbec623082359fcdf');
+<?php return array('dependencies' => array('react', 'wp-element', 'wp-i18n'), 'version' => '6402b995e2b7e1ecd469');
--- a/wp-event-solution/build/js/gutenberg-blocks.asset.php
+++ b/wp-event-solution/build/js/gutenberg-blocks.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-data', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n', 'wp-primitives', 'wp-server-side-render'), 'version' => '2f7b47441cac65cc371e');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-data', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n', 'wp-primitives', 'wp-server-side-render'), 'version' => '8079282a46951db576ac');
--- a/wp-event-solution/build/js/i18n-loader.asset.php
+++ b/wp-event-solution/build/js/i18n-loader.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('wp-i18n'), 'version' => '8c994aa33ece729f1210');
+<?php return array('dependencies' => array('wp-i18n'), 'version' => '9ce615c290f8bfeb17c9');
--- a/wp-event-solution/build/js/index-ai-script.asset.php
+++ b/wp-event-solution/build/js/index-ai-script.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react'), 'version' => 'cd82cdece798591ada85');
+<?php return array('dependencies' => array('react'), 'version' => '16712e0496a912904e3d');
--- a/wp-event-solution/build/js/index-calendar.asset.php
+++ b/wp-event-solution/build/js/index-calendar.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('moment', 'react', 'react-dom', 'wp-element', 'wp-html-entities', 'wp-i18n'), 'version' => 'bc3f68215820d1a172a9');
+<?php return array('dependencies' => array('moment', 'react', 'react-dom', 'wp-element', 'wp-html-entities', 'wp-i18n'), 'version' => 'd1fe6522b25f4851cd69');
--- a/wp-event-solution/build/js/index-onboard.asset.php
+++ b/wp-event-solution/build/js/index-onboard.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-compose', 'wp-dom-ready', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n'), 'version' => '26cd550ab841df254349');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-compose', 'wp-dom-ready', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n'), 'version' => 'da22aef3eba1f0dd9f84');
--- a/wp-event-solution/build/js/module-purchase.asset.php
+++ b/wp-event-solution/build/js/module-purchase.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('moment', 'react', 'react-dom', 'wp-api-fetch', 'wp-block-editor', 'wp-block-library', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-dom-ready', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n', 'wp-keyboard-shortcuts', 'wp-media-utils', 'wp-primitives', 'wp-url'), 'version' => '6abaa8bd1fe6a5c4b77d');
+<?php return array('dependencies' => array('moment', 'react', 'react-dom', 'wp-api-fetch', 'wp-block-editor', 'wp-block-library', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-dom-ready', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n', 'wp-keyboard-shortcuts', 'wp-media-utils', 'wp-primitives', 'wp-url'), 'version' => '8717f450baced0cc6600');
--- a/wp-event-solution/build/js/packages.asset.php
+++ b/wp-event-solution/build/js/packages.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('moment', 'react', 'react-dom', 'wp-api-fetch', 'wp-block-editor', 'wp-block-library', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n', 'wp-keyboard-shortcuts', 'wp-media-utils', 'wp-primitives', 'wp-url'), 'version' => '3fb5e8fdd9b27aa1b868');
+<?php return array('dependencies' => array('moment', 'react', 'react-dom', 'wp-api-fetch', 'wp-block-editor', 'wp-block-library', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n', 'wp-keyboard-shortcuts', 'wp-media-utils', 'wp-primitives', 'wp-url'), 'version' => '7f28a0ffe06f1d2d8e5c');
--- a/wp-event-solution/build/js/template-builder-header-toolbar.asset.php
+++ b/wp-event-solution/build/js/template-builder-header-toolbar.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-api-fetch', 'wp-compose', 'wp-data', 'wp-edit-post', 'wp-element', 'wp-html-entities', 'wp-i18n', 'wp-plugins', 'wp-url'), 'version' => '39b2615bc7c8734ddc3f');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-api-fetch', 'wp-compose', 'wp-data', 'wp-edit-post', 'wp-element', 'wp-html-entities', 'wp-i18n', 'wp-plugins', 'wp-url'), 'version' => 'd3c07cb6986e09917de1');
--- a/wp-event-solution/core/Attendee/Api/AttendeeController.php
+++ b/wp-event-solution/core/Attendee/Api/AttendeeController.php
@@ -497,6 +497,20 @@
);
}
+ $attendee_details = $attendee->get_data();
+ $ticket_slug = $attendee_details['ticket_slug'] ?? '';
+ $event_id = $attendee_details['etn_event_id'] ?? '';
+
+ if (!empty($ticket_slug) && !empty($event_id)) {
+ $formatted_booked_tickets[] = [
+ 'ticket_slug' => $ticket_slug,
+ 'ticket_quantity' => 1
+ ];
+
+ EtnUtilsHelper::decrease_count_by_ticket_slug($formatted_booked_tickets, $event_id);
+ }
+
+
do_action( 'eventin_attendee_deleted', $id );
return $response;
@@ -526,8 +540,22 @@
if ( $attendee->trash_post() ) {
$count++;
-
- do_action( 'eventin_attendee_deleted', $id );
+
+ $attendee_details = $attendee->get_data();
+ $ticket_slug = $attendee_details['ticket_slug'] ?? '';
+ $event_id = $attendee_details['etn_event_id'] ?? '';
+
+ if (!empty($ticket_slug) && !empty($event_id)) {
+ $formatted_booked_tickets = [];
+ $formatted_booked_tickets[] = [
+ 'ticket_slug' => $ticket_slug,
+ 'ticket_quantity' => 1
+ ];
+
+ EtnUtilsHelper::decrease_count_by_ticket_slug($formatted_booked_tickets, $event_id);
+ }
+
+ do_action('eventin_attendee_deleted', $id);
}
}
@@ -976,4 +1004,4 @@
return $response;
}
-}
+}
No newline at end of file
--- a/wp-event-solution/core/Attendee/attendee-model.php
+++ b/wp-event-solution/core/Attendee/attendee-model.php
@@ -70,10 +70,10 @@
*
* @return array
*/
- public function get_attendees_by( $key, $value ) {
+ public function get_attendees_by( $key, $value, $post_status = ['publish', 'trash'] ) {
$args = [
'post_type' => 'etn-attendee',
- 'post_status' => ['publish', 'trash'],
+ 'post_status' => $post_status,
'posts_per_page' => -1,
'meta_query' => [
[
--- a/wp-event-solution/core/Emails/AdminEventReminderEmail.php
+++ b/wp-event-solution/core/Emails/AdminEventReminderEmail.php
@@ -82,9 +82,10 @@
// Format date and time according to WordPress settings
$date_format = get_option( 'date_format' );
$time_format = get_option( 'time_format' );
- $start_date = wp_date( $date_format, strtotime( $event->etn_start_date ) );
+ $utc = new DateTimeZone( 'UTC' );
+ $start_date = wp_date( $date_format, strtotime( $event->etn_start_date ), $utc );
$start_date_time = $event->etn_start_date . ' ' . $event->etn_start_time;
- $start_time = wp_date( $time_format, strtotime( $start_date_time ) );
+ $start_time = wp_date( $time_format, strtotime( $start_date_time ), $utc );
$placeholder = [
'{%site_name%}' => get_bloginfo( 'name' ),
--- a/wp-event-solution/core/Emails/AdminOrderEmail.php
+++ b/wp-event-solution/core/Emails/AdminOrderEmail.php
@@ -95,9 +95,10 @@
// Format date and time according to WordPress settings
$date_format = get_option( 'date_format' );
$time_format = get_option( 'time_format' );
- $start_date = wp_date( $date_format, strtotime( $event->etn_start_date ) );
+ $utc = new DateTimeZone( 'UTC' );
+ $start_date = wp_date( $date_format, strtotime( $event->etn_start_date ), $utc );
$start_date_time = $event->etn_start_date . ' ' . $event->etn_start_time;
- $start_time = wp_date( $time_format, strtotime( $start_date_time ) );
+ $start_time = wp_date( $time_format, strtotime( $start_date_time ), $utc );
$placeholder = [
'{%site_name%}' => get_bloginfo( 'name' ),
--- a/wp-event-solution/core/Emails/AdminRsvpEmail.php
+++ b/wp-event-solution/core/Emails/AdminRsvpEmail.php
@@ -82,9 +82,10 @@
// Format date and time according to WordPress settings
$date_format = get_option( 'date_format' );
$time_format = get_option( 'time_format' );
- $start_date = wp_date( $date_format, strtotime( $event->etn_start_date ) );
+ $utc = new DateTimeZone( 'UTC' );
+ $start_date = wp_date( $date_format, strtotime( $event->etn_start_date ), $utc );
$start_date_time = $event->etn_start_date . ' ' . $event->etn_start_time;
- $start_time = wp_date( $time_format, strtotime( $start_date_time ) );
+ $start_time = wp_date( $time_format, strtotime( $start_date_time ), $utc );
$placeholder = [
'{%site_name%}' => get_bloginfo( 'name' ),
--- a/wp-event-solution/core/Emails/AttendeeCertificateEmail.php
+++ b/wp-event-solution/core/Emails/AttendeeCertificateEmail.php
@@ -87,9 +87,10 @@
// Format date and time according to WordPress settings
$date_format = get_option( 'date_format' );
$time_format = get_option( 'time_format' );
- $start_date = wp_date( $date_format, strtotime( $event->etn_start_date ) );
+ $utc = new DateTimeZone( 'UTC' );
+ $start_date = wp_date( $date_format, strtotime( $event->etn_start_date ), $utc );
$start_date_time = $event->etn_start_date . ' ' . $event->etn_start_time;
- $start_time = wp_date( $time_format, strtotime( $start_date_time ) );
+ $start_time = wp_date( $time_format, strtotime( $start_date_time ), $utc );
$placeholder = [
'{%site_name%}' => get_bloginfo( 'name' ),
--- a/wp-event-solution/core/Emails/AttendeeEventReminderEmail.php
+++ b/wp-event-solution/core/Emails/AttendeeEventReminderEmail.php
@@ -83,9 +83,10 @@
// Format date and time according to WordPress settings
$date_format = get_option( 'date_format' );
$time_format = get_option( 'time_format' );
- $start_date = wp_date( $date_format, strtotime( $event->etn_start_date ) );
+ $utc = new DateTimeZone( 'UTC' );
+ $start_date = wp_date( $date_format, strtotime( $event->etn_start_date ), $utc );
$start_date_time = $event->etn_start_date . ' ' . $event->etn_start_time;
- $start_time = wp_date( $time_format, strtotime( $start_date_time ) );
+ $start_time = wp_date( $time_format, strtotime( $start_date_time ), $utc );
$placeholder = [
'{%site_name%}' => get_bloginfo( 'name' ),
--- a/wp-event-solution/core/Emails/AttendeeOrderEmail.php
+++ b/wp-event-solution/core/Emails/AttendeeOrderEmail.php
@@ -87,9 +87,10 @@
// Format date and time according to WordPress settings
$date_format = get_option( 'date_format' );
$time_format = get_option( 'time_format' );
- $start_date = wp_date( $date_format, strtotime( $event->etn_start_date ) );
+ $utc = new DateTimeZone( 'UTC' );
+ $start_date = wp_date( $date_format, strtotime( $event->etn_start_date ), $utc );
$start_date_time = $event->etn_start_date . ' ' . $event->etn_start_time;
- $start_time = wp_date( $time_format, strtotime( $start_date_time ) );
+ $start_time = wp_date( $time_format, strtotime( $start_date_time ), $utc );
$placeholder = [
'{%site_name%}' => get_bloginfo( 'name' ),
--- a/wp-event-solution/core/Emails/AttendeeRsvpEmail.php
+++ b/wp-event-solution/core/Emails/AttendeeRsvpEmail.php
@@ -82,9 +82,10 @@
// Format date and time according to WordPress settings
$date_format = get_option( 'date_format' );
$time_format = get_option( 'time_format' );
- $start_date = wp_date( $date_format, strtotime( $event->etn_start_date ) );
+ $utc = new DateTimeZone( 'UTC' );
+ $start_date = wp_date( $date_format, strtotime( $event->etn_start_date ), $utc );
$start_date_time = $event->etn_start_date . ' ' . $event->etn_start_time;
- $start_time = wp_date( $time_format, strtotime( $start_date_time ) );
+ $start_time = wp_date( $time_format, strtotime( $start_date_time ), $utc );
$placeholder = [
'{%site_name%}' => get_bloginfo( 'name' ),
--- a/wp-event-solution/core/Order/OrderController.php
+++ b/wp-event-solution/core/Order/OrderController.php
@@ -373,8 +373,8 @@
return new WP_Error( 'invalid_data', __( 'Invalid event ID or seat IDs.', 'eventin' ), ['status' => 400] );
}
- $event_tickets = maybe_unserialize( get_post_meta( $event_id, 'etn_ticket_variations', true ) );
- $pending_seats = maybe_unserialize( get_post_meta( $event_id, 'pending_seats', true ));
+ $event_tickets = etn_safe_decode( get_post_meta( $event_id, 'etn_ticket_variations', true ) );
+ $pending_seats = etn_safe_decode( get_post_meta( $event_id, 'pending_seats', true ));
if(empty($pending_seats)){
$pending_seats = [];
}
@@ -490,9 +490,9 @@
}
$id = intval( $request['id'] );
- $seat_ids = maybe_unserialize(get_post_meta($id, 'seat_ids', true));
+ $seat_ids = etn_safe_decode(get_post_meta($id, 'seat_ids', true));
$event_id = get_post_meta($id, 'event_id', true);
- $tickets = maybe_unserialize(get_post_meta($id, 'tickets', true));
+ $tickets = etn_safe_decode(get_post_meta($id, 'tickets', true));
if ( $status === "completed" ) {
if (!empty($seat_ids)) {
@@ -646,6 +646,21 @@
$order = new OrderModel( $id );
+ if ($order->status) {
+ $booked_tickets = $order->tickets;
+ $formatted_booked_tickets = [];
+ if (!empty($booked_tickets)) {
+ foreach ($booked_tickets as $ticket) {
+ $formatted_booked_tickets[] = [
+ 'ticket_slug' => $ticket['ticket_slug'],
+ 'ticket_quantity' => $ticket['ticket_quantity']
+ ];
+ }
+ }
+
+ EtnUtilsHelper::decrease_count_by_ticket_slug($formatted_booked_tickets, $order->event_id);
+ }
+
$previous = $this->prepare_item_for_response( $order, $request );
do_action( 'eventin_order_before_delete', $order );
@@ -692,7 +707,20 @@
foreach ( $ids as $id ) {
$order = new OrderModel( $id );
-
+
+ $booked_tickets = $order->tickets;
+ $formatted_booked_tickets = [];
+ if (!empty($booked_tickets)) {
+ foreach ($booked_tickets as $ticket) {
+ $formatted_booked_tickets[] = [
+ 'ticket_slug' => $ticket['ticket_slug'],
+ 'ticket_quantity' => $ticket['ticket_quantity']
+ ];
+ }
+ }
+
+ EtnUtilsHelper::decrease_count_by_ticket_slug($formatted_booked_tickets, $order->event_id);
+
do_action( 'eventin_order_before_delete', $order );
if ( $order->delete() ) {
@@ -924,6 +952,7 @@
'etn_event_id' => $event_id,
'etn_status' => '',
'ticket_name' => $ticket['etn_ticket_name'],
+ 'ticket_slug' => $ticket_slug,
'etn_ticket_price' => $ticket['etn_ticket_price'],
'etn_info_edit_token' => md5( $ticket['etn_ticket_name'] ),
'etn_unique_ticket_id' => substr(md5($ticket['etn_ticket_price']), 0, 10),
--- a/wp-event-solution/core/Order/OrderExporter.php
+++ b/wp-event-solution/core/Order/OrderExporter.php
@@ -85,7 +85,7 @@
$total_tax = floatval(get_post_meta( $order->id, 'tax_total', true ));
$total_discount = floatval(get_post_meta( $order->id, 'discount_total', true ));
$tax_display_mode = get_post_meta( $order->id, 'tax_display_mode', true );
- $extra_fields = json_encode(maybe_unserialize(get_post_meta( $order->id, 'extra_fields', true )));
+ $extra_fields = json_encode(etn_safe_decode(get_post_meta( $order->id, 'extra_fields', true )));
$final_total = $order->total_price - $total_discount;
--- a/wp-event-solution/core/Order/OrderTicket.php
+++ b/wp-event-solution/core/Order/OrderTicket.php
@@ -140,13 +140,13 @@
if ( isset( $event_orders[$event_id] ) ) {
foreach ( $event_orders[$event_id] as $order_id ) {
// Get allocated seats
- $order_seats = maybe_unserialize( get_post_meta( $order_id, 'seat_ids', true ) );
+ $order_seats = etn_safe_decode( get_post_meta( $order_id, 'seat_ids', true ) );
if ( is_array( $order_seats ) && ! empty( $order_seats ) ) {
$allocated_seats = array_merge( $allocated_seats, $order_seats );
}
// Get allocated tickets
- $order_tickets = maybe_unserialize( get_post_meta( $order_id, 'tickets', true ) );
+ $order_tickets = etn_safe_decode( get_post_meta( $order_id, 'tickets', true ) );
if ( is_array( $order_tickets ) && ! empty( $order_tickets ) ) {
foreach ( $order_tickets as $ticket ) {
$ticket_slug = $ticket['ticket_slug'];
@@ -165,7 +165,7 @@
}
// Get event's pending seats
- $pending_seats = maybe_unserialize( get_post_meta( $event_id, 'pending_seats', true ) );
+ $pending_seats = etn_safe_decode( get_post_meta( $event_id, 'pending_seats', true ) );
if ( ! is_array( $pending_seats ) ) {
$pending_seats = [];
}
@@ -184,7 +184,7 @@
}
// Get event tickets
- $event_tickets = maybe_unserialize( get_post_meta( $event_id, 'etn_ticket_variations', true ) );
+ $event_tickets = etn_safe_decode( get_post_meta( $event_id, 'etn_ticket_variations', true ) );
if ( is_array( $event_tickets ) ) {
$tickets_updated = false;
@@ -244,7 +244,7 @@
$this->update_booked_seat($event, $order);
$this->update_pending_seat($event, $order);
- $booked_seats = maybe_unserialize(get_post_meta($order->id, 'seat_ids', true));
+ $booked_seats = etn_safe_decode(get_post_meta($order->id, 'seat_ids', true));
$booked_tickets = $order->tickets;
$formatted_booked_tickets = [];
if (!empty($booked_tickets)) {
@@ -335,7 +335,7 @@
return;
}
- $pending_seats = maybe_unserialize(get_post_meta($event->id, 'pending_seats', true));
+ $pending_seats = etn_safe_decode(get_post_meta($event->id, 'pending_seats', true));
if (! is_array($pending_seats)) {
$pending_seats = [];
}
@@ -496,7 +496,7 @@
// Update seat on refunded.
$event_seats = get_post_meta( $event->id, '_etn_seat_unique_id', true );
- $order_seats = maybe_unserialize(get_post_meta( $order->id, 'seat_ids', true ));
+ $order_seats = etn_safe_decode(get_post_meta( $order->id, 'seat_ids', true ));
if ( $order_seats ) {
$event_seats = explode(',', $event_seats );
@@ -653,8 +653,8 @@
* @return void
*/
public function release_held_seats_and_tickets( $event_id, $seat_ids = [], $booked_tickets = [] ) {
- $event_tickets = maybe_unserialize( get_post_meta( $event_id, 'etn_ticket_variations', true ) );
- $pending_seats = maybe_unserialize( get_post_meta( $event_id, 'pending_seats', true ));
+ $event_tickets = etn_safe_decode( get_post_meta( $event_id, 'etn_ticket_variations', true ) );
+ $pending_seats = etn_safe_decode( get_post_meta( $event_id, 'pending_seats', true ));
if ( ! is_array( $pending_seats ) ) {
$pending_seats = [];
--- a/wp-event-solution/core/Reports/OrderReport.php
+++ b/wp-event-solution/core/Reports/OrderReport.php
@@ -68,7 +68,7 @@
*
* @return array
*/
- public static function get_orders( $data = [] ) {
+ public static function get_orders( $data = [], $event_id = null ) {
$input = new Input( $data );
$start_date = $input->get( 'start_date' );
$end_date = $input->get( 'end_date' );
@@ -87,7 +87,14 @@
]
];
- if ( ! current_user_can( 'manage_options' ) ) {
+ if ( ! empty( $event_id ) ) {
+ $args['meta_query'][] = [
+ 'key' => 'event_id',
+ 'value' => $event_id,
+ 'compare' => '=',
+ ];
+ }
+ elseif ( ! current_user_can( 'manage_options' ) ) {
$event = new Event_Model();
$event_ids = $event->get_ids_by_author( get_current_user_id() );
$event_ids = ! empty( $event_ids ) ? $event_ids : '';
--- a/wp-event-solution/core/Reports/RevenueReport.php
+++ b/wp-event-solution/core/Reports/RevenueReport.php
@@ -18,29 +18,29 @@
*
* @return number
*/
- public static function get_total_revenue( $dates = [] ) {
+ public static function get_total_revenue( $dates = [], $event_id = null ) {
$total = 0;
- $orders = OrderReport::get_orders( $dates );
+ $order_ids = OrderReport::get_orders( $dates, $event_id );
- if ( $orders ) {
- foreach( $orders as $order_id ) {
- $order = new OrderModel( $order_id );
- $total_price = floatval($order->total_price);
-
- $raw_discount = $order->discount_total;
- $float_discount = floatval($raw_discount);
-
- $raw_tax = $order->tax_total;
- $float_tax = floatval($raw_tax);
-
- // Check WooCommerce tax display setting
- $tax_display_mode = get_option( 'woocommerce_tax_display_shop' );
-
- if ( $tax_display_mode === 'incl' ) {
- $total += $total_price - $float_discount;
- } else {
- $total += $total_price - $float_discount + $float_tax;
- }
+ if ( empty( $order_ids ) ) {
+ return $total;
+ }
+
+ // Batch-load all order meta in a single query
+ update_meta_cache( 'post', $order_ids );
+
+ // Get tax display mode once, outside the loop
+ $tax_display_mode = get_option( 'woocommerce_tax_display_shop' );
+
+ foreach ( $order_ids as $order_id ) {
+ $total_price = floatval( get_post_meta( $order_id, 'total_price', true ) );
+ $float_discount = floatval( get_post_meta( $order_id, 'discount_total', true ) );
+ $float_tax = floatval( get_post_meta( $order_id, 'tax_total', true ) );
+
+ if ( $tax_display_mode === 'incl' ) {
+ $total += $total_price - $float_discount;
+ } else {
+ $total += $total_price - $float_discount + $float_tax;
}
}
--- a/wp-event-solution/core/Upgrade/Upgraders/V_4_0_0.php
+++ b/wp-event-solution/core/Upgrade/Upgraders/V_4_0_0.php
@@ -126,7 +126,7 @@
'rsvp_attendee_form_limit' => get_post_meta( $event_id, 'etn_rsvp_attendee_form_limit', true ),
'rsvp_miminum_attendee_to_start' => get_post_meta( $event_id, 'etn_rsvp_miminum_attendee_to_start', true ),
'show_rsvp_attendee' => get_post_meta( $event_id, 'etn_show_rsvp_attendee', true ),
- 'rsvp_form_type' => maybe_unserialize( get_post_meta( $event_id, 'etn_rsvp_form_type', true ) ),
+ 'rsvp_form_type' => etn_safe_decode( get_post_meta( $event_id, 'etn_rsvp_form_type', true ) ),
];
return $rsvp;
--- a/wp-event-solution/core/Upgrade/Upgraders/V_4_0_9.php
+++ b/wp-event-solution/core/Upgrade/Upgraders/V_4_0_9.php
@@ -64,7 +64,7 @@
'payment_method' => $payment_method,
'status' => $status,
'user_id' => $report->user_id,
- 'tickets' => $this->prepare_tickets(maybe_unserialize($report->ticket_variations) ),
+ 'tickets' => $this->prepare_tickets(etn_safe_decode($report->ticket_variations) ),
'total_price' => $report->event_amount,
];
--- a/wp-event-solution/core/event/Api/CategoryController.php
+++ b/wp-event-solution/core/event/Api/CategoryController.php
@@ -6,6 +6,8 @@
*/
namespace EventinEventCategoryApi;
+use EventinEventCategoryExporter;
+use EventinEventCategoryImporter;
use WP_Error;
use WP_REST_Controller;
use WP_REST_Server;
@@ -91,6 +93,32 @@
),
),
);
+
+ // Export route
+ register_rest_route(
+ $this->namespace,
+ '/' . $this->rest_base . '/export',
+ array(
+ array(
+ 'methods' => WP_REST_Server::CREATABLE,
+ 'callback' => array( $this, 'export_items' ),
+ 'permission_callback' => array( $this, 'export_permissions_check' ),
+ ),
+ ),
+ );
+
+ // Import route
+ register_rest_route(
+ $this->namespace,
+ '/' . $this->rest_base . '/import',
+ array(
+ array(
+ 'methods' => WP_REST_Server::CREATABLE,
+ 'callback' => array( $this, 'import_items' ),
+ 'permission_callback' => array( $this, 'import_permissions_check' ),
+ ),
+ ),
+ );
}
/**
@@ -110,35 +138,67 @@
* @return WP_Error|WP_REST_Response
*/
public function get_items( $request ) {
- $prepared_args = array(
- 'taxonomy' => $this->taxonomy,
- 'hide_empty' => false,
- );
-
- $query_result = get_terms( $prepared_args );
-
- $response = array();
-
- foreach ( $query_result as $term ) {
- $item = $this->prepare_item_for_response( $term->term_id, $request );
-
- // Get the parent term name if the parent term exists
- if ( $term->parent ) {
- $parent_term = get_term( $term->parent, $this->taxonomy );
- if ( ! is_wp_error( $parent_term ) ) {
- $item['parent_name'] = $parent_term->name;
- } else {
- $item['parent_name'] = null; // or some default value
+ $per_page = ! empty( $request['per_page'] ) ? intval( $request['per_page'] ) : 20;
+ $paged = ! empty( $request['paged'] ) ? intval( $request['paged'] ) : 1;
+ $offset = ( $paged - 1 ) * $per_page;
+
+ $prepared_args = array(
+ 'taxonomy' => $this->taxonomy,
+ 'hide_empty' => false,
+ 'number' => $per_page,
+ 'offset' => $offset,
+ );
+
+ // Filter by parent category
+ if ( isset( $request['parent'] ) && $request['parent'] !== '' ) {
+ $prepared_args['parent'] = absint( $request['parent'] );
+ }
+
+ // Filter by search string
+ if ( ! empty( $request['search'] ) ) {
+ $prepared_args['search'] = sanitize_text_field( $request['search'] );
+ }
+
+ $query_result = get_terms( $prepared_args );
+
+ // Get total count for pagination
+ $count_args = $prepared_args;
+ unset( $count_args['number'], $count_args['offset'] );
+ $count_args['fields'] = 'count';
+ $total_items = (int) get_terms( $count_args );
+
+ $items = array();
+
+ if ( ! is_wp_error( $query_result ) ) {
+ foreach ( $query_result as $term ) {
+ $item = $this->prepare_item_for_response( $term->term_id, $request );
+
+ // Get the parent term name if the parent term exists
+ if ( $term->parent ) {
+ $parent_term = get_term( $term->parent, $this->taxonomy );
+ if ( ! is_wp_error( $parent_term ) ) {
+ $item['parent_name'] = $parent_term->name;
+ } else {
+ $item['parent_name'] = null;
+ }
+ } else {
+ $item['parent_name'] = null;
+ }
+
+ $items[] = $item;
}
- } else {
- $item['parent_name'] = null; // or some default value
}
- $response[] = $item;
- }
+ $total_pages = $per_page > 0 ? (int) ceil( $total_items / $per_page ) : 0;
- return rest_ensure_response( $response );
-}
+ $data = [
+ 'total_items' => $total_items,
+ 'items' => $items,
+ ];
+
+ $response = rest_ensure_response( $data );
+ return $response;
+ }
/**
* Get one item from the collection.
@@ -411,4 +471,70 @@
return $prepared_data;
}
+
+ /**
+ * Export categories
+ *
+ * @param WP_REST_Request $request Full data about the request.
+ * @return WP_Error|void
+ */
+ public function export_items( $request ) {
+ $format = ! empty( $request['format'] ) ? sanitize_text_field( $request['format'] ) : '';
+ $ids = ! empty( $request['ids'] ) ? $request['ids'] : '';
+
+ if ( ! $format ) {
+ return new WP_Error( 'format_error', __( 'Invalid data format', 'eventin' ), [ 'status' => 400 ] );
+ }
+
+ if ( ! $ids ) {
+ $ids = CategoryExporter::get_ids();
+ }
+
+ $exporter = new CategoryExporter();
+ $exporter->export( $ids, $format );
+ }
+
+ /**
+ * Check permissions for export categories
+ *
+ * @param WP_REST_Request $request Full data about the request.
+ * @return bool
+ */
+ public function export_permissions_check( $request ) {
+ return current_user_can( 'etn_manage_event' );
+ }
+
+ /**
+ * Import categories
+ *
+ * @param WP_REST_Request $request Full data about the request.
+ * @return WP_Error|WP_REST_Response
+ */
+ public function import_items( $request ) {
+ $data = $request->get_file_params();
+ $file = ! empty( $data['category_import'] ) ? $data['category_import'] : '';
+
+ if ( ! $file ) {
+ return new WP_Error( 'empty_file', __( 'You must provide a valid file.', 'eventin' ), [ 'status' => 409 ] );
+ }
+
+ $importer = new CategoryImporter();
+ $importer->import( $file );
+
+ $response = [
+ 'message' => __( 'Successfully imported categories', 'eventin' ),
+ ];
+
+ return rest_ensure_response( $response );
+ }
+
+ /**
+ * Check permissions for import categories
+ *
+ * @param WP_REST_Request $request Full data about the request.
+ * @return bool
+ */
+ public function import_permissions_check( $request ) {
+ return current_user_can( 'etn_manage_event' );
+ }
}
No newline at end of file
--- a/wp-event-solution/core/event/Api/EventController.php
+++ b/wp-event-solution/core/event/Api/EventController.php
@@ -18,6 +18,7 @@
use WP_REST_Controller;
use WP_REST_Server;
use EtnUtilsHelper;
+use EventinReportsRevenueReport;
use WP_User_Query;
/**
@@ -257,6 +258,20 @@
],
]
);
+
+ register_rest_route(
+ $this->namespace,
+ '/' . $this->rest_base . '/update-status',
+ [
+ [
+ 'methods' => WP_REST_Server::EDITABLE,
+ 'callback' => array($this, 'update_status'),
+ 'permission_callback' => function () {
+ return current_user_can('etn_manage_event');
+ },
+ ],
+ ],
+ );
}
/**
@@ -266,11 +281,11 @@
* @return WP_Error|boolean
*/
public function get_item_permissions_check( $request ) {
- return current_user_can( 'etn_manage_event' ) && wp_verify_nonce( $request->get_header( 'X-Wp-Nonce' ), 'wp_rest' );
+ return current_user_can( 'etn_manage_event' ) || wp_verify_nonce( $request->get_header( 'X-Wp-Nonce' ), 'wp_rest' );
}
public function get_single_item_permissions_check( $request ) {
- return wp_verify_nonce( $request->get_header( 'X-Wp-Nonce' ), 'wp_rest' );
+ return current_user_can( 'etn_manage_event' ) || wp_verify_nonce( $request->get_header( 'X-Wp-Nonce' ), 'wp_rest' );
}
/**
@@ -287,7 +302,11 @@
$end_date = ! empty( $request['end_date'] ) ? sanitize_text_field( $request['end_date'] ) : '';
$search_keyword = ! empty( $request['search_keyword'] ) ? sanitize_text_field( $request['search_keyword'] ) : '';
$status = ! empty( $request['status'] ) ? sanitize_text_field( $request['status'] ) : 'all';
-
+ $category = ! empty( $request['category'] ) ? intval($request['category']): [];
+ $organizer = ! empty( $request['organizer'] ) ? intval($request['organizer']) : [];
+ $speaker = ! empty( $request['speaker'] ) ? intval($request['speaker']) : [];
+ $parent = isset( $request['parent'] ) ? intval( $request['parent'] ) : null;
+
$args = [
'post_type' => 'etn',
'post_status' => 'any',
@@ -295,8 +314,28 @@
'paged' => $paged,
];
+ // Filter by parent event for recurring child events.
+ if ( $parent !== null ) {
+ $args['post_parent'] = $parent;
+ }
+ else{
+ $args['post_parent'] = 0;
+ }
+
if ( ! current_user_can( 'manage_options' ) ) {
- $args['author'] = get_current_user_id();
+ $args['author'] = get_current_user_id();
+ }
+
+ // Category filter (taxonomy query).
+ if ( ! empty( $category ) ) {
+ $args['tax_query'] = [
+ [
+ 'taxonomy' => 'etn_category',
+ 'field' => 'term_id',
+ 'terms' => $category,
+ 'operator' => 'IN',
+ ],
+ ];
}
$meta_query = [];
@@ -306,18 +345,28 @@
'relation' => 'AND',
[
'key' => 'etn_start_date',
- 'value' => $start_date,
- 'compare' => '>=',
- 'type' => 'DATETIME'
+ 'value' => $end_date,
+ 'compare' => '<=',
+ 'type' => 'DATE'
],
[
'key' => 'etn_end_date',
- 'value' => $end_date,
- 'compare' => '<=',
- 'type' => 'DATETIME'
+ 'value' => $start_date,
+ 'compare' => '>=',
+ 'type' => 'DATE'
],
];
}
+
+ if (!empty($type)) {
+ $meta_query[] = [
+ [
+ 'key' => 'event_type',
+ 'value' => $type,
+ 'compare' => '='
+ ]
+ ];
+ }
if ( $search_keyword ) {
$args['s'] = $search_keyword;
@@ -371,7 +420,7 @@
$args['meta_query'] = $meta_query;
}
- if ( $meta_query || $search_keyword || $status ) {
+ if ( $meta_query || $search_keyword || $status || $category || $organizer || $speaker || $parent !== null ) {
return $this->get_event_list( $args, $request );
}
@@ -400,22 +449,62 @@
* @return [type] [return description]
*/
protected function get_event_list( $args, $request ) {
+ $category = ! empty( $request['category'] ) ? intval($request['category']) : [];
+ $organizer = ! empty( $request['organizer'] ) ? intval($request['organizer']) : [];
+ $speaker = ! empty( $request['speaker'] ) ? intval($request['speaker']) : [];
+
$events = [];
$post_query = new WP_Query( $args );
$query_result = $post_query->posts;
$total_posts = $post_query->found_posts;
+ $total_upcomming_events = 0;
+ $total_ongoing_events = 0;
+ $total_expired_events = 0;
foreach ( $query_result as $post ) {
+ $speakers_and_organizers = $this->get_event_organizers_and_speakers($post->ID);
+
+ $speakers = $speakers_and_organizers['speaker'];
+ $organizers = $speakers_and_organizers['organizer'];
+
+ $categories = get_the_terms( $post->ID, 'etn_category' );
+ $categories = $categories ? array_column( $categories, 'term_id' ) : [];
+
+ if (!empty($category) && !in_array($category, $categories)) {
+ continue;
+ }
+ if (!empty($speaker) && !in_array($speaker, $speakers)) {
+ continue;
+ }
+ if (!empty($organizer) && !in_array($organizer, $organizers)) {
+ continue;
+ }
+
$post_data = $this->prepare_item_for_response( $post, $request );
+
+ if(isset($post_data['status'])){
+ if($post_data['status'] == 'Expired'){
+ $total_expired_events = $total_expired_events + 1;
+ }
+ if($post_data['status'] == 'Ongoing'){
+ $total_ongoing_events = $total_ongoing_events + 1;
+ }
+ if($post_data['status'] == 'Upcoming'){
+ $total_upcomming_events = $total_upcomming_events + 1;
+ }
+ }
$events[] = $this->prepare_response_for_collection( $post_data );
}
$data = [
'total_items' => $total_posts,
- 'items' => $events,
+ 'total_expired_events' => $total_expired_events,
+ 'total_ongoing_events' => $total_ongoing_events,
+ 'total_upcomming_events' => $total_upcomming_events,
+ 'items' => $events
];
$response = rest_ensure_response( $data );
@@ -433,10 +522,36 @@
public function get_item( $request ) {
$id = intval( $request['id'] );
$post = get_post( $id );
-
$item = $this->prepare_item_for_response( $post, $request );
+ // Check if event is a recurring event and fetch child events.
+ $recurring_enabled = get_post_meta( $id, 'recurring_enabled', true );
+
+ if ( $recurring_enabled ) {
+ // Prepare request array with parent parameter and pass through other params.
+ $child_request = [
+ 'parent' => $id,
+ 'per_page' => ! empty( $request['per_page'] ) ? $request['per_page'] : 20,
+ 'paged' => ! empty( $request['paged'] ) ? $request['paged'] : 1,
+ 'type' => ! empty( $request['type'] ) ? $request['type'] : '',
+ 'start_date' => ! empty( $request['start_date'] ) ? $request['start_date'] : '',
+ 'end_date' => ! empty( $request['end_date'] ) ? $request['end_date'] : '',
+ 'search_keyword' => ! empty( $request['search_keyword'] ) ? $request['search_keyword'] : '',
+ 'status' => ! empty( $request['status'] ) ? $request['status'] : 'all',
+ 'category' => ! empty( $request['category'] ) ? $request['category'] : [],
+ 'organizer' => ! empty( $request['organizer'] ) ? $request['organizer'] : [],
+ 'speaker' => ! empty( $request['speaker'] ) ? $request['speaker'] : [],
+ ];
+
+ $child_response = $this->get_items( $child_request );
+ $child_data = $child_response->get_data();
+
+ $item['recurring_events'] = $child_data;
+ } else {
+ $item['recurring_events'] = null;
+ }
+
$response = rest_ensure_response( $item );
return $response;
@@ -850,15 +965,6 @@
}
/**
- * Get the item's schema for display / public consumption purposes.
- *
- * @return array
- */
- public function get_item_schema() {
-
- }
-
- /**
* Prepare the item for the REST response.
*
* @param mixed $item WordPress representation of the item.
@@ -905,7 +1011,7 @@
$seat_plan = get_post_meta( $id, 'seat_plan', true );
$enable_seatmap = get_post_meta( $id, 'enable_seatmap', true );
$sold_tickets = (array)Helper::etn_get_sold_tickets_by_event( $id );
- $ticket_variations = maybe_unserialize(get_post_meta( $id, 'etn_ticket_variations', true ));
+ $ticket_variations = etn_safe_decode(get_post_meta( $id, 'etn_ticket_variations', true ));
if(empty($ticket_variations) || !is_array($ticket_variations)){
$ticket_variations = [];
@@ -1019,7 +1125,8 @@
'module' => [
'seat_map' => ( EtnCoreAddonsHelper::instance()->check_active_module( 'seat_map' ) ) ? true : false,
'rsvp' => ( EtnCoreAddonsHelper::instance()->check_active_module( 'rsvp' ) ) ? true : false,
- ]
+ ],
+ 'revenue' => RevenueReport::get_total_revenue( [], $id ),
];
$location_type = get_post_meta( $id, 'etn_event_location_type', true );
@@ -1118,7 +1225,15 @@
$user_id = $user->ID;
// Get JSON-decoded group array
- $speaker_group = json_decode(get_user_meta($user_id, 'etn_speaker_group', true));
+ $speaker_group = get_user_meta($user_id, 'etn_speaker_group', true);
+
+ if (!is_array($speaker_group)) {
+ $speaker_group = json_decode($speaker_group);
+ if(!is_array($speaker_group)){
+ $speaker_group = [$speaker_group];
+ }
+ }
+
$speaker_speaker_group = get_user_meta($user_id, 'etn_speaker_speaker_group', true);
// Check if group_id exists in either meta
@@ -1605,7 +1720,7 @@
foreach($event_data['etn_ticket_variations'] as &$ticket){
$ticket['etn_sold_tickets'] = !empty($sold_tickets[$ticket['etn_ticket_slug']]) ? $sold_tickets[$ticket['etn_ticket_slug']] : 0;
$ticket['etn_avaiilable_tickets'] = (int)$ticket['etn_avaiilable_tickets'];
- if($ticket['etn_sold_tickets'] > $ticket['etn_avaiilable_tickets']){
+ if($ticket['etn_avaiilable_tickets'] > 0 && $ticket['etn_sold_tickets'] > $ticket['etn_avaiilable_tickets']){
return new WP_Error( 'etn_ticket_sold_out', 'Available ticket must be greater than the sold ticket' );
}
}
@@ -1874,4 +1989,78 @@
}
return 0;
}
+
+ /**
+ * Update event status
+ *
+ * @param WP_Rest_Request $request [$request description]
+ *
+ * @return WP_Rest_Response | WP_Error
+ */
+ public function update_status($request) {
+ $input_data = is_a($request, 'WP_REST_Request') ? json_decode($request->get_body(), true) : $request;
+
+ $event_ids = !empty($input_data['event_ids']) && is_array($input_data['event_ids']) ? array_map('intval', $input_data['event_ids']) : [];
+ $status = !empty($input_data['status']) ? sanitize_text_field($input_data['status']) : '';
+
+ if (!in_array($status, ['publish', 'draft'])) {
+ return new WP_Error('invalid_status', 'Status must be Publish OR Draft', array('status' => 400));
+ }
+
+ foreach ($event_ids as $event_id) {
+ $event = get_post($event_id);
+ if (!$event || $event->post_type !== 'etn') {
+ return new WP_Error(
+ 'invalid_event',
+ __('Invalid event ID.', 'eventin'),
+ ['status' => 404]
+ );
+ }
+
+ $result = wp_update_post([
+ 'ID' => $event_id,
+ 'post_status' => $status
+ ]);
+
+ if (is_wp_error($result)) {
+ return new WP_Error(
+ 'update_failed',
+ __('Failed to update event status.', 'eventin'),
+ ['status' => 500]
+ );
+ }
+ }
+
+ return rest_ensure_response([
+ 'success' => true,
+ 'message' => __('Event status updated successfully.', 'eventin'),
+ ]);
+ }
+
+ public function get_event_organizers_and_speakers($event_id){
+ $event = new Event_Model( $event_id );
+ $organizer = array_map( function( $org ) { return (int) $org; }, get_post_meta( $event_id, 'etn_event_organizer', true ) ?: [] );
+ $speaker = get_post_meta( $event_id, 'etn_event_speaker', true );
+
+
+ $organizer_group = get_post_meta( $event_id, 'organizer_group', true );
+ $speaker_group = get_post_meta( $event_id, 'speaker_group', true );
+
+
+
+ $speaker_type = get_post_meta( $event_id, 'speaker_type', true );
+ $organizer_type = get_post_meta( $event_id, 'organizer_type', true );
+
+ if($speaker_type == 'group'){
+ $speaker = $this->etn_get_user_ids_by_group($speaker_group);
+ }
+
+ if($organizer_type == 'group'){
+ $organizer = $this->etn_get_user_ids_by_group($organizer_group);
+ }
+
+ $filter_user = $this->filter_organizer_and_speaker($organizer, $speaker);
+
+ return $filter_user;
+ }
}
--- a/wp-event-solution/core/event/Api/EventTagController.php
+++ b/wp-event-solution/core/event/Api/EventTagController.php
@@ -6,6 +6,8 @@
*/
namespace EventinEventApi;
+use EventinEventEventTagExporter;
+use EventinEventEventTagImporter;
use WP_Error;
use WP_REST_Controller;
use WP_REST_Server;
@@ -91,6 +93,22 @@
),
),
);
+
+ register_rest_route( $this->namespace, $this->rest_base . '/export', [
+ [
+ 'methods' => WP_REST_Server::CREATABLE,
+ 'callback' => [ $this, 'export_items' ],
+ 'permission_callback' => [ $this, 'export_item_permissions_check' ],
+ ]
+ ] );
+
+ register_rest_route( $this->namespace, $this->rest_base . '/import', [
+ [
+ 'methods' => WP_REST_Server::CREATABLE,
+ 'callback' => [ $this, 'import_items' ],
+ 'permission_callback' => [ $this, 'import_item_permissions_check' ],
+ ]
+ ] );
}
/**
@@ -110,19 +128,51 @@
* @return WP_Error|WP_REST_Response
*/
public function get_items( $request ) {
+ $per_page = isset( $request['per_page'] ) ? absint( $request['per_page'] ) : 10;
+ $page = isset( $request['paged'] ) ? absint( $request['paged'] ) : 1;
+ $search = isset( $request['search'] ) ? sanitize_text_field( $request['search'] ) : '';
+
$prepared_args = array(
'taxonomy' => $this->taxonomy,
'hide_empty' => false,
+ 'number' => $per_page,
+ 'offset' => ( $page - 1 ) * $per_page,
);
+ if ( ! empty( $search ) ) {
+ $prepared_args['search'] = $search;
+ }
+
$query_result = get_terms( $prepared_args );
- $response = array();
+ $items = array();
- foreach ( $query_result as $term ) {
- $response[] = $this->prepare_item_for_response( $term->term_id, $request );
+ if ( ! is_wp_error( $query_result ) ) {
+ foreach ( $query_result as $term ) {
+ $items[] = $this->prepare_item_for_response( $term->term_id, $request );
+ }
}
+ $total_args = array(
+ 'taxonomy' => $this->taxonomy,
+ 'hide_empty' => false,
+ 'fields' => 'count',
+ );
+
+ if ( ! empty( $search ) ) {
+ $total_args['search'] = $search;
+ }
+
+ $total = get_terms( $total_args );
+
+ $response = array(
+ 'items' => $items,
+ 'total' => $total,
+ 'total_pages' => ceil( $total / $per_page ),
+ 'page' => $page,
+ 'per_page' => $per_page,
+ );
+
return rest_ensure_response( $response );
}
@@ -385,4 +435,74 @@
return $prepared_data;
}
+
+ /**
+ * Export items
+ *
+ * @param WP_REST_Request $request Full data about the request.
+ * @return WP_Error|void
+ */
+ public function export_items( $request ) {
+ $format = ! empty( $request['format'] ) ? sanitize_text_field( $request['format'] ) : '';
+ $ids = ! empty( $request['ids'] ) ? $request['ids'] : '';
+
+ if ( ! $format ) {
+ return new WP_Error( 'format_error', __( 'Invalid data format', 'eventin' ));
+ }
+
+ if ( ! $ids ) {
+ $ids = EventTagExporter::get_ids();
+ }
+
+ $exporter = new EventTagExporter();
+ $response = $exporter->export( $ids, $format );
+
+ if ( is_wp_error( $response ) ) {
+ return $response;
+ }
+ }
+
+ /**
+ * Check the permissions for export items
+ *
+ * @param WP_REST_Request $request Full data about the request.
+ * @return bool
+ */
+ public function export_item_permissions_check( $request ) {
+ return current_user_can( 'etn_manage_event' );
+ }
+
+ /**
+ * Import items
+ *
+ * @param WP_REST_Request $request Full data about the request.
+ * @return WP_Error|WP_REST_Response
+ */
+ public function import_items( $request ) {
+ $data = $request->get_file_params();
+ $file = ! empty( $data['tag_import'] ) ? $data['tag_import'] : '';
+
+ if ( ! $file ) {
+ return new WP_Error( 'empty_file', __( 'You must provide a valid file.', 'eventin' ), [ 'status' => 409 ] );
+ }
+
+ $importer = new EventTagImporter();
+ $importer->import( $file );
+
+ $response = [
+ 'message' => __( 'Successfully imported tags', 'eventin' ),
+ ];
+
+ return rest_ensure_response( $response );
+ }
+
+ /**
+ * Check permission for the import tags
+ *
+ * @param WP_REST_Request $request Full data about the request.
+ * @return bool
+ */
+ public function import_item_permissions_check( $request ) {
+ return current_user_can( 'etn_manage_event' );
+ }
}
--- a/wp-event-solution/core/event/Api/TransactionController.php
+++ b/wp-event-solution/core/event/Api/TransactionController.php
@@ -330,7 +330,7 @@
'invoice' => $item->invoice,
'amount' => $item->event_amount,
'ticket_quantity' => $item->ticket_qty,
- 'ticket_variations' => maybe_unserialize( $item->ticket_variations ),
+ 'ticket_variations' => etn_safe_decode( $item->ticket_variations ),
];
return $transaction_data;
--- a/wp-event-solution/core/event/CategoryExporter.php
+++ b/wp-event-solution/core/event/CategoryExporter.php
@@ -0,0 +1,132 @@
+<?php
+/**
+ * Category Exporter Class
+ *
+ * @package Eventin
+ */
+namespace EventinEvent;
+
+use EventinExporterExporterFactory;
+use EventinExporterPostExporterInterface;
+
+/**
+ * Class Category Exporter
+ *
+ * Export Category Data
+ */
+class CategoryExporter implements PostExporterInterface {
+ /**
+ * Store file name
+ *
+ * @var string
+ */
+ private $file_name = 'category-data';
+
+ /**
+ * Store category data
+ *
+ * @var array
+ */
+ private $data;
+
+ /**
+ * Taxonomy key
+ *
+ * @var string
+ */
+ private $taxonomy = 'etn_category';
+
+ /**
+ * Export category data
+ *
+ * @param array $data Category IDs to export
+ * @param string $format Export format (csv, json)
+ *
+ * @return void
+ */
+ public function export( $data, $format ) {
+ $this->data = $data;
+
+ $rows = $this->prepare_data();
+ $columns = $this->get_columns();
+ $file_name = $this->file_name;
+
+ $exporter = ExporterFactory::get_exporter( $format );
+
+ $exporter->export( $rows, $columns, $file_name );
+ }
+
+ /**
+ * Prepare data to export
+ *
+ * @return array
+ */
+ private function prepare_data() {
+ $ids = $this->data;
+ $exported_data = [];
+
+ foreach ( $ids as $id ) {
+ $term = get_term( $id, $this->taxonomy );
+
+ if ( is_wp_error( $term ) || ! $term ) {
+ continue;
+ }
+
+ $parent_name = '';
+ if ( $term->parent ) {
+ $parent_term = get_term( $term->parent, $this->taxonomy );
+ if ( ! is_wp_error( $parent_term ) && $parent_term ) {
+ $parent_name = $parent_term->name;
+ }
+ }
+
+ $category_data = [
+ 'id' => $term->term_id,
+ 'name' => $term->name,
+ 'slug' => $term->slug,
+ 'description' => $term->description,
+ 'parent' => $term->parent,
+ 'parent_name' => $parent_name,
+ 'color' => get_term_meta( $term->term_id, 'color', true ),
+ 'count' => $term->count,
+ ];
+
+ array_push( $exported_data, $category_data );
+ }
+
+ return $exported_data;
+ }
+
+ /**
+ * Get columns
+ *
+ * @return array
+ */
+ private function get_columns() {
+ return [
+ 'id' => __( 'ID', 'eventin' ),
+ 'name' => __( 'Name', 'eventin' ),
+ 'slug' => __( 'Slug', 'eventin' ),
+ 'description' => __( 'Description', 'eventin' ),
+ 'parent' => __( 'Parent ID', 'eventin' ),
+ 'parent_name' => __( 'Parent Name', 'eventin' ),
+ 'color' => __( 'Color', 'eventin' ),
+ 'count' => __( 'Event Count', 'eventin' ),
+ ];
+ }
+
+ /**
+ * Get all category IDs
+ *
+ * @return array
+ */
+ public static function get_ids() {
+ $terms = get_terms( [
+ 'taxonomy' => 'etn_category',
+ 'hide_empty' => false,
+ 'fields' => 'ids',
+ ] );
+
+ return ! is_wp_error( $terms ) ? $terms : [];
+ }
+}
--- a/wp-event-solution/core/event/CategoryImporter.php
+++ b/wp-event-solution/core/event/CategoryImporter.php
@@ -0,0 +1,141 @@
+<?php
+/**
+ * Category Importer Class
+ *
+ * @package Eventin
+ */
+namespace EventinEvent;
+
+use EventinImporterPostImporterInterface;
+use EventinImporterReaderFactory;
+
+/**
+ * Class Category Importer
+ */
+class CategoryImporter implements PostImporterInterface {
+ /**
+ * Store File
+ *
+ * @var array
+ */
+ private $file;
+
+ /**
+ * Store data
+ *
+ * @var array
+ */
+ private $data;
+
+ /**
+ * Taxonomy key
+ *
+ * @var string
+ */
+ private $taxonomy = 'etn_category';
+
+ /**
+ * Category import
+ *
+ * @param array $file Uploaded file data
+ *
+ * @return void
+ */
+ public function import( $file ) {
+ $this->file = $file;
+ $file_reader = ReaderFactory::get_reader( $file );
+
+ $this->data = $file_reader->read_file();
+ $this->create_categories();
+ }
+
+ /**
+ * Create categories
+ *
+ * @return void
+ */
+ private function create_categories() {
+ $rows = $this->data;
+
+ // First pass: Create all categories without parent relationships
+ $id_mapping = [];
+
+ foreach ( $rows as $row ) {
+ $name = ! empty( $row['name'] ) ? sanitize_text_field( $row['name'] ) : '';
+ $slug = ! empty( $row['slug'] ) ? sanitize_title( $row['slug'] ) : '';
+ $description = ! empty( $row['description'] ) ? sanitize_textarea_field( $row['description'] ) : '';
+ $color = ! empty( $row['color'] ) ? sanitize_hex_color( $row['color'] ) : '';
+ $old_id = ! empty( $row['id'] ) ? intval( $row['id'] ) : 0;
+
+ if ( empty( $name ) ) {
+ continue;
+ }
+
+ // Check if term already exists
+ $existing_term = term_exists( $name, $this->taxonomy );
+
+ if ( $existing_term ) {
+ $term_id = $existing_term['term_id'];
+
+ // Update existing term
+ wp_update_term( $term_id, $this->taxonomy, [
+ 'slug' => $slug,
+ 'description' => $description,
+ ] );
+ } else {
+ // Create new term
+